@crossdelta/platform-sdk 0.13.3 → 0.13.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/bin/cli.js +312 -0
  2. package/bin/docs/generators/README.md +56 -0
  3. package/bin/docs/generators/code-style.md +96 -0
  4. package/bin/docs/generators/hono-bun.md +181 -0
  5. package/bin/docs/generators/hono-node.md +194 -0
  6. package/bin/docs/generators/nest.md +358 -0
  7. package/bin/docs/generators/service.md +564 -0
  8. package/bin/docs/generators/testing.md +97 -0
  9. package/bin/integration.collection.json +18 -0
  10. package/bin/templates/hono-microservice/Dockerfile.hbs +16 -0
  11. package/bin/templates/hono-microservice/biome.json.hbs +3 -0
  12. package/bin/templates/hono-microservice/src/index.ts.hbs +18 -0
  13. package/bin/templates/hono-microservice/tsconfig.json.hbs +14 -0
  14. package/bin/templates/nest-microservice/Dockerfile.hbs +37 -0
  15. package/bin/templates/nest-microservice/biome.json.hbs +3 -0
  16. package/bin/templates/nest-microservice/src/app.context.ts.hbs +17 -0
  17. package/bin/templates/nest-microservice/src/events/events.module.ts.hbs +8 -0
  18. package/bin/templates/nest-microservice/src/events/events.service.ts.hbs +22 -0
  19. package/bin/templates/nest-microservice/src/main.ts.hbs +34 -0
  20. package/bin/templates/workspace/biome.json.hbs +62 -0
  21. package/bin/templates/workspace/bunfig.toml.hbs +5 -0
  22. package/bin/templates/workspace/editorconfig.hbs +9 -0
  23. package/bin/templates/workspace/gitignore.hbs +15 -0
  24. package/bin/templates/workspace/infra/Pulumi.dev.yaml.hbs +5 -0
  25. package/bin/templates/workspace/infra/Pulumi.yaml.hbs +6 -0
  26. package/bin/templates/workspace/infra/index.ts.hbs +56 -0
  27. package/bin/templates/workspace/infra/package.json.hbs +23 -0
  28. package/bin/templates/workspace/infra/tsconfig.json.hbs +15 -0
  29. package/bin/templates/workspace/npmrc.hbs +2 -0
  30. package/bin/templates/workspace/package.json.hbs +51 -0
  31. package/bin/templates/workspace/packages/contracts/README.md.hbs +166 -0
  32. package/bin/templates/workspace/packages/contracts/package.json.hbs +22 -0
  33. package/bin/templates/workspace/packages/contracts/src/events/index.ts +16 -0
  34. package/bin/templates/workspace/packages/contracts/src/index.ts +10 -0
  35. package/bin/templates/workspace/packages/contracts/src/stream-policies.ts.hbs +40 -0
  36. package/bin/templates/workspace/packages/contracts/tsconfig.json.hbs +7 -0
  37. package/bin/templates/workspace/pnpm-workspace.yaml.hbs +5 -0
  38. package/bin/templates/workspace/turbo.json +38 -0
  39. package/bin/templates/workspace/turbo.json.hbs +29 -0
  40. package/install.sh +46 -8
  41. package/package.json +1 -3
  42. package/scripts/postinstall.js +0 -53
