@aurora/codegen (0.3.3)
Published 2025-12-27 10:44:47 +00:00 by vlad
Installation
@aurora:registry=npm install @aurora/codegen@0.3.3"@aurora/codegen": "0.3.3"About this package
@aurora/codegen
Code generation engine for Aurora - generates types, validators, repositories, routers, and SDKs from schemas.
Overview
The codegen package transforms schema definitions into production-ready code:
- TypeScript types from schemas
- Zod validators
- Repository interfaces and implementations
- API route handlers
- Projection workers
- Client SDK (TypeScript)
- React hooks (via @aurora/codegen-react)
- Zustand stores (via @aurora/codegen-zustand)
Installation
bun add -D @aurora/codegen
Usage
import { codegen } from "@aurora/codegen";
import { loadSchemas } from "@aurora/codegen/loader";
// Load schemas from disk
const schemas = await loadSchemas({
pattern: "./schemas/**/*.schema.ts",
});
// Generate code
await codegen(schemas, {
output: "./generated",
codegen: {
react: true,
zustand: false,
client: true,
},
});
CLI Integration
Use via @aurora/cli:
aurora codegen
Generated Files
Types
TypeScript types for all schemas:
// generated/types/events.ts
export interface OrderCreatedPayload {
tenantId: string;
orderId: string;
userId: string;
amount: number;
currency: string;
}
// generated/types/projections.ts
export interface OrderReadModelKey {
tenantId: string;
orderId: string;
}
export interface OrderReadModelValue {
tenantId: string;
orderId: string;
amount: number;
status: string;
}
// generated/types/api.ts
export interface CreateOrderParams {
tenantId: string;
}
export interface CreateOrderBody {
userId: string;
amount: number;
currency: string;
}
export interface CreateOrderResponse {
orderId: string;
}
Validators
Zod validators from type definitions:
// generated/validators/events.ts
export const OrderCreatedSchema = z.object({
tenantId: z.string(),
orderId: z.string(),
userId: z.string(),
amount: z.number(),
currency: z.string(),
});
Repositories
Repository interfaces and implementations:
// generated/repositories/OrderRepository.ts
export interface IOrderRepository {
get(key: OrderReadModelKey): Effect<Env, Error, OrderReadModelValue | null>;
set(key: OrderReadModelKey, value: OrderReadModelValue): Effect<Env, Error, void>;
delete(key: OrderReadModelKey): Effect<Env, Error, void>;
}
export class OrderRepository implements IOrderRepository {
constructor(private storage: Storage) {}
async get(key: OrderReadModelKey) {
return this.storage.get(key);
}
async set(key: OrderReadModelKey, value: OrderReadModelValue) {
return this.storage.set(key, value);
}
async delete(key: OrderReadModelKey) {
return this.storage.delete(key);
}
}
API Handlers
Type-safe HTTP handlers:
// generated/handlers/CreateOrderHandler.ts
export function createOrderHandler(
deps: Dependencies
): Effect<Dependencies, Error, Response> {
return async ({ eventLog, logger }) => {
const { tenantId } = deps.params;
const { userId, amount, currency } = deps.body;
logger.log(`Creating order for tenant ${tenantId}`);
const event = {
type: "OrderCreated",
version: 1,
tenantId,
orderId: generateId(),
userId,
amount,
currency,
createdAt: new Date().toISOString(),
};
await eventLog.append(event);
return Response.json({ orderId: event.orderId });
};
}
Projection Workers
Workers that consume from JetStream:
// generated/workers/OrderReadModelWorker.ts
export class OrderReadModelWorker {
constructor(
private eventLog: EventLog,
private storage: Storage,
private logger: Logger
) {}
async start() {
const stream = this.eventLog.subscribe({
subjects: ["orders.*.OrderCreated", "orders.*.OrderUpdated"],
});
await pipe(
stream,
supervised(SupervisionStrategies.alwaysRestart(10)),
run({}, async (event) => {
await this.processEvent(event);
})
);
}
private async processEvent(event: Event) {
switch (event.type) {
case "OrderCreated":
await this.storage.set(
{ tenantId: event.tenantId, orderId: event.orderId },
event
);
break;
case "OrderUpdated":
const current = await this.storage.get(
{ tenantId: event.tenantId, orderId: event.orderId }
);
if (current) {
await this.storage.set(
{ tenantId: event.tenantId, orderId: event.orderId },
{ ...current, ...event.payload }
);
}
break;
}
}
}
Client SDK
Type-safe client for frontend:
// generated/client/index.ts
export class AuroraClient {
constructor(private config: AuroraClientConfig) {}
async createOrder(
params: CreateOrderParams,
body: CreateOrderBody
): Promise<CreateOrderResponse> {
const response = await fetch(
`${this.config.baseUrl}/api/v1/${params.tenantId}/orders`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${this.config.token}`,
},
body: JSON.stringify(body),
}
);
if (!response.ok) {
throw new AuroraClientError(response.status, await response.text());
}
return response.json();
}
}
React Hooks
React hooks for frontend (via @aurora/codegen-react):
// generated/hooks/index.ts
export function useCreateOrder(options?: MutationOptions) {
const { mutate, loading, error } = useMutation(
async (params: CreateOrderParams, body: CreateOrderBody) => {
const client = getAuroraClient();
return client.createOrder(params, body);
},
options
);
return { mutate, loading, error };
}
export function useGetOrder(
params: GetOrderParams,
options?: QueryOptions
) {
const { data, loading, error, refetch } = useQuery(
async () => {
const client = getAuroraClient();
return client.getOrder(params);
},
{ ...options, enabled: !!params.orderId }
);
return { data, loading, error, refetch };
}
Options
interface CodegenOptions {
// Output directory
output: string;
// What to generate
codegen: {
types?: boolean; // TypeScript types (default: true)
validators?: boolean; // Zod validators (default: true)
repositories?: boolean; // Repository interfaces (default: true)
handlers?: boolean; // API handlers (default: true)
workers?: boolean; // Projection workers (default: true)
client?: boolean; // Client SDK (default: true)
react?: boolean; // React hooks (default: true)
zustand?: boolean; // Zustand stores (default: false)
};
// Caching
cache?: {
enabled?: boolean; // Enable caching (default: true)
path?: string; // Cache file path (default: .codegen-cache.json)
};
}
Caching
Incremental codegen uses SHA-256 hashing to only regenerate changed files:
// Cache file format
{
"version": "0.2.0",
"files": {
"schemas/events.schema.ts": "abc123...",
"schemas/projections.schema.ts": "def456..."
},
"generated": {
"generated/types/events.ts": "abc123...",
"generated/handlers/CreateOrderHandler.ts": "def456..."
}
}
Disable caching:
await codegen(schemas, {
output: "./generated",
cache: { enabled: false },
});
Or use CLI:
aurora codegen --force
Type Generation
The codegen package can generate TypeScript types from runtime schemas:
import { schemaToTypeString } from "@aurora/codegen/type-generator";
import { t } from "@aurora/schema";
const schema = t.object({
name: t.string(),
age: t.number().min(0),
});
const typeString = schemaToTypeString(schema);
// Output: "{ name: string; age: number; }"
Testing
bun test src/**/*.test.ts
License
MIT
Dependencies
Dependencies
| ID | Version |
|---|---|
| @aurora/codegen-eos | 0.3.3 |
| @aurora/codegen-react | 0.3.3 |
| @aurora/codegen-zustand | 0.3.3 |
| @aurora/runtime-effect | 0.3.3 |
| @aurora/runtime-http | 0.3.3 |
| @aurora/runtime-storage | 0.3.3 |
| @aurora/schema | 0.3.3 |
| zod | ^3.22.4 |