@crossdelta/platform-sdk 0.9.3 → 0.10.0
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/bin/cli.js +42434 -262
- package/bin/docs/generators/hono-bun.md +101 -0
- package/bin/docs/generators/hono-node.md +116 -0
- package/bin/docs/generators/nest.md +265 -0
- package/bin/docs/generators/nest.md.new +351 -0
- package/bin/docs/generators/service.md +501 -78
- package/bin/templates/hono-microservice/biome.json.hbs +3 -0
- package/bin/templates/hono-microservice/tsconfig.json.hbs +1 -0
- package/bin/templates/nest-microservice/biome.json.hbs +10 -0
- package/bin/templates/nest-microservice/src/app.context.ts.hbs +17 -0
- package/bin/templates/nest-microservice/src/events/events.module.ts.hbs +8 -0
- package/bin/templates/nest-microservice/src/events/events.service.ts.hbs +25 -0
- package/bin/templates/nest-microservice/src/main.ts.hbs +9 -0
- package/bin/templates/workspace/.github/copilot-instructions.md.hbs +1 -0
- package/bin/templates/workspace/biome.json.hbs +1 -1
- package/bin/templates/workspace/package.json.hbs +2 -6
- package/bin/templates/workspace/packages/contracts/package.json.hbs +3 -1
- package/bin/templates/workspace/packages/contracts/tsconfig.json.hbs +0 -1
- package/package.json +24 -3
- package/schemas/service-types.schema.json +33 -0
- package/bin/templates/hono-microservice/src/index.ts.hbs +0 -18
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Hono Service (Bun Runtime) - AI Generator Guidelines
|
|
2
|
+
|
|
3
|
+
These guidelines are for generating Hono microservices that run with **Bun runtime**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Entry Point Template (src/index.ts)
|
|
8
|
+
|
|
9
|
+
**Basic REST API:**
|
|
10
|
+
```ts
|
|
11
|
+
import '@crossdelta/telemetry'
|
|
12
|
+
|
|
13
|
+
import { Hono } from 'hono'
|
|
14
|
+
|
|
15
|
+
const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
|
|
16
|
+
const app = new Hono()
|
|
17
|
+
|
|
18
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
19
|
+
|
|
20
|
+
// Your routes here
|
|
21
|
+
app.get('/', (c) => c.text('Hello Hono!'))
|
|
22
|
+
|
|
23
|
+
Bun.serve({ port, fetch: app.fetch })
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Event Consumer (NATS) - Multiple Streams:**
|
|
27
|
+
```ts
|
|
28
|
+
import '@crossdelta/telemetry'
|
|
29
|
+
|
|
30
|
+
import { consumeJetStreamStreams, ensureJetStreamStreams } from '@crossdelta/cloudevents'
|
|
31
|
+
import { Hono } from 'hono'
|
|
32
|
+
|
|
33
|
+
const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
|
|
34
|
+
const app = new Hono()
|
|
35
|
+
|
|
36
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
37
|
+
|
|
38
|
+
Bun.serve({ port, fetch: app.fetch })
|
|
39
|
+
|
|
40
|
+
await ensureJetStreamStreams({
|
|
41
|
+
streams: [
|
|
42
|
+
{ stream: 'ORDERS', subjects: ['orders.*'] },
|
|
43
|
+
{ stream: 'CUSTOMERS', subjects: ['customers.*'] },
|
|
44
|
+
]
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
consumeJetStreamStreams({
|
|
48
|
+
streams: ['ORDERS', 'CUSTOMERS'],
|
|
49
|
+
consumer: 'my-service',
|
|
50
|
+
discover: './src/events/**/*.event.ts',
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Event Publisher (REST + CloudEvents):**
|
|
55
|
+
```ts
|
|
56
|
+
import '@crossdelta/telemetry'
|
|
57
|
+
|
|
58
|
+
import { publish } from '@crossdelta/cloudevents'
|
|
59
|
+
import { Hono } from 'hono'
|
|
60
|
+
|
|
61
|
+
const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
|
|
62
|
+
const app = new Hono()
|
|
63
|
+
|
|
64
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
65
|
+
|
|
66
|
+
app.post('/orders', async (c) => {
|
|
67
|
+
const data = await c.req.json()
|
|
68
|
+
await publish('orders.created', data, { source: 'my-service' })
|
|
69
|
+
return c.json({ success: true })
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
Bun.serve({ port, fetch: app.fetch })
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
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
|
|
85
|
+
|
|
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
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Hono Service (Node.js Runtime) - AI Generator Guidelines
|
|
2
|
+
|
|
3
|
+
These guidelines are for generating Hono microservices that run with **Node.js runtime** (pnpm, npm, yarn).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Entry Point Template (src/index.ts)
|
|
8
|
+
|
|
9
|
+
**Basic REST API:**
|
|
10
|
+
```ts
|
|
11
|
+
import '@crossdelta/telemetry'
|
|
12
|
+
|
|
13
|
+
import { serve } from '@hono/node-server'
|
|
14
|
+
import { Hono } from 'hono'
|
|
15
|
+
|
|
16
|
+
const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
|
|
17
|
+
const app = new Hono()
|
|
18
|
+
|
|
19
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
20
|
+
|
|
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
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Event Consumer (NATS) - Multiple Streams:**
|
|
33
|
+
```ts
|
|
34
|
+
import '@crossdelta/telemetry'
|
|
35
|
+
|
|
36
|
+
import { consumeJetStreamStreams, ensureJetStreamStreams } from '@crossdelta/cloudevents'
|
|
37
|
+
import { serve } from '@hono/node-server'
|
|
38
|
+
import { Hono } from 'hono'
|
|
39
|
+
|
|
40
|
+
const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
|
|
41
|
+
const app = new Hono()
|
|
42
|
+
|
|
43
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
44
|
+
|
|
45
|
+
serve({
|
|
46
|
+
fetch: app.fetch,
|
|
47
|
+
port
|
|
48
|
+
}, (info) => {
|
|
49
|
+
console.log(`Server is running on http://localhost:${info.port}`)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
await ensureJetStreamStreams({
|
|
53
|
+
streams: [
|
|
54
|
+
{ stream: 'ORDERS', subjects: ['orders.*'] },
|
|
55
|
+
{ stream: 'CUSTOMERS', subjects: ['customers.*'] },
|
|
56
|
+
]
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
consumeJetStreamStreams({
|
|
60
|
+
streams: ['ORDERS', 'CUSTOMERS'],
|
|
61
|
+
consumer: 'my-service',
|
|
62
|
+
discover: './src/events/**/*.event.ts',
|
|
63
|
+
})
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Event Publisher (REST + CloudEvents):**
|
|
67
|
+
```ts
|
|
68
|
+
import '@crossdelta/telemetry'
|
|
69
|
+
|
|
70
|
+
import { publish } from '@crossdelta/cloudevents'
|
|
71
|
+
import { serve } from '@hono/node-server'
|
|
72
|
+
import { Hono } from 'hono'
|
|
73
|
+
|
|
74
|
+
const port = Number(process.env.PORT || process.env.MY_SERVICE_PORT) || 8080
|
|
75
|
+
const app = new Hono()
|
|
76
|
+
|
|
77
|
+
app.get('/health', (c) => c.json({ status: 'ok' }))
|
|
78
|
+
|
|
79
|
+
app.post('/orders', async (c) => {
|
|
80
|
+
const data = await c.req.json()
|
|
81
|
+
await publish('orders.created', data, { source: 'my-service' })
|
|
82
|
+
return c.json({ success: true })
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
serve({
|
|
86
|
+
fetch: app.fetch,
|
|
87
|
+
port
|
|
88
|
+
}, (info) => {
|
|
89
|
+
console.log(`Server is running on http://localhost:${info.port}`)
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
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
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"scripts": {
|
|
113
|
+
"dev": "tsx watch src/index.ts"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# NestJS Service - AI Generator Guidelines
|
|
2
|
+
|
|
3
|
+
These guidelines are for generating NestJS microservices.
|
|
4
|
+
|
|
5
|
+
**For handler location and structure rules (shared for all frameworks), see:** [Service Generator - Handler Location & Structure](./service.md#handler-location--structure-critical)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🚨 CRITICAL: Commands Block (REQUIRED - MUST BE FIRST IN YOUR RESPONSE)
|
|
10
|
+
|
|
11
|
+
Your response **MUST** start with a commands block that scaffolds the NestJS service structure:
|
|
12
|
+
|
|
13
|
+
```commands
|
|
14
|
+
pf new nest-micro <service-path> -y
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Example:** If user asks for "orders service", generate:
|
|
18
|
+
```commands
|
|
19
|
+
pf new nest-micro services/orders -y
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This command creates: `package.json`, `tsconfig.json`, NestJS structure, and basic files.
|
|
23
|
+
**Without this command, the service cannot be built or run!**
|
|
24
|
+
|
|
25
|
+
- Services MUST be in `services/` directory
|
|
26
|
+
- User says "orders" → Generate path: `services/orders`
|
|
27
|
+
- Always include `-y` flag to skip prompts
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## NestJS Event Consumer Architecture
|
|
32
|
+
|
|
33
|
+
For NestJS event consumers, we use NestJS's application context to bridge
|
|
34
|
+
`@crossdelta/cloudevents` handlers with NestJS's dependency injection system.
|
|
35
|
+
|
|
36
|
+
### Entry Point (src/main.ts)
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import '@crossdelta/telemetry'
|
|
40
|
+
|
|
41
|
+
import { NestFactory } from '@nestjs/core'
|
|
42
|
+
import { AppModule } from './app.module'
|
|
43
|
+
import { EventsService } from './events/events.service'
|
|
44
|
+
|
|
45
|
+
async function bootstrap() {
|
|
46
|
+
const app = await NestFactory.create(AppModule)
|
|
47
|
+
const port = Number(process.env.MY_SERVICE_PORT) || 8080
|
|
48
|
+
|
|
49
|
+
// Get EventsService from DI container and start consuming
|
|
50
|
+
const eventsService = app.get(EventsService)
|
|
51
|
+
await eventsService.startConsumers()
|
|
52
|
+
|
|
53
|
+
await app.listen(port)
|
|
54
|
+
console.log(`Service running on http://localhost:${port}`)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
bootstrap()
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Events Module (src/events/events.module.ts)
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { Module } from '@nestjs/common'
|
|
66
|
+
import { EventsService } from './events.service'
|
|
67
|
+
|
|
68
|
+
@Module({
|
|
69
|
+
providers: [EventsService],
|
|
70
|
+
exports: [EventsService],
|
|
71
|
+
})
|
|
72
|
+
export class EventsModule {}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Events Service (src/events/events.service.ts)
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { Injectable, Logger } from '@nestjs/common'
|
|
81
|
+
import { consumeJetStreamStreams, ensureJetStreamStreams } from '@crossdelta/cloudevents'
|
|
82
|
+
|
|
83
|
+
@Injectable()
|
|
84
|
+
export class EventsService {
|
|
85
|
+
private readonly logger = new Logger(EventsService.name)
|
|
86
|
+
|
|
87
|
+
async startConsumers(): Promise<void> {
|
|
88
|
+
await ensureJetStreamStreams({
|
|
89
|
+
streams: [
|
|
90
|
+
{ stream: 'ORDERS', subjects: ['orders.*'] },
|
|
91
|
+
],
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
consumeJetStreamStreams({
|
|
95
|
+
streams: ['ORDERS'],
|
|
96
|
+
consumer: 'my-service',
|
|
97
|
+
discover: './src/events/**/*.event.ts',
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Accessing NestJS Services in Handlers
|
|
106
|
+
|
|
107
|
+
For handlers that need NestJS DI (database, external services), use the app context:
|
|
108
|
+
|
|
109
|
+
### App Context Singleton (src/app.context.ts)
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import type { INestApplication, Type } from '@nestjs/common'
|
|
113
|
+
|
|
114
|
+
let app: INestApplication
|
|
115
|
+
|
|
116
|
+
export const setAppContext = (nestApp: INestApplication): void => {
|
|
117
|
+
app = nestApp
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const getAppContext = (): INestApplication => {
|
|
121
|
+
if (!app) throw new Error('App context not initialized')
|
|
122
|
+
return app
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const getService = <T>(serviceClass: Type<T>): T => {
|
|
126
|
+
return getAppContext().get(serviceClass)
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Updated main.ts with App Context
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import '@crossdelta/telemetry'
|
|
134
|
+
|
|
135
|
+
import { NestFactory } from '@nestjs/core'
|
|
136
|
+
import { AppModule } from './app.module'
|
|
137
|
+
import { setAppContext } from './app.context'
|
|
138
|
+
import { EventsService } from './events/events.service'
|
|
139
|
+
|
|
140
|
+
async function bootstrap() {
|
|
141
|
+
const app = await NestFactory.create(AppModule)
|
|
142
|
+
const port = Number(process.env.MY_SERVICE_PORT) || 8080
|
|
143
|
+
|
|
144
|
+
// Make app context available to event handlers
|
|
145
|
+
setAppContext(app)
|
|
146
|
+
|
|
147
|
+
// Start event consumers
|
|
148
|
+
const eventsService = app.get(EventsService)
|
|
149
|
+
await eventsService.startConsumers()
|
|
150
|
+
|
|
151
|
+
await app.listen(port)
|
|
152
|
+
console.log(`Service running on http://localhost:${port}`)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
bootstrap()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Handler with DI Access (src/events/orders-created.event.ts)
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import { handleEvent } from '@crossdelta/cloudevents'
|
|
162
|
+
import { OrdersCreatedContract, type OrdersCreatedData } from '{{scope}}/contracts'
|
|
163
|
+
import { getService } from '../app.context'
|
|
164
|
+
import { OrdersService } from '../orders/orders.service'
|
|
165
|
+
|
|
166
|
+
export default handleEvent(OrdersCreatedContract, async (data: OrdersCreatedData) => {
|
|
167
|
+
// Get service from NestJS DI container
|
|
168
|
+
const ordersService = getService(OrdersService)
|
|
169
|
+
await ordersService.processOrder(data)
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Orders Service (src/orders/orders.service.ts)
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { Injectable, Logger } from '@nestjs/common'
|
|
177
|
+
import type { OrdersCreatedData } from '{{scope}}/contracts'
|
|
178
|
+
|
|
179
|
+
@Injectable()
|
|
180
|
+
export class OrdersService {
|
|
181
|
+
private readonly logger = new Logger(OrdersService.name)
|
|
182
|
+
|
|
183
|
+
async processOrder(data: OrdersCreatedData): Promise<void> {
|
|
184
|
+
this.logger.log(`Processing order: ${data.orderId}`)
|
|
185
|
+
// Business logic with full DI access
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## App Module Structure
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
// src/app.module.ts
|
|
196
|
+
import { Module } from '@nestjs/common'
|
|
197
|
+
import { AppController } from './app.controller'
|
|
198
|
+
import { EventsModule } from './events/events.module'
|
|
199
|
+
import { OrdersModule } from './orders/orders.module'
|
|
200
|
+
|
|
201
|
+
@Module({
|
|
202
|
+
imports: [EventsModule, OrdersModule],
|
|
203
|
+
controllers: [AppController],
|
|
204
|
+
})
|
|
205
|
+
export class AppModule {}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
// src/app.controller.ts
|
|
210
|
+
import { Controller, Get } from '@nestjs/common'
|
|
211
|
+
|
|
212
|
+
@Controller()
|
|
213
|
+
export class AppController {
|
|
214
|
+
@Get('health')
|
|
215
|
+
health() {
|
|
216
|
+
return { status: 'ok' }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Testing
|
|
224
|
+
|
|
225
|
+
### Unit Test for Service
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
// src/orders/orders.service.spec.ts
|
|
229
|
+
import { Test, TestingModule } from '@nestjs/testing'
|
|
230
|
+
import { OrdersService } from './orders.service'
|
|
231
|
+
|
|
232
|
+
describe('OrdersService', () => {
|
|
233
|
+
let service: OrdersService
|
|
234
|
+
|
|
235
|
+
beforeEach(async () => {
|
|
236
|
+
const module: TestingModule = await Test.createTestingModule({
|
|
237
|
+
providers: [OrdersService],
|
|
238
|
+
}).compile()
|
|
239
|
+
|
|
240
|
+
service = module.get<OrdersService>(OrdersService)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('should process order', async () => {
|
|
244
|
+
const mockData = {
|
|
245
|
+
orderId: 'ord_123',
|
|
246
|
+
customerId: 'cust_456',
|
|
247
|
+
total: 99.99,
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
await expect(service.processOrder(mockData)).resolves.not.toThrow()
|
|
251
|
+
})
|
|
252
|
+
})
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Dev Command
|
|
258
|
+
|
|
259
|
+
```json
|
|
260
|
+
{
|
|
261
|
+
"scripts": {
|
|
262
|
+
"start:dev": "nest start --watch"
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|