@crossdelta/platform-sdk 0.7.16 → 0.7.17
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.
- package/README.md +55 -77
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
|
-
<strong>
|
|
13
|
-
Scaffold
|
|
14
|
-
|
|
12
|
+
<strong>Opinionated CLI for event-driven microservice platforms.</strong><br />
|
|
13
|
+
Scaffold <a href="https://turbo.build/repo">Turborepo</a> workspaces, generate services from natural language,<br />
|
|
14
|
+
and deploy via <a href="https://www.pulumi.com">Pulumi</a> — DigitalOcean-first, provider-agnostic by design.
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
</p>
|
|
28
28
|
|
|
29
29
|
<p align="center">
|
|
30
|
-
<em><code>pf</code>
|
|
30
|
+
<em><code>pf</code> enforces conventions that keep application code and cloud infrastructure in lockstep — from local development to production.</em>
|
|
31
31
|
</p>
|
|
32
32
|
|
|
33
33
|
<br />
|
|
@@ -151,38 +151,52 @@ When you create a workspace with `pf`, you get a **Turborepo monorepo** with thi
|
|
|
151
151
|
|
|
152
152
|
```
|
|
153
153
|
my-platform/
|
|
154
|
-
├── services/
|
|
155
|
-
│
|
|
156
|
-
|
|
157
|
-
├── packages/ # Shared libraries
|
|
158
|
-
│ └── contracts/ # Event contracts (Schema Registry)
|
|
154
|
+
├── services/ # Microservices (generate with pf new hono-micro)
|
|
155
|
+
│ ├── nats/ # NATS message broker (auto-scaffolded)
|
|
156
|
+
│ └── <service>/ # Your services go here
|
|
159
157
|
│ └── src/
|
|
160
|
-
│
|
|
161
|
-
├──
|
|
162
|
-
│
|
|
163
|
-
│
|
|
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)
|
|
164
170
|
├── .github/
|
|
165
|
-
│ └── workflows/
|
|
166
|
-
├── turbo.json
|
|
167
|
-
└── .env.local
|
|
171
|
+
│ └── workflows/ # CI/CD pipelines
|
|
172
|
+
├── turbo.json # Turborepo task orchestration
|
|
173
|
+
└── .env.local # Auto-generated from infra configs
|
|
168
174
|
```
|
|
169
175
|
|
|
170
|
-
### Key
|
|
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
|
|
171
187
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
4. **Auto-wiring everywhere** — Ports, env vars, NATS subjects, and event contracts are derived automatically
|
|
176
|
-
5. **AI-assisted generation** — Services generate with correct event schemas from natural language descriptions
|
|
177
|
-
6. **Opinionated conventions** — Event handlers in `src/events/*.event.ts`, business logic in `src/use-cases/*.use-case.ts`, schemas in `src/types/*.ts`
|
|
178
|
-
7. **Bun-first DX** — Ultra-fast installs, tests, and dev server with fallback to npm/yarn
|
|
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`
|
|
179
191
|
|
|
180
192
|
### Event-Driven Mental Model
|
|
181
193
|
|
|
182
194
|
Services communicate via **CloudEvents** over **NATS JetStream** using the **Schema Registry** as single source of truth:
|
|
183
195
|
|
|
196
|
+
**1. Define contract (Schema Registry):**
|
|
197
|
+
|
|
184
198
|
```typescript
|
|
185
|
-
// packages/contracts/src/events/orders-created.ts
|
|
199
|
+
// packages/contracts/src/events/orders-created.ts
|
|
186
200
|
import { createContract } from '@crossdelta/cloudevents'
|
|
187
201
|
import { z } from 'zod'
|
|
188
202
|
|
|
@@ -196,8 +210,12 @@ export const OrdersCreatedContract = createContract({
|
|
|
196
210
|
})
|
|
197
211
|
|
|
198
212
|
export type OrdersCreatedData = z.infer<typeof OrdersCreatedContract.schema>
|
|
213
|
+
```
|
|
199
214
|
|
|
200
|
-
|
|
215
|
+
**2. Service A publishes an event:**
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// services/orders/src/index.ts
|
|
201
219
|
import { publish } from '@crossdelta/cloudevents'
|
|
202
220
|
import { OrdersCreatedContract } from '@my-platform/contracts'
|
|
203
221
|
|
|
@@ -206,14 +224,18 @@ await publish(OrdersCreatedContract, {
|
|
|
206
224
|
customerId: 'cust-456',
|
|
207
225
|
total: 99.99
|
|
208
226
|
})
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**3. Service B auto-discovers and handles it:**
|
|
209
230
|
|
|
210
|
-
|
|
211
|
-
//
|
|
231
|
+
```typescript
|
|
232
|
+
// services/notifications/src/events/orders-created.event.ts
|
|
212
233
|
import { handleEvent } from '@crossdelta/cloudevents'
|
|
213
234
|
import { OrdersCreatedContract, type OrdersCreatedData } from '@my-platform/contracts'
|
|
235
|
+
import { sendOrderNotification } from '../use-cases/send-order-notification.use-case'
|
|
214
236
|
|
|
215
237
|
export default handleEvent(OrdersCreatedContract, async (data: OrdersCreatedData) => {
|
|
216
|
-
await
|
|
238
|
+
await sendOrderNotification(data) // Delegate to use-case
|
|
217
239
|
})
|
|
218
240
|
```
|
|
219
241
|
|
|
@@ -409,22 +431,11 @@ pf dev
|
|
|
409
431
|
|
|
410
432
|
---
|
|
411
433
|
|
|
412
|
-
## ⚡
|
|
413
|
-
|
|
414
|
-
Every workspace includes **NATS + JetStream** for event-driven microservices communication using **[`@crossdelta/cloudevents`](https://www.npmjs.com/package/@crossdelta/cloudevents)**:
|
|
415
|
-
|
|
416
|
-
- 🎯 **Type-safe event handlers** with Zod schemas
|
|
417
|
-
- 🔄 **Auto-discovery** of event handlers (`*.event.ts` files)
|
|
418
|
-
- 📦 **Publisher/Consumer patterns** out of the box
|
|
419
|
-
- 🚀 **NATS auto-scaffolded** in `services/nats/` with Docker setup
|
|
420
|
-
- 🗄️ **JetStream persistence** for durable event streaming
|
|
421
|
-
|
|
422
|
-
### NATS Message Broker
|
|
434
|
+
## ⚡ NATS Message Broker
|
|
423
435
|
|
|
424
|
-
Every workspace includes a pre-configured NATS service:
|
|
436
|
+
Every workspace includes a pre-configured NATS service with JetStream:
|
|
425
437
|
|
|
426
|
-
```
|
|
427
|
-
# Auto-started with `bun dev`
|
|
438
|
+
```
|
|
428
439
|
services/nats/
|
|
429
440
|
├── nats.conf # Local dev config (JetStream enabled)
|
|
430
441
|
├── nats.prod.conf # Production config (auth + persistence)
|
|
@@ -433,44 +444,11 @@ services/nats/
|
|
|
433
444
|
```
|
|
434
445
|
|
|
435
446
|
**Local Development:**
|
|
447
|
+
- Auto-started with `pf dev`
|
|
436
448
|
- Runs in Docker on ports `4222` (client) and `8222` (HTTP monitoring)
|
|
437
449
|
- Data persisted in `.nats-data/` directory
|
|
438
450
|
- Health check: `curl http://localhost:8222/healthz`
|
|
439
451
|
|
|
440
|
-
### Publish Events
|
|
441
|
-
|
|
442
|
-
```typescript
|
|
443
|
-
import { publish } from '@crossdelta/cloudevents'
|
|
444
|
-
|
|
445
|
-
await publish('orders.created', { orderId: 'ord_123', total: 99.99 })
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### Consume Events (Auto-Discovered)
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
// services/notifications/src/events/orders-created.event.ts
|
|
452
|
-
import { handleEvent } from '@crossdelta/cloudevents'
|
|
453
|
-
import { z } from 'zod'
|
|
454
|
-
|
|
455
|
-
const OrdersCreatedSchema = z.object({
|
|
456
|
-
orderId: z.string(),
|
|
457
|
-
total: z.number(),
|
|
458
|
-
})
|
|
459
|
-
|
|
460
|
-
// Export type for use in use-cases
|
|
461
|
-
export type OrdersCreatedEvent = z.infer<typeof OrdersCreatedSchema>
|
|
462
|
-
|
|
463
|
-
export default handleEvent(
|
|
464
|
-
{
|
|
465
|
-
schema: OrdersCreatedSchema,
|
|
466
|
-
type: 'orders.created',
|
|
467
|
-
},
|
|
468
|
-
async (data) => {
|
|
469
|
-
await sendNotification(data)
|
|
470
|
-
},
|
|
471
|
-
)
|
|
472
|
-
```
|
|
473
|
-
|
|
474
452
|
**📚 Learn more:** See `services/nats/README.md` in your workspace for monitoring, configuration, and JetStream details.
|
|
475
453
|
|
|
476
454
|
<br />
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crossdelta/platform-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.17",
|
|
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",
|