@@ -0,0 +1,18 @@
1
+ // IMPORTANT: telemetry must be imported first to patch modules before they're loaded
2
+ import '@crossdelta/telemetry'
3
+
4
+ import { Hono } from 'hono'
5
+
6
+ const port = Number(process.env.{{envKey}}_PORT) || 8080
7
+ const app = new Hono()
8
+
9
+ app.get('/health', (c) => {
10
+ return c.json({ status: 'ok' })
11
+ })
12
+
13
+ Bun.serve({
14
+ port,
15
+ fetch: app.fetch,
16
+ })
17
+
18
+ console.log(`🚀 Service ready at http://localhost:${port}`)
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "lib": ["ES2022"],
8
+ "types": ["bun"],
9
+ "jsx": "react-jsx",
10
+ "jsxImportSource": "hono/jsx",
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true
13
+ }
14
+ }
@@ -0,0 +1,37 @@
1
+ ARG NODE_VERSION={{nodeVersion}}
2
+ ARG BUN_VERSION={{bunVersion}}
3
+
4
+ # STAGE 1 — Build
5
+ FROM oven/bun:${BUN_VERSION}-alpine AS builder
6
+ WORKDIR /app
7
+
8
+ COPY package.json tsconfig*.json nest-cli.json ./
9
+ COPY src ./src
10
+
11
+ RUN --mount=type=secret,id=NPM_TOKEN \
12
+ export NPM_TOKEN="$(cat /run/secrets/NPM_TOKEN)" && \
13
+ bun install
14
+
15
+ RUN bun run build
16
+
17
+ # STAGE 2 — Production dependencies
18
+ FROM oven/bun:${BUN_VERSION}-alpine AS deps
19
+ WORKDIR /app
20
+
21
+ COPY package.json ./
22
+
23
+ RUN --mount=type=secret,id=NPM_TOKEN \
24
+ export NPM_TOKEN="$(cat /run/secrets/NPM_TOKEN)" && \
25
+ bun install --production --omit=optional
26
+
27
+ # STAGE 3 — Runtime
28
+ FROM node:${NODE_VERSION}-alpine AS production
29
+ WORKDIR /app
30
+
31
+ COPY --from=builder /app/dist ./dist
32
+ COPY --from=deps /app/node_modules ./node_modules
33
+
34
+ USER node
35
+ ENV NODE_ENV=production
36
+
37
+ CMD ["node", "dist/main.js"]
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": ["../../biome.json"]
3
+ }
@@ -0,0 +1,17 @@
1
+ import type { INestApplication, Type } from '@nestjs/common'
2
+
3
+ let app: INestApplication
4
+
5
+ export const setAppContext = (nestApp: INestApplication): void => {
6
+ app = nestApp
7
+ }
8
+
9
+ export const getAppContext = (): INestApplication => {
10
+ if (!app) throw new Error('App context not initialized')
11
+ return app
12
+ }
13
+
14
+ export const getService = <T>(serviceClass: Type<T>): T => {
15
+ return getAppContext().get(serviceClass)
16
+ }
17
+
@@ -0,0 +1,8 @@
1
+ import { Module } from '@nestjs/common'
2
+ import { EventsService } from './events.service'
3
+
4
+ @Module({
5
+ providers: [EventsService],
6
+ exports: [EventsService],
7
+ })
8
+ export class EventsModule {}
@@ -0,0 +1,22 @@
1
+ import { Injectable, Logger } from '@nestjs/common'
2
+ import { consumeJetStreams } from '@crossdelta/cloudevents'
3
+
4
+ @Injectable()
5
+ export class EventsService {
6
+ private readonly logger = new Logger(EventsService.name)
7
+
8
+ async startConsumers(): Promise<void> {
9
+ // Services NEVER create streams!
10
+ // - Development: pf dev auto-creates ephemeral streams from contracts
11
+ // - Production: Pulumi materializes persistent streams
12
+
13
+ // Uncomment and configure when you have events:
14
+ // consumeJetStreams({
15
+ // streams: ['ORDERS'],
16
+ // consumer: '{{serviceName}}',
17
+ // discover: './src/events/**/*.event.ts',
18
+ // })
19
+
20
+ this.logger.log('Event consumers ready')
21
+ }
22
+ }
@@ -0,0 +1,34 @@
1
+ // IMPORTANT: telemetry must be imported first to patch modules before they're loaded
2
+ import '@crossdelta/telemetry'
3
+
4
+ import { env } from 'node:process'
5
+ import { ConsoleLogger } from '@nestjs/common'
6
+ import { NestFactory } from '@nestjs/core'
7
+ import { AppModule } from './app.module'
8
+ import { setAppContext } from './app.context'
9
+ import { EventsService } from './events/events.service'
10
+
11
+ const port = Number(process.env.{{envKey}}_PORT) || {{defaultPort}}
12
+ const serviceName = '{{displayName}}'
13
+
14
+ const logger = new ConsoleLogger({
15
+ json: env.JSON_LOGS === 'true',
16
+ prefix: serviceName,
17
+ })
18
+
19
+ async function bootstrap() {
20
+ const app = await NestFactory.create(AppModule, { logger })
21
+
22
+ // Make app context available to event handlers
23
+ setAppContext(app)
24
+
25
+ // Start NATS event consumers
26
+ const eventsService = app.get(EventsService)
27
+ await eventsService.startConsumers()
28
+
29
+ await app
30
+ .listen(port)
31
+ .then(() => logger.log(`${serviceName} is running on port ${port}`))
32
+ }
33
+
34
+ bootstrap()
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
3
+ "formatter": {
4
+ "indentStyle": "space"
5
+ },
6
+ "assist": {
7
+ "actions": {
8
+ "source": {
9
+ "organizeImports": "on"
10
+ }
11
+ }
12
+ },
13
+ "linter": {
14
+ "enabled": true,
15
+ "rules": {
16
+ "security": {
17
+ "recommended": true
18
+ },
19
+ "style": {
20
+ "recommended": true,
21
+ "useAsConstAssertion": "warn",
22
+ "noUselessElse": "error",
23
+ "useConst": "error",
24
+ "useImportType": "off"
25
+ },
26
+ "complexity": {
27
+ "recommended": true,
28
+ "noUselessEmptyExport": "error",
29
+ "noExcessiveCognitiveComplexity": {
30
+ "level": "warn",
31
+ "options": {
32
+ "maxAllowedComplexity": 15
33
+ }
34
+ }
35
+ }
36
+ }
37
+ },
38
+ "javascript": {
39
+ "formatter": {
40
+ "indentWidth": 2,
41
+ "quoteStyle": "single",
42
+ "semicolons": "asNeeded",
43
+ "lineWidth": 120,
44
+ "trailingCommas": "all",
45
+ "arrowParentheses": "always"
46
+ }
47
+ },
48
+ "files": {
49
+ "includes": [
50
+ "**/src/**/*.ts",
51
+ "infra/**/*.ts",
52
+ "!apps/storefront",
53
+ "!**/vendor",
54
+ "!**/dist",
55
+ "!**/node_modules",
56
+ "!reports",
57
+ "!coverage",
58
+ "!stryker-tmp",
59
+ "!**/.stryker-tmp"
60
+ ]
61
+ }
62
+ }
@@ -0,0 +1,5 @@
1
+ [install]
2
+ workspaces = ["packages/*", "apps/*", "services/*"]
3
+
4
+ [install.scopes]
5
+ "@{{projectName}}" = { url = "https://npm.pkg.github.com", token = "$NPM_TOKEN" }
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ end_of_line = lf
7
+ charset = utf-8
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
@@ -0,0 +1,15 @@
1
+ out/
2
+ .env
3
+ .turbo
4
+ .idea/
5
+ .temp
6
+ .vscode/
7
+ .env.local
8
+ .temp/
9
+ node_modules
10
+ .artifacts/
11
+ .changed/
12
+ .nats-data
13
+ dist/
14
+ coverage/
15
+ *.log
@@ -0,0 +1,5 @@
1
+ config:
2
+ {{projectName}}-infra:logtailToken:
3
+ secure: # Add your encrypted token here
4
+ {{projectName}}-infra:registryCredentials:
5
+ secure: # Add your encrypted credentials here
@@ -0,0 +1,6 @@
1
+ name: {{projectName}}-infra
2
+ runtime:
3
+ name: nodejs
4
+ options:
5
+ packagemanager: bun
6
+ description: Infrastructure as Code for {{projectName}}
@@ -0,0 +1,56 @@
1
+ import { join } from 'node:path'
2
+ import {
3
+ buildExternalUrls,
4
+ buildIngressRules,
5
+ buildInternalUrls,
6
+ buildServicePortEnvs,
7
+ buildServices,
8
+ buildServiceUrlEnvs,
9
+ discoverServices,
10
+ } from '@crossdelta/infrastructure'
11
+ import { App } from '@pulumi/digitalocean'
12
+ import { Config, getStack } from '@pulumi/pulumi'
13
+
14
+ const allServiceConfigs = discoverServices(join(__dirname, 'services'))
15
+ const serviceConfigs = allServiceConfigs.filter((config) => !config.skip)
16
+ const cfg = new Config()
17
+ const logtailToken = cfg.requireSecret('logtailToken')
18
+ const registryCredentials = cfg.requireSecret('registryCredentials')
19
+
20
+ const stack = getStack()
21
+
22
+ const doAppName = `{{projectName}}-${stack}`
23
+
24
+ const app = new App('{{projectName}}', {
25
+ spec: {
26
+ name: doAppName,
27
+ region: 'fra',
28
+
29
+ alerts: [{ rule: 'DEPLOYMENT_FAILED' }, { rule: 'DOMAIN_FAILED' }],
30
+
31
+ features: ['buildpack-stack=ubuntu-22'],
32
+
33
+ envs: [
34
+ ...buildServiceUrlEnvs(serviceConfigs),
35
+ ...buildServicePortEnvs(serviceConfigs),
36
+ ],
37
+
38
+ services: buildServices({
39
+ serviceConfigs,
40
+ registryCredentials,
41
+ logtailToken,
42
+ }),
43
+
44
+ ingress: {
45
+ rules: buildIngressRules(serviceConfigs),
46
+ },
47
+ },
48
+ })
49
+
50
+ // Outputs
51
+ export const appId = app.id
52
+ export const appDefaultIngress = app.defaultIngress
53
+ export const internalUrls = buildInternalUrls(serviceConfigs)
54
+ export const serviceUrls = app.defaultIngress.apply((baseUrl) =>
55
+ buildExternalUrls(serviceConfigs, baseUrl ?? ''),
56
+ )
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "infra",
3
+ "private": true,
4
+ "scripts": {
5
+ "generate-env": "bunx generate-env",
6
+ "lint": "biome lint --fix",
7
+ "pulumi": "pulumi"
8
+ },
9
+ "dependencies": {
10
+ "@crossdelta/cloudevents": "^0.5.3",
11
+ "@crossdelta/infrastructure": "^0.5.2",
12
+ "{{scope}}/contracts": "workspace:*",
13
+ "@pulumi/digitalocean": "^4.55.0",
14
+ "@pulumi/kubernetes": "^4.21.0",
15
+ "@pulumi/pulumi": "^3.208.0",
16
+ "tsx": "^4.19.0"
17
+ },
18
+ "devDependencies": {
19
+ "@biomejs/biome": "2.3.8",
20
+ "@types/node": "^24.10.1",
21
+ "typescript": "^5.9.3"
22
+ }
23
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "commonjs",
5
+ "lib": ["ES2022"],
6
+ "moduleResolution": "node",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "outDir": "./dist"
12
+ },
13
+ "include": ["**/*.ts"],
14
+ "exclude": ["node_modules"]
15
+ }
@@ -0,0 +1,2 @@
1
+ # Add private registry scopes here if needed
2
+ # @your-org:registry=https://npm.pkg.github.com
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "private": true,
4
+ "scripts": {
5
+ "dev": "pf dev",
6
+ "generate-env": "cd infra && bun run generate-env",
7
+ "build": "dotenv -e .env.local -- turbo run build",
8
+ "preview": "dotenv -e .env.local -- turbo run preview",
9
+ "lint": "turbo run lint",
10
+ "format": "turbo run format",
11
+ "pulumi": "cd infra && pulumi",
12
+ "test": "dotenv -e .env.local -- turbo run test"
13
+ },
14
+ "pf": {
15
+ "registry": "{{projectName}}/platform",
16
+ "commands": {
17
+ "pulumi": {
18
+ "cwd": "infra"
19
+ }
20
+ },
21
+ "paths": {
22
+ "services": {
23
+ "path": "services",
24
+ "watch": true
25
+ },
26
+ "apps": {
27
+ "path": "apps",
28
+ "watch": true
29
+ },
30
+ "packages": {
31
+ "path": "packages",
32
+ "watch": true
33
+ },
34
+ "contracts": {
35
+ "path": "packages/contracts"
36
+ }
37
+ }
38
+ },
39
+ "dependencies": {
40
+ "@crossdelta/cloudevents": "latest",
41
+ "@crossdelta/telemetry": "latest"
42
+ },
43
+ "devDependencies": {
44
+ "@biomejs/biome": "2.3.7",
45
+ "@crossdelta/platform-sdk": "latest",
46
+ "dotenv-cli": "^8.0.0",
47
+ "turbo": "^2.5.6"
48
+ },
49
+ "packageManager": "{{packageManagerVersion}}",
50
+ "workspaces": ["packages/*", "apps/*", "services/*", "infra"]
51
+ }
@@ -0,0 +1,166 @@
1
+ # {{scope}}/contracts
2
+
3
+ Shared event contracts for cross-service event consumption.
4
+
5
+ ## Purpose
6
+
7
+ This package contains **shared event definitions** (contracts) for events that are consumed by multiple services. When an event is used by more than one service, define it here to ensure type consistency across the platform.
8
+
9
+ ## Structure
10
+
11
+ ```
12
+ src/
13
+ ├── events/ # Event contracts grouped by domain
14
+ │ ├── orders/ # Orders domain
15
+ │ │ ├── created.ts # orders.created event
16
+ │ │ ├── updated.ts # orders.updated event
17
+ │ │ └── index.ts # Re-exports
18
+ │ ├── customers/ # Customers domain
19
+ │ │ ├── updated.ts # customers.updated event
20
+ │ │ └── index.ts # Re-exports
21
+ │ └── index.ts # Re-exports all domains
22
+ ├── stream-policies.ts # NATS JetStream retention policies
23
+ └── index.ts # Main export file
24
+ ```
25
+
26
+ **Contract files contain:**
27
+ - Zod schema definition
28
+ - Contract object (type + schema + **channel metadata**)
29
+ - TypeScript type inference
30
+
31
+ **Channel metadata** defines which NATS JetStream stream the event belongs to. This enables infrastructure-as-code workflows where streams are auto-created in dev (`pf dev`) and materialized via Pulumi in production.
32
+
33
+ ## Adding New Events
34
+
35
+ ### Using the CLI (Recommended)
36
+
37
+ ```bash
38
+ pf event add products.created --fields "productId:string,name:string,price:number"
39
+ ```
40
+
41
+ This will create `src/events/products/created.ts` with proper domain structure.
42
+
43
+ ### Manual Creation
44
+
45
+ See [Adding Events](#manual-creation) section below.
46
+
47
+ ## Usage
48
+
49
+ ### In Event Handlers (Consumers)
50
+
51
+ ```ts
52
+ import { handleEvent } from '@crossdelta/cloudevents'
53
+ import { OrdersCreatedContract, type OrdersCreatedData } from '{{scope}}/contracts'
54
+
55
+ export default handleEvent(OrdersCreatedContract, async (data: OrdersCreatedData) => {
56
+ // data is fully typed from contract
57
+ console.log(data.orderId, data.customerId)
58
+ })
59
+ ```
60
+
61
+ ### In Publishers (REST APIs)
62
+
63
+ ```ts
64
+ import { publish } from '@crossdelta/cloudevents'
65
+ import { OrdersCreatedContract } from '{{scope}}/contracts'
66
+
67
+ // Type-safe publishing with contract
68
+ await publish(OrdersCreatedContract, {
69
+ orderId: 'order-123',
70
+ customerId: 'cust-456',
71
+ total: 99.99,
72
+ items: [...]
73
+ })
74
+ ```
75
+
76
+ ### In Use-Cases
77
+
78
+ ```ts
79
+ import type { OrdersCreatedData } from '{{scope}}/contracts'
80
+
81
+ export const processOrder = async (data: OrdersCreatedData) => {
82
+ // Use typed event data
83
+ }
84
+ ```
85
+
86
+ ## Adding New Contracts
87
+
88
+ Contracts are **auto-generated** when you create event handlers:
89
+
90
+ ```bash
91
+ # 1. Create service with event handler
92
+ pf new hono-micro notifications --ai -d "Sends emails on orders.created events"
93
+
94
+ # 2. Add event (creates contract, mock, handler)
95
+ pf event add orders.created --service services/notifications
96
+ ```
97
+
98
+ This creates:
99
+ - `packages/contracts/src/events/orders-created.ts` (contract)
100
+ - `packages/contracts/src/events/orders-created.mock.json` (mock)
101
+ - Updates `packages/contracts/src/index.ts` (exports)
102
+
103
+ ### Manual Contract Creation
104
+
105
+ ```ts
106
+ // packages/contracts/src/events/orders/created.ts
107
+ import { createContract } from '@crossdelta/cloudevents'
108
+ import { z } from 'zod'
109
+
110
+ export const OrdersCreatedSchema = z.object({
111
+ orderId: z.string(),
112
+ customerId: z.string(),
113
+ total: z.number(),
114
+ items: z.array(z.object({
115
+ productId: z.string(),
116
+ quantity: z.number(),
117
+ price: z.number(),
118
+ })),
119
+ })
120
+
121
+ export const OrdersCreatedContract = createContract({
122
+ type: 'orders.created',
123
+ channel: { stream: 'ORDERS' }, // Stream routing metadata
124
+ schema: OrdersCreatedSchema,
125
+ })
126
+
127
+ export type OrdersCreatedData = z.infer<typeof OrdersCreatedContract.schema>
128
+ ```
129
+
130
+ **Channel Metadata:**
131
+ - `stream` - NATS JetStream stream name (e.g., `ORDERS`)
132
+ - `subject` - Optional, defaults to event type (e.g., `orders.created`)
133
+
134
+ **Stream Materialization:**
135
+ 1. **Development**: `pf dev` scans contracts and auto-creates ephemeral streams from channel metadata
136
+ 2. **Production**: Pulumi collects streams from contracts and materializes with retention policies
137
+
138
+ See [`infra/streams/README.md`](../../infra/streams/README.md) for details.
139
+
140
+ ## Testing with Mocks
141
+
142
+ ```bash
143
+ # List all available events
144
+ pf event list
145
+
146
+ # Publish mock event
147
+ pf event publish orders.created
148
+
149
+ # Publish with custom data
150
+ pf event publish orders.created --data '{"orderId":"test-123"}'
151
+ ```
152
+
153
+ ## Guidelines
154
+
155
+ - ✅ Use contracts for **shared events** (multi-consumer)
156
+ - ✅ Export both contract and inferred type
157
+ - ✅ Keep contracts minimal and focused
158
+ - ✅ Generate mocks for all contracts
159
+ - ❌ Don't put business logic in contracts
160
+ - ❌ Don't include event handlers in this package
161
+
162
+ **Naming conventions:**
163
+ - Contracts: `OrdersCreatedContract` (plural namespace)
164
+ - Types: `OrdersCreatedData`
165
+ - Files: `orders-created.ts`
166
+ - Event types: `orders.created` (plural namespace, dot notation)
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "{{scope}}/contracts",
3
+ "private": true,
4
+ "type": "module",
5
+ "main": "./src/index.ts",
6
+ "types": "./src/index.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./src/index.ts",
10
+ "default": "./src/index.ts"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "@crossdelta/cloudevents": "^0.5.3",
15
+ "@crossdelta/infrastructure": "^0.5.2",
16
+ "zod": "^4.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "@biomejs/biome": "^1.9.4",
20
+ "typescript": "^5.7.2"
21
+ }
22
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Event Contracts Index
3
+ *
4
+ * Re-exports all event contracts for convenient importing.
5
+ * Services can import from '{{scope}}/contracts' instead of deep imports.
6
+ *
7
+ * Structure:
8
+ * - events/<domain>/<event>.ts - Individual event contracts
9
+ * - events/<domain>/index.ts - Domain-specific exports
10
+ * - This file: Re-exports all domains
11
+ */
12
+
13
+ // Add your event domains here as you create them:
14
+ // export * from './orders'
15
+ // export * from './customers'
16
+ // export * from './products'
@@ -0,0 +1,10 @@
1
+ // Export your event contracts and schemas here
2
+ // Use the CLI to generate contracts:
3
+ //
4
+ // pf event add orders.created --fields "orderId:string,total:number"
5
+ //
6
+ // This will create: src/events/orders/created.ts
7
+ // Then uncomment the exports below:
8
+
9
+ // export * from './events'
10
+ // export * from './stream-policies'