@crossdelta/platform-sdk 0.10.1 → 0.11.1

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.
@@ -7,35 +7,44 @@ This directory contains AI instructions for code generators.
7
7
  ```
8
8
  generators/
9
9
  ├── README.md # This file
10
- └── service.md # Service generator instructions
10
+ ├── service.md # Main service generator instructions
11
+ ├── code-style.md # Code style, formatting, naming conventions
12
+ ├── testing.md # Testing rules and patterns
13
+ ├── hono-bun.md # Hono with Bun runtime specifics
14
+ ├── hono-node.md # Hono with Node.js runtime specifics
15
+ └── nest.md # NestJS framework specifics
11
16
  ```
12
17
 
13
18
  ## How Instructions Are Loaded
14
19
 
15
- The AI service generator loads instructions in priority order (most specific first):
16
-
17
- 1. **Generator-specific** (`packages/platform-sdk/docs/generators/service.md`)
18
- - Detailed rules for the service generator output format
19
- - Event consumer/publisher workflows
20
- - File structure requirements
21
-
22
- 2. **Copilot instructions** (`.github/copilot-instructions.md`)
23
- - Project-wide coding standards
24
- - Code style rules
25
- - Package-specific guidelines
20
+ Instructions are configured in `package.json` under `generatorConfig.docs`:
21
+
22
+ ```json
23
+ {
24
+ "generatorConfig": {
25
+ "docs": {
26
+ "base": ["service.md", "code-style.md", "testing.md"],
27
+ "frameworks": {
28
+ "hono": { "bun": "hono-bun.md", "node": "hono-node.md" },
29
+ "nest": "nest.md"
30
+ }
31
+ }
32
+ }
33
+ }
34
+ ```
26
35
 
27
- 3. **Project AI guidelines** (`docs/ai-guidelines.md`)
28
- - General architectural principles
29
- - Validation patterns
30
- - Testing guidelines
36
+ **Load Order:**
37
+ 1. **Base docs** - Always loaded (service.md, code-style.md, testing.md)
38
+ 2. **Framework-specific** - Based on `serviceType` and `packageManager`
39
+ 3. **Workspace instructions** - `.github/copilot-instructions.md`, `docs/ai-guidelines.md`
31
40
 
32
41
  ## Adding New Generators
33
42
 
34
- To add instructions for a new generator:
43
+ To add instructions for a new framework:
35
44
 
36
- 1. Create `<generator-name>.md` in this directory
37
- 2. Update `INSTRUCTION_FILES` in `ai-service-generator.ts` if needed
38
- 3. Follow the existing format from `service.md`
45
+ 1. Create `<framework>.md` in this directory
46
+ 2. Add to `generatorConfig.docs.frameworks` in `package.json`
47
+ 3. Follow the existing format from `hono-bun.md` or `nest.md`
39
48
 
40
49
  ## Template Variables
41
50
 
