@crossdelta/platform-sdk 0.7.21 β†’ 0.7.22

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 (2) hide show
  1. package/README.md +165 -417
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -15,12 +15,11 @@
15
15
  </p>
16
16
 
17
17
  <p align="center">
18
- <strong>πŸš€ Scaffold β€’ πŸ€– Generate β€’ ☁️ Deploy</strong>
18
+ <em>Includes optional AI-assisted service generation (OpenAI / Anthropic).</em>
19
19
  </p>
20
20
 
21
21
  <p align="center">
22
22
  <a href="https://www.npmjs.com/package/@crossdelta/platform-sdk"><img src="https://img.shields.io/npm/v/@crossdelta/platform-sdk.svg?style=flat-square" alt="npm version" /></a>
23
-
24
23
  <img src="https://img.shields.io/badge/bun-%E2%9A%A1-f9f1e1?style=flat-square" alt="Bun" />
25
24
  <img src="https://img.shields.io/badge/pulumi-ready-blueviolet?style=flat-square" alt="Pulumi" />
26
25
  <img src="https://img.shields.io/badge/DigitalOcean-App_Platform_|_DOKS-0080FF?style=flat-square" alt="DigitalOcean" />
@@ -30,29 +29,24 @@
30
29
  <em><code>pf</code> enforces conventions that keep application code and cloud infrastructure in lockstep β€” from local development to production.</em>
31
30
  </p>
32
31
 
33
- <br />
34
-
35
32
  ---
36
33
 
37
34
  ## Installation
38
35
 
39
36
  ```bash
40
- # Pick your package manager
41
37
  bun add -g @crossdelta/platform-sdk
42
- npm install -g @crossdelta/platform-sdk
43
- pnpm add -g @crossdelta/platform-sdk
38
+ # or: npm install -g @crossdelta/platform-sdk
44
39
  ```
45
40
 
46
41
  <details>
47
- <summary>Alternative: Auto-installer or use without installing</summary>
42
+ <summary>Alternative: Auto-installer or run without installing</summary>
48
43
 
49
44
  ```bash
50
- # Auto-installer (detects package manager, offers to install Bun if needed)
45
+ # Auto-installer (installs CLI globally, prompts to install Bun if missing)
51
46
  curl -fsSL https://unpkg.com/@crossdelta/platform-sdk@latest/install.sh | bash
52
47
 
53
- # Or run directly without global install
48
+ # Or run directly without installing
54
49
  bunx @crossdelta/platform-sdk new workspace my-platform
55
- npx @crossdelta/platform-sdk new workspace my-platform
56
50
  ```
57
51
 
58
52
  </details>
@@ -62,277 +56,83 @@ npx @crossdelta/platform-sdk new workspace my-platform
62
56
  ## Quick Start
63
57
 
64
58
  ```bash
65
- # Create workspace
66
- pf new workspace my-platform -y
67
- cd my-platform
68
-
69
- # Generate microservice with AI
70
- pf setup --ai # Configure AI provider (first time only)
71
- pf new hono-micro services/orders --ai -d "Handle order creation and payment"
72
-
73
- # Start development
59
+ pf new workspace my-platform -y && cd my-platform
74
60
  pf dev
75
61
  ```
76
62
 
