@aurora/schema (0.3.3)
Published 2025-12-27 10:44:40 +00:00 by vlad
Installation
@aurora:registry=npm install @aurora/schema@0.3.3"@aurora/schema": "0.3.3"About this package
@aurora/schema
Schema DSL for defining events, projections, APIs, and authorization rules in Aurora applications.
Overview
Aurora uses a schema-first approach where you define your domain in TypeScript, and the framework generates type-safe code from these definitions.
This package provides:
- Event Schema DSL - Define domain events with versioning and sharding
- Projection Schema DSL - Define read models and their storage
- API Schema DSL - Define REST endpoints with validation and auth
- Auth Schema DSL - Define authorization rules (RBAC/ABAC)
- Type Builder - Runtime type system based on Zod
Installation
bun add @aurora/schema
Event Schema DSL
Define domain events with versioning and sharding keys:
import { events } from "@aurora/schema";
export const orderEvents = events.define({
OrderCreated: {
version: 1,
shardingKey: "payload.tenantId",
payload: (t) => t.object({
tenantId: t.string(),
orderId: t.string(),
userId: t.string(),
amount: t.number(),
currency: t.string(),
createdAt: t.string(),
}),
},
OrderUpdated: {
version: 1,
shardingKey: "payload.tenantId",
payload: (t) => t.object({
tenantId: t.string(),
orderId: t.string(),
amount: t.number().nullable(),
currency: t.string().nullable(),
}),
},
} as const);
Type Builder
The t parameter provides type constructors:
// Primitives
t.string()
t.number()
t.boolean()
t.any()
// Modifiers
t.nullable(inner)
t.optional(inner)
// Complex
t.object({ ... })
t.array(inner)
t.tuple([t1, t2, t3])
// String constraints
.string().min(1)
.string().max(100)
.string().length(10)
.string().email()
.string().url()
.string().uuid()
// Number constraints
.number().min(0)
.number().max(100)
// Enums and literals
t.enum(["active", "inactive"])
t.literal("success")
Projection Schema DSL
Define read models with storage configuration:
import { projections } from "@aurora/schema";
import { orderEvents } from "./events.schema";
export const orderProjections = projections.define(orderEvents, {
OrderReadModel: (p) => p.hot({
tenantKey: "tenantId",
key: (t) => t.object({
tenantId: t.string(),
orderId: t.string(),
}),
value: (t) => t.object({
tenantId: t.string(),
orderId: t.string(),
userId: t.string(),
amount: t.number(),
currency: t.string(),
status: t.string(),
createdAt: t.string(),
updatedAt: t.string().nullable(),
}),
hotRetentionDays: 90,
fromEvents: (e) => ({
OrderCreated: (ev) => ({
tenantId: ev.tenantId,
orderId: ev.orderId,
userId: ev.userId,
amount: ev.amount,
currency: ev.currency,
status: "pending",
createdAt: ev.createdAt,
updatedAt: null,
}),
OrderUpdated: (ev, current) => ({
...current,
amount: ev.amount ?? current.amount,
currency: ev.currency ?? current.currency,
updatedAt: new Date().toISOString(),
}),
}),
}),
OrderHistory: (p) => p.history({
tenantKey: "tenantId",
aggregateKey: "orderId",
hotRetentionDays: 365,
fromEvents: (e) => ({
"*": (ev) => ({
eventType: ev.type,
eventVersion: ev.version,
eventPayload: ev.payload,
occurredAt: ev.occurredAt,
}),
}),
}),
} as const);
Projection Types
- p.hot() - Fast read-optimized storage for current state
- p.history() - Write-optimized storage for complete event history
API Schema DSL
Define REST endpoints with validation and auth:
import { api } from "@aurora/schema";
import { auth } from "@aurora/schema/auth";
export const routes = api.define({
rest: (r) => ({
createOrder: r.post("/api/v1/:tenantId/orders")
.params((t) => t.object({
tenantId: t.string(),
}))
.body((t) => t.object({
userId: t.string(),
amount: t.number().min(0),
currency: t.string().length(3),
}))
.response((t) => t.object({
orderId: t.string(),
}))
.auth(auth.required())
.auth(auth.requireTenantRole(["admin", "user"])),
getOrder: r.get("/api/v1/:tenantId/orders/:orderId")
.params((t) => t.object({
tenantId: t.string(),
orderId: t.string(),
}))
.response((t) => t.object({
orderId: t.string(),
amount: t.number(),
status: t.string(),
}))
.auth(auth.required()),
listOrders: r.get("/api/v1/:tenantId/orders")
.params((t) => t.object({
tenantId: t.string(),
}))
.query((t) => t.object({
status: t.string().optional(),
limit: t.number().min(1).max(100).optional(),
offset: t.number().min(0).optional(),
}))
.response((t) => t.object({
orders: t.array(t.object({
orderId: t.string(),
amount: t.number(),
status: t.string(),
})),
total: t.number(),
}))
.auth(auth.required()),
}),
} as const);
HTTP Methods
r.get(path) // GET request
r.post(path) // POST request
r.put(path) // PUT request
r.patch(path) // PATCH request
r.delete(path) // DELETE request
Auth Rules
import { auth } from "@aurora/schema/auth";
// Authentication
auth.required() // Require authenticated user
auth.optional() // Optional authentication
auth.none() // No authentication required
// Authorization
auth.requireTenantRole(["admin", "user"])
auth.requireTenantPermission(["read:orders", "write:orders"])
auth.requireTenantAttributeIn("tier", ["gold", "platinum"])
Pages Schema DSL
Define SSR pages with validation:
import { pages } from "@aurora/schema";
export const pageRoutes = pages.define({
dashboard: (p) => p.page("/dashboard/:tenantId")
.params((t) => t.object({
tenantId: t.string(),
}))
.layout((t) => t.object({
tenantId: t.string(),
})),
} as const);
Type Safety
All schemas generate TypeScript types:
import type {
OrderCreatedPayload,
OrderReadModelKey,
OrderReadModelValue,
CreateOrderParams,
CreateOrderBody,
CreateOrderResponse,
} from "./generated/types";
Integration with Codegen
Use with @aurora/codegen to generate:
- TypeScript types
- Validators (Zod schemas)
- Repository interfaces
- API route handlers
- Projection workers
bun add @aurora/codegen
aurora codegen
API Reference
See docs/schemas.md for complete schema DSL documentation.
License
MIT
Dependencies
Dependencies
| ID | Version |
|---|---|
| zod | ^3.22.4 |