@@ -0,0 +1,96 @@
1
+ # Code Style
2
+
3
+ ## Formatting
4
+
5
+ - Single quotes, no semicolons, 2-space indent, trailing commas
6
+ - Arrow functions over `function`
7
+ - Template literals over concatenation
8
+
9
+ ---
10
+
11
+ ## Imports
12
+
13
+ **Must be alphabetically sorted** (Biome enforces this):
14
+
15
+ ```ts
16
+ // ✅ CORRECT - sorted alphabetically, type imports first
17
+ import type { DomainCreatedData } from '@my-platform/contracts'
18
+ import type { OrdersCreatedData } from '@scope/contracts'
19
+ import { handleEvent } from '@crossdelta/cloudevents'
20
+ import PusherPushNotifications from '@pusher/push-notifications-server'
21
+
22
+ // ❌ WRONG - unsorted
23
+ import PusherPushNotifications from '@pusher/push-notifications-server'
24
+ import type { DomainCreatedData } from '@my-platform/contracts'
25
+
26
+ // ❌ WRONG - missing 'type' keyword
27
+ import { OrdersCreatedData } from '@scope/contracts'
28
+
29
+ // ❌ WRONG - unused imports
30
+ import { handleEvent, publish } from '@crossdelta/cloudevents'
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Environment Variables
36
+
37
+ ```ts
38
+ // ✅ CORRECT
39
+ const apiKey = process.env.API_KEY
40
+ if (!apiKey) throw new Error('Missing API_KEY')
41
+
42
+ // ❌ WRONG
43
+ const apiKey = process.env.API_KEY! // no assertions
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Naming
49
+
50
+ | Type | Convention | Example |
51
+ |------|------------|---------|
52
+ | Files | kebab-case | `send-notification.use-case.ts` |
53
+ | Contracts | PascalCase | `OrdersCreatedContract` |
54
+ | Types | PascalCase + Data | `OrdersCreatedData` |
55
+
56
+ ---
57
+
58
+ ## Config Validation (Type Narrowing)
59
+
60
+ Use validation functions that return typed objects - avoids `!` assertions:
61
+
62
+ ```ts
63
+ // ✅ CORRECT - validation returns typed object
64
+ export const validateBeamsConfig = (config: {
65
+ instanceId?: string
66
+ secretKey?: string
67
+ }): { instanceId: string; secretKey: string } => {
68
+ if (!config.instanceId) throw new Error('Missing PUSHER_BEAMS_INSTANCE_ID')
69
+ if (!config.secretKey) throw new Error('Missing PUSHER_BEAMS_SECRET_KEY')
70
+ return { instanceId: config.instanceId, secretKey: config.secretKey }
71
+ }
72
+
73
+ // Usage - no assertions needed
74
+ const config = validateBeamsConfig({
75
+ instanceId: process.env.PUSHER_BEAMS_INSTANCE_ID,
76
+ secretKey: process.env.PUSHER_BEAMS_SECRET_KEY,
77
+ })
78
+ new PusherClient(config) // ✅ Typed correctly
79
+
80
+ // ❌ WRONG - non-null assertions (Biome error)
81
+ validateConfig({ instanceId, secretKey })
82
+ new PusherClient({ instanceId: instanceId!, secretKey: secretKey! })
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Zod 4
88
+
89
+ ```ts
90
+ // ✅ No params
91
+ z.string().email()
92
+ z.string().datetime()
93
+
94
+ // ❌ Deprecated
95
+ z.string().email('Invalid')
96
+ ```
@@ -1,15 +1,23 @@
1
- # Hono Service (Bun Runtime) - AI Generator Guidelines
1
+ # Hono (Bun Runtime)
2
2
 
3
- These guidelines are for generating Hono microservices that run with **Bun runtime**.
3
+ ## 🚨 CRITICAL: Commands Block (REQUIRED FIRST)
4
+
5
+ ```commands
6
+ pf new hono-micro services/<service-name> -y
7
+ ```
8
+
9
+ **Example:** User asks for "push notifications service" → generate:
10
+ ```commands
11
+ pf new hono-micro services/push-notifications -y
12
+ ```
4
13
 
5
14
  ---
6
15
 
7
- ## Entry Point Template (src/index.ts)
16
+ ## Entry Point (src/index.ts)
8
17
 
9
- **Basic REST API:**
18
+ **REST API:**
10
19
  ```ts
11
20
  import '@crossdelta/telemetry'
12
-
13
21
  import { Hono } from 'hono'
14
22
 
15
23
  const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
@@ -17,17 +25,14 @@ const app = new Hono()
17
25
 
18
26
  app.get('/health', (c) => c.json({ status: 'ok' }))
19
27
 
20
- // Your routes here
21
- app.get('/', (c) => c.text('Hello Hono!'))
22
-
23
28
  Bun.serve({ port, fetch: app.fetch })
29
+ console.log(`Service running on http://localhost:${port}`)
24
30
  ```
25
31
 
26
- **Event Consumer (NATS) - Multiple Streams:**
32
+ **Event Consumer:**
27
33
  ```ts
28
34
  import '@crossdelta/telemetry'
29
-
30
- import { consumeJetStreamStreams, ensureJetStreamStreams } from '@crossdelta/cloudevents'
35
+ import { consumeJetStreams, ensureJetStreams } from '@crossdelta/cloudevents'
31
36
  import { Hono } from 'hono'
32
37
 
33
38
  const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
@@ -36,25 +41,22 @@ const app = new Hono()
36
41
  app.get('/health', (c) => c.json({ status: 'ok' }))
37
42
 
38
43
  Bun.serve({ port, fetch: app.fetch })
44
+ console.log(`Service running on http://localhost:${port}`)
39
45
 