77
- **What you get in minutes:**
78
-
79
- - βœ” Turborepo monorepo with Biome linting
80
- - βœ” NATS + event-driven microservices
81
- - βœ” Pulumi infrastructure (`infra/services/*.ts`)
82
- - βœ” Auto-generated `.env.local` with service ports
83
- - βœ” AI-generated service code
84
-
85
- All wired automatically. Local + production infra in lockstep.
86
-
87
- ### ⚑ One CLI for everything
88
-
89
- `pf` runs your workspace scripts from anywhere:
90
-
91
- ```bash
92
- pf test # β†’ turbo run test
93
- pf build # β†’ turbo run build
94
- pf pulumi up # β†’ runs in infra/ directory
95
- ```
96
-
97
- **Why:** Keeps commands consistent across the team and works from any subdirectory.
98
-
99
- > **πŸ“– Note:** You can be productive with `pf` in minutes using the commands above. The sections below are reference documentationβ€”explore them when you need specific details.
100
-
101
- <br />
102
-
103
- ---
104
-
105
- ## 🎯 Why This Exists
106
-
107
- **`pf` solves these platform engineering problems:**
108
-
109
- - **Infrastructure drift** β€” Infra configs live in separate repos, diverge from code
110
- - **Manual wiring** β€” Ports, env vars, service discovery configured by hand
111
- - **Slow onboarding** β€” New devs spend days setting up local environment
112
-
113
- **`pf` is lockstep infra + code:** Services auto-generate `infra/services/*.ts`, ports/env derived automatically, event handlers type-safe and auto-discovered.
114
-
115
- <br />
116
-
117
- ---
118
-
119
- ## 🧩 What This SDK Is / Is Not
120
-
121
- ### βœ… `pf` is:
122
-
123
- - **Opinionated platform toolkit** for event-driven microservices
124
- - **[Turborepo](https://turbo.build/repo) scaffolder** with [Pulumi](https://www.pulumi.com) IaC and [NATS](https://nats.io) messaging built-in
125
- - **AI-assisted code generator** that creates service boilerplate from descriptions
126
- - **Unified dev workflow** β€” one command to run all services (`pf dev`)
127
- - **[DigitalOcean](https://www.digitalocean.com)-first** deployment target (App Platform + DOKS)
128
-
129
- ### ❌ `pf` is not:
130
-
131
- - **Generic microservice generator** β€” makes architectural choices for you
132
- - **Multi-cloud** (not yet) β€” DigitalOcean first, extensible provider architecture
133
- - **Runtime manager** β€” scaffolds code, you deploy with Pulumi
134
- - **Kubernetes replacement** β€” generates K8s configs via Pulumi
135
-
136
- **Note:** `pf` runs nothing implicitlyβ€”no hidden daemons, no automatic deployments or provisioning. You maintain explicit control over when code runs and infrastructure is deployed.
137
-
138
- ### πŸ”₯ Why `pf` vs other tools?
139
-
140
- - **πŸ”— Lockstep infra + code** β€” `infra/services/*.ts` auto-generated from service metadata, ports/env derived automatically
141
- - **⚑ Event-driven by default** β€” [NATS](https://nats.io) + JetStream built-in with auto-discovered handlers (`*.event.ts`) and Zod-validated payloads
142
- - **πŸ€– Automation through conventions** β€” New service = infra config + env vars + port assignment happens automatically
63
+ **What you get:**
64
+ - Turborepo monorepo with Biome linting
65
+ - NATS + JetStream for event-driven messaging
66
+ - Pulumi infrastructure (`infra/services/*.ts`)
67
+ - Auto-generated `.env.local` with service ports
143
68
 
144
- <br />
69
+ > **Lockstep by design:**
70
+ > In `pf`, application code and infrastructure are generated from the same source of truth.
71
+ > Service metadata defines ports, env vars, event wiring, and Pulumi configs β€”
72
+ > eliminating drift between local development, CI, and production.
145
73
 
146
74
  ---
147
75
 
148
- ## πŸ—οΈ Architecture at 10,000 ft
76
+ ## 🧭 How You Work With pf (Happy Paths)
149
77
 
150
- When you create a workspace with `pf`, you get a **Turborepo monorepo** with this structure:
78
+ ### Start a new platform
151
79
 
80
+ ```bash
81
+ pf new workspace my-platform --github-owner my-org --pulumi-stack dev -y
82
+ cd my-platform
83
+ pf dev
152
84
  ```
153
- my-platform/
154
- β”œβ”€β”€ services/ # Microservices (generate with pf new hono-micro)
155
- β”‚ β”œβ”€β”€ nats/ # NATS message broker (auto-scaffolded)
156
- β”‚ └── <service>/ # Your services go here
157
- β”‚ └── src/
158
- β”‚ β”œβ”€β”€ events/ # Event handlers (*.event.ts)
159
- β”‚ β”œβ”€β”€ use-cases/ # Business logic (*.use-case.ts)
160
- β”‚ β”œβ”€β”€ types/ # Zod schemas & types
161
- β”‚ └── index.ts # Service entrypoint
162
- β”œβ”€β”€ apps/ # Frontend apps (optional)
163
- β”œβ”€β”€ packages/
164
- β”‚ └── contracts/ # Event contracts (Schema Registry)
165
- β”‚ └── src/
166
- β”‚ └── events/ # Event schemas (single source of truth)
167
- β”œβ”€β”€ infra/ # Pulumi Infrastructure-as-Code
168
- β”‚ β”œβ”€β”€ index.ts # Main Pulumi program
169
- β”‚ └── services/ # Per-service K8s configs (auto-generated)
170
- β”œβ”€β”€ .github/
171
- β”‚ └── workflows/ # CI/CD pipelines
172
- β”œβ”€β”€ turbo.json # Turborepo task orchestration
173
- └── .env.local # Auto-generated from infra configs
174
- ```
175
-
176
- ### Key Conventions
177
-
178
- | Location | Purpose |
179
- |----------|---------|
180
- | `services/*/src/events/*.event.ts` | Event handlers (auto-discovered) |
181
- | `services/*/src/use-cases/*.use-case.ts` | Business logic (pure functions) |
182
- | `services/*/src/types/*.ts` | Service-local Zod schemas |
183
- | `packages/contracts/src/events/*.ts` | Event contracts (Schema Registry) |
184
- | `infra/services/*.ts` | Pulumi configs per service |
185
-
186
- ### Key Rules
187
-
188
- - **Never duplicate schemas** β€” Contracts in `packages/contracts` are the single source of truth
189
- - **Event handlers stay thin** β€” Delegate to use-cases, no business logic in handlers
190
- - **Infrastructure is explicit** β€” Ports, env vars derived from `infra/services/*.ts`
191
-
192
- ### Event-Driven Mental Model
193
-
194
- Services communicate via **CloudEvents** over **NATS JetStream** using the **Schema Registry** as single source of truth:
195
-
196
- **1. Define contract (Schema Registry):**
197
-
198
- ```typescript
199
- // packages/contracts/src/events/orders-created.ts
200
- import { createContract } from '@crossdelta/cloudevents'
201
- import { z } from 'zod'
202
85
 
203
- export const OrdersCreatedContract = createContract({
204
- type: 'orders.created',
205
- schema: z.object({
206
- orderId: z.string(),
207
- customerId: z.string(),
208
- total: z.number(),
209
- }),
210
- })
86
+ This scaffolds a complete Turborepo monorepo with NATS, Pulumi infrastructure, GitHub Actions workflows, and auto-generated environment variables.
211
87
 
212
- export type OrdersCreatedData = z.infer<typeof OrdersCreatedContract.schema>
213
- ```
214
-
215
- **2. Service A publishes an event:**
88
+ ### Add a new microservice
216
89
 
217
- ```typescript
218
- // services/orders/src/index.ts
219
- import { publish } from '@crossdelta/cloudevents'
220
- import { OrdersCreatedContract } from '@my-platform/contracts'
221
-
222
- await publish(OrdersCreatedContract, {
223
- orderId: '123',
224
- customerId: 'cust-456',
225
- total: 99.99
226
- })
90
+ ```bash
91
+ pf new hono-micro services/orders
227
92
  ```
228
93
 
229
- **3. Service B auto-discovers and handles it:**
230
-
231
- ```typescript
232
- // services/notifications/src/events/orders-created.event.ts
233
- import { handleEvent } from '@crossdelta/cloudevents'
234
- import { OrdersCreatedContract, type OrdersCreatedData } from '@my-platform/contracts'
235
- import { sendOrderNotification } from '../use-cases/send-order-notification.use-case'
94
+ Or use AI generation:
236
95
 
237
- export default handleEvent(OrdersCreatedContract, async (data: OrdersCreatedData) => {
238
- await sendOrderNotification(data) // Delegate to use-case
239
- })
96
+ ```bash
97
+ pf new hono-micro services/orders --ai -d "Handle order creation and publish order events"
240
98
  ```
241
99
 
242
- No manual NATS subscriptions. No boilerplate. Just **convention over configuration**.
243
-
244
- <br />
245
-
246
- ---
247
-
248
- ## 🧭 Design Principles
249
-
250
- These principles guide every decision in `pf`:
100
+ Both generate the service structure, Pulumi config in `infra/services/`, and wire everything automatically.
251
101
 
252
- - **πŸ₯Ÿ Bun-first DX** β€” Leverage Bun's speed for installs, tests, and dev mode (npm/yarn fallback supported)
253
- - **πŸ“¦ Monorepo-centric** β€” One repo to rule them all. Turborepo for caching and parallel builds
254
- - **πŸ—οΈ Infrastructure-as-Code by default** β€” No ClickOps. Every service has Pulumi config
255
- - **πŸ” Event-driven communication baked in** β€” NATS + JetStream are first-class citizens, not afterthoughts
256
- - **🌊 DigitalOcean-first, cloud-agnostic later** β€” Start simple with DO, expand to AWS/GCP when needed
257
- - **πŸ€– AI-augmented development** β€” Use AI to generate complete services, not just snippets
258
- - **πŸ“ Convention over configuration** β€” Strong opinions enable automation
102
+ ### Generate with AI (optional)
259
103
 
260
- <br />
104
+ Configure your AI provider once:
261
105
 
262
- ---
263
-
264
- ## πŸ‘₯ Who Is This For?
265
-
266
- `pf` is designed for **small to mid-sized teams building event-driven systems** who want strong conventions, infra parity, and fast onboarding β€” without maintaining their own internal platform.
267
-
268
- <br />
269
-
270
- ---
271
-
272
- ## πŸ“š Deep Dive & Reference
273
-
274
- The sections below cover architectural details, workflows, and advanced usage.
275
- **You don't need to read them to get started** β€” they're here when you need them.
276
-
277
- ---
278
-
279
- ## πŸ“˜ Workflows
280
-
281
- ### Generate microservices
282
-
283
- **Manual scaffolding:**
284
- ```bash
285
- pf new hono-micro services/orders
286
- pf new nest-micro services/api-gateway
287
- ```
288
-
289
- **AI-powered generation:**
290
106
  ```bash
291
- # First time: configure AI provider (OpenAI or Anthropic)
292
- pf setup --ai
293
-
294
- # Generate service with AI
295
- pf new hono-micro services/payments --ai \
296
- -d "Handle Stripe webhooks and send payment confirmations"
107
+ pf setup --ai # OpenAI or Anthropic
297
108
  ```
298
109
 
299
- **✨ AI generates:**
300
- - βœ… Complete service with event handlers & use cases
301
- - βœ… Pulumi infrastructure configuration
302
- - βœ… Test files with validation logic
303
- - βœ… Complete README documentation
304
-
305
- > **Note:** AI-generated code is a starting point. Always review and test before deploying to production. `pf` never deploys or provisions infrastructure automatically β€” deployment always happens explicitly via Pulumi.
306
-
307
- ### Start local development
110
+ Then use `--ai` with any service generator:
308
111
 
309
112
  ```bash
310
- cd my-platform
311
- pf dev
113
+ pf new hono-micro services/notifications --ai -d "Send emails on order events"
312
114
  ```
313
115
 
314
- This will:
315
- - πŸ”„ Auto-generate `.env.local` from infrastructure config
316
- - πŸš€ Start NATS + all services in watch mode (via Turbo)
317
- - πŸ”Œ Auto-assign unique ports per service
318
- - πŸ“¦ Monitor for file changes and hot-reload
116
+ AI generates: service code, event handlers, use cases, tests, and documentation.
319
117
 
320
- ### 4. Essential workspace commands
118
+ AI is a productivity layer β€” all generated code follows the same conventions and can be written manually without loss of functionality.
321
119
 
322
- ```bash
323
- # Run all tests across the monorepo
324
- pf test
120
+ ### Daily commands
325
121
 
326
- # Lint and format all code with Biome
327
- pf lint
122
+ | Command | What it does |
123
+ |---------|--------------|
124
+ | `pf dev` | Start NATS + all services in watch mode |
125
+ | `pf test` | Run tests across the monorepo |
126
+ | `pf lint` | Lint and format with Biome |
127
+ | `pf build` | Build all packages and services |
128
+ | `pf pulumi up` | Deploy infrastructure (runs in `infra/`) |
328
129
 
329
- # Build all packages and services
330
- pf build
331
- ```
130
+ `pf` proxies to Turborepo from any subdirectory.
332
131
 
333
- ### 5. Workspace Configuration
132
+ ### Configuration (advanced)
334
133
 
335
- Configure workspace behavior via the `pf` field in your root `package.json`:
134
+ <details>
135
+ <summary>Workspace configuration via <code>package.json</code></summary>
336
136
 
337
137
  ```json
338
138
  {
@@ -343,238 +143,186 @@ Configure workspace behavior via the `pf` field in your root `package.json`:
343
143
  "deploy": { "cwd": "infra", "command": "pulumi up --yes" }
344
144
  },
345
145
  "paths": {
346
- "services": {
347
- "path": "services",
348
- "watch": true
349
- },
350
- "apps": {
351
- "path": "apps",
352
- "watch": true
353
- },
354
- "packages": {
355
- "path": "packages",
356
- "watch": true,
357
- "ignorePatterns": ["packages/some-internal-package"]
358
- },
359
- "contracts": {
360
- "path": "packages/contracts"
361
- }
146
+ "services": { "path": "services", "watch": true },
147
+ "apps": { "path": "apps", "watch": true },
148
+ "packages": { "path": "packages", "watch": true },
149
+ "contracts": { "path": "packages/contracts" }
362
150
  }
363
151
  }
364
152
  }
365
153
  ```
366
154
 
367
- **Options:**
368
- - `commands`: Custom command shortcuts with `cwd` (working directory) and `command` overrides
369
- - `paths.<type>.path`: Directory path for each workspace type
370
- - `paths.<type>.watch`: Whether to watch this directory in dev mode (default: `false`)
371
- - `paths.<type>.ignorePatterns`: Glob patterns to ignore within this path (optional)
155
+ - `commands`: Custom shortcuts with working directory overrides
156
+ - `paths.<type>.watch`: Enable file watching in dev mode
157
+ - `paths.<type>.ignorePatterns`: Glob patterns to exclude
372
158
 
373
- <br />
374
-
375
- ---
376
-
377
- ## πŸ“˜ Typical Workflows
378
-
379
- Here's how developers actually use `pf` in real-world scenarios:
159
+ </details>
380
160
 
381
161
  <details>
382
- <summary><strong>Workflow 1: Start a New Platform</strong></summary>
383
-
384
- <br />
162
+ <summary>Infrastructure configuration via <code>infra/services/*.ts</code></summary>
385
163
 
386
- You're building a new product from scratch and want to establish a solid foundation.
387
-
388
- ```bash
389
- # Step 1: Scaffold the workspace
390
- bunx @crossdelta/platform-sdk new workspace my-platform \
391
- --github-owner my-platform \
392
- --pulumi-stack dev \
393
- -y
394
-
395
- cd my-platform
396
-
397
- # Step 2: Configure infrastructure (optional)
398
- # Edit infra/config.ts to customize:
399
- # - DigitalOcean region (defaults to nyc3)
400
- # - Kubernetes cluster size
401
- # - Database instance sizes
164
+ ```ts
165
+ import { ports, type K8sServiceConfig } from '@crossdelta/infrastructure'
402
166
 
403
- # Step 3: Start local development
404
- pf dev
167
+ export const config: K8sServiceConfig = {
168
+ name: 'orders',
169
+ ports: ports().http(4001).build(),
170
+ replicas: 1,
171
+ healthCheck: { httpPath: '/health' },
172
+ resources: {
173
+ requests: { cpu: '50m', memory: '64Mi' },
174
+ limits: { cpu: '150m', memory: '128Mi' },
175
+ },
176
+ }
405
177
  ```
406
178
 
407
- **What you get:**
408
- - βœ… Turborepo monorepo with Biome linting/formatting
409
- - βœ… NATS service running in Docker
410
- - βœ… Pulumi infrastructure setup for DigitalOcean
411
- - βœ… GitHub Actions workflows for CI/CD
412
- - βœ… `.env.local` auto-generated with all service ports
179
+ See [@crossdelta/infrastructure](https://www.npmjs.com/package/@crossdelta/infrastructure) for full options.
413
180
 
414
181
  </details>
415
182
 
416
183
  ---
417
184
 
418
- ### Workflow 2: Add a New Microservice
419
-
420
- ```bash
421
- # Generate with AI (optional: use --ai flag)
422
- pf new hono-micro services/payments --ai \
423
- -d "Stripe payment processing: handle webhooks, publish events"
185
+ ## 🎯 Why This Exists
424
186
 
425
- # Auto-generated: service code + infra config + tests + README
426
- # Start the service
427
- pf dev
428
- ```
187
+ `pf` solves platform engineering problems:
429
188
 
430
- **AI generates:** Service structure, event handlers, use cases, tests, and documentation. Always review before deploying.
189
+ - **Infrastructure drift** β€” Infra configs diverge from code in separate repos
190
+ - **Manual wiring** β€” Ports, env vars, service discovery configured by hand
191
+ - **Slow onboarding** β€” New devs spend days setting up local environments
431
192
 
432
- ---
193
+ **Solution:** Services auto-generate `infra/services/*.ts`, ports/env derived automatically, event handlers type-safe and auto-discovered.
433
194
 
434
- ## ⚑ NATS Message Broker
195
+ In short: docker-compose starts services β€” `pf` prevents systems from drifting apart over time.
435
196
 
436
- Every workspace includes a pre-configured NATS service with JetStream:
197
+ ---
437
198
 
438
- ```
439
- services/nats/
440
- β”œβ”€β”€ nats.conf # Local dev config (JetStream enabled)
441
- β”œβ”€β”€ nats.prod.conf # Production config (auth + persistence)
442
- β”œβ”€β”€ scripts/start-dev.sh # Docker startup script
443
- └── README.md # Full NATS documentation
444
- ```
199
+ ## 🧩 What pf Is / Is Not
445
200
 
446
- **Local Development:**
447
- - Auto-started with `pf dev`
448
- - Runs in Docker on ports `4222` (client) and `8222` (HTTP monitoring)
449
- - Data persisted in `.nats-data/` directory
450
- - Health check: `curl http://localhost:8222/healthz`
201
+ **βœ… pf is:**
202
+ - Opinionated platform toolkit for event-driven microservices
203
+ - Turborepo scaffolder with Pulumi IaC and NATS messaging built-in
204
+ - AI-assisted code generator from natural language descriptions
205
+ - Unified dev workflow β€” one command to run everything
206
+ - DigitalOcean-first deployment target
451
207
 
452
- **πŸ“š Learn more:** See `services/nats/README.md` in your workspace for monitoring, configuration, and JetStream details.
208
+ **❌ pf is not:**
209
+ - Generic microservice generator β€” makes architectural choices for you
210
+ - Multi-cloud (not yet) β€” DigitalOcean first, extensible architecture
211
+ - Runtime manager β€” scaffolds code, you deploy with Pulumi
453
212
 
454
- <br />
213
+ **Note:** `pf` runs nothing implicitly. No hidden daemons, no automatic deployments. You control when code runs and infrastructure deploys.
455
214
 
456
215
  ---
457
216
 
458
- ## πŸ›  CLI Commands
459
-
460
- <details>
461
- <summary><strong>πŸ“– View Full Command Reference</strong></summary>
462
-
463
- <br />
217
+ ## πŸ—οΈ Architecture
464
218
 
465
- ### Workspace Commands
219
+ ```
220
+ my-platform/
221
+ β”œβ”€β”€ services/ # Microservices
222
+ β”‚ β”œβ”€β”€ nats/ # NATS message broker (auto-scaffolded)
223
+ β”‚ └── <service>/
224
+ β”‚ └── src/
225
+ β”‚ β”œβ”€β”€ events/ # Event handlers (*.event.ts)
226
+ β”‚ β”œβ”€β”€ use-cases/ # Business logic (*.use-case.ts)
227
+ β”‚ β”œβ”€β”€ types/ # Zod schemas
228
+ β”‚ └── index.ts
229
+ β”œβ”€β”€ packages/
230
+ β”‚ └── contracts/ # Event contracts (Schema Registry)
231
+ β”œβ”€β”€ infra/ # Pulumi Infrastructure-as-Code
232
+ β”‚ └── services/ # Per-service K8s configs
233
+ └── .env.local # Auto-generated from infra
234
+ ```
466
235
 
467
- | Command | Description |
468
- |---------|-------------|
469
- | `pf new` | Interactive creation wizard |
470
- | `pf new workspace <name>` | Scaffold a complete platform monorepo |
471
- | `pf setup --ai` | Configure AI provider (OpenAI or Anthropic) |
236
+ ### Conventions
472
237
 
473
- ### Service Commands
238
+ | Location | Purpose |
239
+ |----------|---------|
240
+ | `services/*/src/events/*.event.ts` | Event handlers (auto-discovered) |
241
+ | `services/*/src/use-cases/*.use-case.ts` | Business logic (pure functions) |
242
+ | `packages/contracts/src/events/*.ts` | Event contracts (single source of truth) |
243
+ | `infra/services/*.ts` | Pulumi configs per service |
474
244
 
475
- | Command | Description |
476
- |---------|-------------|
477
- | `pf new hono-micro <path>` | Generate a Hono microservice (lightweight) |
478
- | `pf new nest-micro <path>` | Generate a NestJS microservice (enterprise-grade) |
479
- | `pf new hono-micro <path> --ai` | Generate service with AI (requires `pf setup --ai`) |
245
+ > **Schema Registry pattern:**
246
+ > All event contracts live in `packages/contracts` as the single source of truth.
247
+ > Services import contracts instead of redefining schemas, ensuring
248
+ > type safety, compatibility, and explicit ownership across service boundaries.
480
249
 
481
- ### Event Testing
250
+ ### Event-Driven Pattern
482
251
 
483
- | Command | Description |
484
- |---------|-------------|
485
- | `pf event:generate <path>` | Generate event mocks from event handlers |
486
- | `pf event:list` | List all available event mocks |
487
- | `pf event:publish <name>` | Publish to NATS JetStream |
488
- | `pf event:http <name>` | Send via HTTP Pub/Sub endpoint |
252
+ **1. Define contract:**
253
+ ```typescript
254
+ // packages/contracts/src/events/orders-created.ts
255
+ import { createContract } from '@crossdelta/cloudevents'
256
+ import { z } from 'zod'
489
257
 
490
- ### Utility Commands
258
+ export const OrdersCreatedContract = createContract({
259
+ type: 'orders.created',
260
+ schema: z.object({ orderId: z.string(), total: z.number() }),
261
+ })
262
+ ```
491
263
 
492
- | Command | Description |
493
- |---------|-------------|
494
- | `pf --version` | Show version information |
495
- | `pf --help` | Show help for any command |
264
+ **2. Publish (Service A):**
265
+ ```typescript
266
+ // services/orders/src/use-cases/create-order.use-case.ts
267
+ await publish(OrdersCreatedContract, { orderId: '123', total: 99.99 })
268
+ ```
496
269
 
497
- </details>
270
+ **3. Handle (Service B, auto-discovered):**
271
+ ```typescript
272
+ // services/notifications/src/events/orders-created.event.ts
273
+ export default handleEvent(OrdersCreatedContract, async (data) => {
274
+ await sendOrderNotification(data)
275
+ })
276
+ ```
498
277
 
499
- <br />
278
+ No manual subscriptions. Convention over configuration.
500
279
 
501
280
  ---
502
281
 
503
- ## πŸ”§ Configuration Example
504
-
505
- Define infrastructure in `infra/services/*.ts` using [`@crossdelta/infrastructure`](https://www.npmjs.com/package/@crossdelta/infrastructure):
282
+ ## ⚑ NATS Message Broker
506
283
 
507
- ```ts
508
- import { ports } from '@crossdelta/infrastructure'
509
- import type { K8sServiceConfig } from '@crossdelta/infrastructure'
284
+ Every workspace includes pre-configured NATS with JetStream:
510
285
 
511
- export const config: K8sServiceConfig = {
512
- name: 'orders',
513
- ports: ports().http(4001).build(),
514
- replicas: 1,
515
- healthCheck: { httpPath: '/health' },
516
- resources: {
517
- requests: { cpu: '50m', memory: '64Mi' },
518
- limits: { cpu: '150m', memory: '128Mi' },
519
- },
520
- env: {
521
- DATABASE_URL: databaseUrl,
522
- NATS_URL: natsUrl,
523
- },
524
- }
525
- ```
526
-
527
- **πŸ“– See the [Infrastructure Package Docs](https://www.npmjs.com/package/@crossdelta/infrastructure) for advanced configuration options.**
286
+ - Auto-started with `pf dev`
287
+ - Ports: `4222` (client), `8222` (monitoring)
288
+ - Health check: `curl http://localhost:8222/healthz`
528
289
 
529
- <br />
290
+ See `services/nats/README.md` for details.
530
291
 
531
292
  ---
532
293
 
533
- ## 🚒 Deployment
534
-
535
- ### Local Deployment
294
+ ## Deployment
536
295
 
537
296
  ```bash
538
- pulumi login
539
- pulumi up --stack dev
297
+ pulumi login && pulumi up --stack dev
540
298
  ```
541
299
 
542
- ### CI/CD with GitHub Actions
543
-
544
- Every workspace includes pre-configured GitHub Actions workflows in `.github/workflows/`:
300
+ ### GitHub Actions (pre-configured)
545
301
 
546
302
  | Workflow | Trigger | Purpose |
547
303
  |----------|---------|---------|
548
- | **`lint-and-tests.yml`** | Pull Requests to `main` | Runs `bun lint` and `bun test` on PRs |
549
- | **`build-and-deploy.yml`** | Push to `main` | Builds Docker images, pushes to GHCR, deploys via Pulumi |
550
- | **`publish-packages.yml`** | Changes in `packages/` | Auto-publishes packages to npm with versioning |
551
-
552
- ### Required GitHub Secrets
553
-
554
- Configure these secrets in your repository settings (`Settings` β†’ `Secrets and variables` β†’ `Actions`):
304
+ | `lint-and-tests.yml` | PR to `main` | Lint + test |
305
+ | `build-and-deploy.yml` | Push to `main` | Build, push to GHCR, deploy |
306
+ | `publish-packages.yml` | Changes in `packages/` | Publish to npm |
555
307
 
556
- | Secret | Description | Required For |
557
- |--------|-------------|--------------|
558
- | `PULUMI_ACCESS_TOKEN` | Pulumi Cloud access token | All deployments |
559
- | `DIGITALOCEAN_TOKEN` | DigitalOcean API token | Infrastructure provisioning |
560
- | `NPM_TOKEN` | npm registry token | Package publishing (optional) |
561
- | `GHCR_TOKEN` | GitHub Container Registry PAT | Docker image publishing |
308
+ <details>
309
+ <summary>Required secrets</summary>
562
310
 
563
- **Get tokens:**
564
- - **Pulumi:** [Create access token](https://app.pulumi.com/account/tokens)
565
- - **DigitalOcean:** [Generate API token](https://cloud.digitalocean.com/account/api/tokens)
566
- - **npm:** [Create access token](https://www.npmjs.com/settings/~/tokens)
311
+ | Secret | Description |
312
+ |--------|-------------|
313
+ | `PULUMI_ACCESS_TOKEN` | [Pulumi Cloud token](https://app.pulumi.com/account/tokens) |
314
+ | `DIGITALOCEAN_TOKEN` | [DO API token](https://cloud.digitalocean.com/account/api/tokens) |
315
+ | `GHCR_TOKEN` | GitHub Container Registry PAT |
567
316
 
568
- <br />
317
+ </details>
569
318
 
570
319
  ---
571
320
 
572
321
  ## πŸ“š Requirements
573
322
 
574
- - **JavaScript runtime** β€” Bun (recommended) or Node.js β‰₯ 21 (npm/yarn/pnpm)
575
- - **[Pulumi CLI](https://www.pulumi.com/docs/install/)** β€” for infrastructure deployment
576
- - **[Docker](https://www.docker.com/)** β€” required for local NATS. Without Docker, you can still scaffold/build
577
-
323
+ - **Bun** (recommended) or Node.js β‰₯ 21
324
+ - **[Pulumi CLI](https://www.pulumi.com/docs/install/)** for deployment
325
+ - **[Docker](https://www.docker.com/)** for local NATS
578
326
 
579
327
  ---
580
328
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crossdelta/platform-sdk",
3
- "version": "0.7.21",
3
+ "version": "0.7.22",
4
4
  "description": "Your AI-powered platform engineer. Scaffold complete Turborepo workspaces, generate microservice boilerplate with natural language, and deploy to the cloud β€” all from one CLI",
5
5
  "keywords": [
6
6
  "cli",