40
- await ensureJetStreamStreams({
41
- streams: [
42
- { stream: 'ORDERS', subjects: ['orders.*'] },
43
- { stream: 'CUSTOMERS', subjects: ['customers.*'] },
44
- ]
46
+ await ensureJetStreams({
47
+ streams: [{ stream: 'ORDERS', subjects: ['orders.*'] }]
45
48
  })
46
49
 
47
- consumeJetStreamStreams({
48
- streams: ['ORDERS', 'CUSTOMERS'],
50
+ consumeJetStreams({
51
+ streams: ['ORDERS'],
49
52
  consumer: 'my-service',
50
53
  discover: './src/events/**/*.event.ts',
51
54
  })
52
55
  ```
53
56
 
54
- **Event Publisher (REST + CloudEvents):**
57
+ **Event Publisher:**
55
58
  ```ts
56
59
  import '@crossdelta/telemetry'
57
-
58
60
  import { publish } from '@crossdelta/cloudevents'
59
61
  import { Hono } from 'hono'
60
62
 
@@ -65,37 +67,21 @@ app.get('/health', (c) => c.json({ status: 'ok' }))
65
67
 
66
68
  app.post('/orders', async (c) => {
67
69
  const data = await c.req.json()
68
- await publish('orders.created', data, { source: 'my-service' })
70
+ await publish('orders.created', data)
69
71
  return c.json({ success: true })
70
72
  })
71
73
 
72
74
  Bun.serve({ port, fetch: app.fetch })
75
+ console.log(`Service running on http://localhost:${port}`)
73
76
  ```
74
77
 
75
78
  ---
76
79
 
77
- ## Key Points
78
-
79
- - ✅ Use `Bun.serve({ port, fetch: app.fetch })` for server
80
- - ✅ Import telemetry FIRST (before any other imports)
81
- - ✅ Use the port env var name provided in the prompt (e.g., `PUSH_NOTIFICATIONS_PORT`)
82
- - ✅ Always include `/health` endpoint
83
- - ✅ Keep routes simple and delegate logic to use-cases
84
- - ✅ Use `ensureJetStreamStreams` + `consumeJetStreamStreams` for multiple event types
80
+ ## Rules
85
81
 
86
- **DO NOT:**
87
- - `export default Bun.serve(...)` - Bun.serve returns Server, not for export
88
- - `export default app` - Not needed for Bun runtime
89
- - Multiple `ensureJetStreamStream` calls - use batch version instead
90
-
91
- ---
92
-
93
- ## Dev Command
94
-
95
- ```json
96
- {
97
- "scripts": {
98
- "dev": "bun run --hot src/index.ts"
99
- }
100
- }
101
- ```
82
+ - ✅ `Bun.serve({ port, fetch: app.fetch })`
83
+ - Import telemetry FIRST
84
+ - Always include `/health`
85
+ - Use port env var from prompt (e.g., `PUSH_NOTIFICATIONS_PORT`)
86
+ - ❌ `export default Bun.serve(...)` - wrong
87
+ - ❌ `export default app` - not needed
@@ -1,15 +1,23 @@
1
- # Hono Service (Node.js Runtime) - AI Generator Guidelines
1
+ # Hono (Node.js Runtime)
2
2
 
3
- These guidelines are for generating Hono microservices that run with **Node.js runtime** (pnpm, npm, yarn).
3
+ ## 🚨 CRITICAL: Commands Block (REQUIRED FIRST)
4
+
5
+ ```commands
6
+ pf new hono-micro services/<service-name> -y
7
+ ```
8
+
9
+ **Example:** User asks for "push notifications service" → generate:
10
+ ```commands
11
+ pf new hono-micro services/push-notifications -y
12
+ ```
4
13
 
5
14
  ---
6
15
 
7
- ## Entry Point Template (src/index.ts)
16
+ ## Entry Point (src/index.ts)
8
17
 
9
- **Basic REST API:**
18
+ **REST API:**
10
19
  ```ts
11
20
  import '@crossdelta/telemetry'
12
-
13
21
  import { serve } from '@hono/node-server'
14
22
  import { Hono } from 'hono'
15
23
 
@@ -18,22 +26,15 @@ const app = new Hono()
18
26
 
19
27
  app.get('/health', (c) => c.json({ status: 'ok' }))
20
28
 
21
- // Your routes here
22
- app.get('/', (c) => c.text('Hello Hono!'))
23
-
24
- serve({
25
- fetch: app.fetch,
26
- port
27
- }, (info) => {
28
- console.log(`Server is running on http://localhost:${info.port}`)
29
+ serve({ fetch: app.fetch, port }, (info) => {
30
+ console.log(`Server running on http://localhost:${info.port}`)
29
31
  })
30
32
  ```
31
33
 
32
- **Event Consumer (NATS) - Multiple Streams:**
34
+ **Event Consumer:**
33
35
  ```ts
34
36
  import '@crossdelta/telemetry'
35
-
36
- import { consumeJetStreamStreams, ensureJetStreamStreams } from '@crossdelta/cloudevents'
37
+ import { consumeJetStreams, ensureJetStreams } from '@crossdelta/cloudevents'
37
38
  import { serve } from '@hono/node-server'
38
39
  import { Hono } from 'hono'
39
40
 
@@ -42,31 +43,24 @@ const app = new Hono()
42
43
 
43
44
  app.get('/health', (c) => c.json({ status: 'ok' }))
44
45
 
45
- serve({
46
- fetch: app.fetch,
47
- port
48
- }, (info) => {
49
- console.log(`Server is running on http://localhost:${info.port}`)
46
+ serve({ fetch: app.fetch, port }, (info) => {
47
+ console.log(`Server running on http://localhost:${info.port}`)
50
48
  })
51
49
 
52
- await ensureJetStreamStreams({
53
- streams: [
54
- { stream: 'ORDERS', subjects: ['orders.*'] },
55
- { stream: 'CUSTOMERS', subjects: ['customers.*'] },
56
- ]
50
+ await ensureJetStreams({
51
+ streams: [{ stream: 'ORDERS', subjects: ['orders.*'] }]
57
52
  })
58
53
 
59
- consumeJetStreamStreams({
60
- streams: ['ORDERS', 'CUSTOMERS'],
54
+ consumeJetStreams({
55
+ streams: ['ORDERS'],
61
56
  consumer: 'my-service',
62
57
  discover: './src/events/**/*.event.ts',
63
58
  })
64
59
  ```
65
60
 
66
- **Event Publisher (REST + CloudEvents):**
61
+ **Event Publisher:**
67
62
  ```ts
68
63
  import '@crossdelta/telemetry'
69
-
70
64
  import { publish } from '@crossdelta/cloudevents'
71
65
  import { serve } from '@hono/node-server'
72
66
  import { Hono } from 'hono'
@@ -78,39 +72,21 @@ app.get('/health', (c) => c.json({ status: 'ok' }))
78
72
 
79
73
  app.post('/orders', async (c) => {
80
74
  const data = await c.req.json()
81
- await publish('orders.created', data, { source: 'my-service' })
75
+ await publish('orders.created', data)
82
76
  return c.json({ success: true })
83
77
  })
84
78
 
85
- serve({
86
- fetch: app.fetch,
87
- port
88
- }, (info) => {
89
- console.log(`Server is running on http://localhost:${info.port}`)
79
+ serve({ fetch: app.fetch, port }, (info) => {
80
+ console.log(`Server running on http://localhost:${info.port}`)
90
81
  })
91
82
  ```
92
83
 
93
84
  ---
94
85
 
95
- ## Key Points
96
-
97
- - ✅ Use `serve()` from `@hono/node-server` (NOT `Bun.serve`)
98
- - ✅ Import `serve` from `@hono/node-server`
99
- - ✅ Import telemetry FIRST (before any other imports)
100
- - ✅ Use the port env var name provided in the prompt (e.g., `API_GATEWAY_PORT`)
101
- - ✅ Always include `/health` endpoint
102
- - ✅ Include callback with console.log for server startup
103
- - ✅ Keep routes simple and delegate logic to use-cases
104
- - ✅ Use `ensureJetStreamStreams` + `consumeJetStreamStreams` for multiple event types
105
-
106
- ---
107
-
108
- ## Dev Command
86
+ ## Rules
109
87
 
110
- ```json
111
- {
112
- "scripts": {
113
- "dev": "tsx watch src/index.ts"
114
- }
115
- }
116
- ```
88
+ - ✅ `serve()` from `@hono/node-server`
89
+ - ✅ Import telemetry FIRST
90
+ - ✅ Always include `/health`
91
+ - Use port env var from prompt (e.g., `API_GATEWAY_PORT`)
92
+ - ❌ `Bun.serve()` - wrong runtime