create-bcp-app 0.2.17 → 0.2.19
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 +101 -187
- package/package.json +1 -1
- package/template/README.md +84 -288
package/README.md
CHANGED
|
@@ -10,9 +10,7 @@ npm run dev
|
|
|
10
10
|
|
|
11
11
|
## Project-local BCP CLI
|
|
12
12
|
|
|
13
|
-
`create-bcp-app` installs BCP Framework as a project-local dependency.
|
|
14
|
-
|
|
15
|
-
Generated npm scripts use `bcp` because npm places `node_modules/.bin` on the script `PATH`:
|
|
13
|
+
`create-bcp-app` installs BCP Framework as a project-local dependency. Generated npm scripts use the local CLI:
|
|
16
14
|
|
|
17
15
|
```json
|
|
18
16
|
{
|
|
@@ -28,7 +26,7 @@ Generated npm scripts use `bcp` because npm places `node_modules/.bin` on the sc
|
|
|
28
26
|
}
|
|
29
27
|
```
|
|
30
28
|
|
|
31
|
-
For direct PowerShell usage, prefer the collision-free
|
|
29
|
+
For direct PowerShell usage, prefer the collision-free alias:
|
|
32
30
|
|
|
33
31
|
```powershell
|
|
34
32
|
npm exec -- bcp-framework --version
|
|
@@ -66,17 +64,17 @@ Select storage provider:
|
|
|
66
64
|
|
|
67
65
|
New projects include `bcp.project.json`.
|
|
68
66
|
|
|
69
|
-
Example for the `0.2.
|
|
67
|
+
Example for the `0.2.19` target:
|
|
70
68
|
|
|
71
69
|
```json
|
|
72
70
|
{
|
|
73
71
|
"schemaVersion": 1,
|
|
74
72
|
"framework": "bcp",
|
|
75
73
|
"projectName": "my-app",
|
|
76
|
-
"frameworkPackage": "npm:@chidchanun/bcp@0.2.
|
|
74
|
+
"frameworkPackage": "npm:@chidchanun/bcp@0.2.19",
|
|
77
75
|
"createdWith": {
|
|
78
76
|
"package": "create-bcp-app",
|
|
79
|
-
"version": "0.2.
|
|
77
|
+
"version": "0.2.19"
|
|
80
78
|
},
|
|
81
79
|
"packageManager": "npm",
|
|
82
80
|
"presets": {
|
|
@@ -88,7 +86,7 @@ Example for the `0.2.17` target:
|
|
|
88
86
|
}
|
|
89
87
|
```
|
|
90
88
|
|
|
91
|
-
This manifest records scaffold identity only.
|
|
89
|
+
This manifest records scaffold identity only. Do not place secrets in it.
|
|
92
90
|
|
|
93
91
|
## Database presets
|
|
94
92
|
|
|
@@ -104,71 +102,23 @@ For MySQL, PostgreSQL and SQLite, generated `lib/database.ts` exposes BCP databa
|
|
|
104
102
|
|
|
105
103
|
## Authentication and security
|
|
106
104
|
|
|
107
|
-
The JWT Cookie preset creates
|
|
105
|
+
The JWT Cookie preset creates starter authentication code. BCP supports revocable session stores, permission/policy authorization, route guards and same-origin/CSRF helpers.
|
|
108
106
|
|
|
109
|
-
## Background jobs and
|
|
107
|
+
## Background jobs, workflows and events
|
|
110
108
|
|
|
111
109
|
```ts
|
|
112
110
|
import {
|
|
113
111
|
createJobQueue,
|
|
114
112
|
createJobScheduler,
|
|
115
113
|
} from "bcp/jobs";
|
|
116
|
-
|
|
117
|
-
export const jobs =
|
|
118
|
-
createJobQueue();
|
|
119
|
-
|
|
120
|
-
export const scheduler =
|
|
121
|
-
createJobScheduler({
|
|
122
|
-
queue: jobs,
|
|
123
|
-
});
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
`0.2.10+` adds visibility leases, heartbeat renewal, stale-running recovery, DLQ/requeue, retention cleanup and Redis-compatible durable adapters.
|
|
127
|
-
|
|
128
|
-
## Workflow orchestration — 0.2.11+
|
|
129
|
-
|
|
130
|
-
```ts
|
|
131
114
|
import {
|
|
132
115
|
createWorkflow,
|
|
133
116
|
} from "bcp/workflow";
|
|
134
|
-
|
|
135
|
-
export const onboarding =
|
|
136
|
-
createWorkflow(
|
|
137
|
-
"user.onboarding",
|
|
138
|
-
workflow => {
|
|
139
|
-
workflow.step(
|
|
140
|
-
"profile",
|
|
141
|
-
createProfile
|
|
142
|
-
);
|
|
143
|
-
workflow.delay(
|
|
144
|
-
"cooldown",
|
|
145
|
-
1_000
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
);
|
|
149
117
|
```
|
|
150
118
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
```ts
|
|
154
|
-
await db.transaction(
|
|
155
|
-
async tx => {
|
|
156
|
-
await tx.execute(
|
|
157
|
-
"INSERT INTO orders ..."
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
await outbox.publish(
|
|
161
|
-
tx,
|
|
162
|
-
"order.created",
|
|
163
|
-
{
|
|
164
|
-
orderId: 42,
|
|
165
|
-
}
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
```
|
|
119
|
+
Durable Redis-compatible queues/schedules, workflow orchestration and transactional outbox/event delivery are available without forcing a Redis client dependency.
|
|
170
120
|
|
|
171
|
-
## Realtime
|
|
121
|
+
## Realtime
|
|
172
122
|
|
|
173
123
|
```ts
|
|
174
124
|
import {
|
|
@@ -179,187 +129,151 @@ export const realtime =
|
|
|
179
129
|
createRealtime();
|
|
180
130
|
```
|
|
181
131
|
|
|
182
|
-
BCP does not install a WebSocket library.
|
|
132
|
+
BCP does not install a WebSocket server library. Applications adapt their provider to `RealtimeSocket`; SSE is built in.
|
|
183
133
|
|
|
184
|
-
## Testing
|
|
134
|
+
## Testing
|
|
185
135
|
|
|
186
|
-
|
|
187
|
-
import {
|
|
188
|
-
createRouteTestHandler,
|
|
189
|
-
createTestApp,
|
|
190
|
-
expectResponse,
|
|
191
|
-
} from "bcp/testing";
|
|
192
|
-
|
|
193
|
-
const app =
|
|
194
|
-
createTestApp({
|
|
195
|
-
handler:
|
|
196
|
-
createRouteTestHandler({
|
|
197
|
-
GET() {
|
|
198
|
-
return {
|
|
199
|
-
ok: true,
|
|
200
|
-
};
|
|
201
|
-
},
|
|
202
|
-
}),
|
|
203
|
-
});
|
|
136
|
+
`bcp/testing` provides request/route/page/auth/database/middleware/jobs/workflow/outbox/realtime test harnesses and does not require Jest or Vitest.
|
|
204
137
|
|
|
205
|
-
|
|
206
|
-
await app.get("/api/health")
|
|
207
|
-
)
|
|
208
|
-
.status(200)
|
|
209
|
-
.json({
|
|
210
|
-
ok: true,
|
|
211
|
-
});
|
|
212
|
-
```
|
|
138
|
+
## Plugins
|
|
213
139
|
|
|
214
|
-
|
|
140
|
+
`bcp/plugins` provides dependency ordering, module composition, lifecycle hooks, config parsing, shared services and async hooks.
|
|
215
141
|
|
|
216
|
-
##
|
|
217
|
-
|
|
218
|
-
```ts
|
|
219
|
-
import {
|
|
220
|
-
createPluginHost,
|
|
221
|
-
definePlugin,
|
|
222
|
-
} from "bcp/plugins";
|
|
223
|
-
|
|
224
|
-
const databasePlugin =
|
|
225
|
-
definePlugin({
|
|
226
|
-
name: "database",
|
|
227
|
-
setup(context) {
|
|
228
|
-
context.services.provide(
|
|
229
|
-
"database",
|
|
230
|
-
db
|
|
231
|
-
);
|
|
232
|
-
},
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
const jobsPlugin =
|
|
236
|
-
definePlugin({
|
|
237
|
-
name: "jobs",
|
|
238
|
-
requires: [
|
|
239
|
-
"database",
|
|
240
|
-
],
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
export const plugins =
|
|
244
|
-
createPluginHost({
|
|
245
|
-
plugins: [
|
|
246
|
-
jobsPlugin,
|
|
247
|
-
databasePlugin,
|
|
248
|
-
],
|
|
249
|
-
});
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
## Cache Platform v2 — 0.2.16+
|
|
142
|
+
## Cache Platform v2
|
|
253
143
|
|
|
254
144
|
```ts
|
|
255
145
|
import {
|
|
256
146
|
createCacheStore,
|
|
257
|
-
createRedisCacheAdapter,
|
|
258
|
-
createRedisCacheLockAdapter,
|
|
259
147
|
} from "bcp/cache";
|
|
260
148
|
|
|
261
149
|
export const cache =
|
|
262
|
-
createCacheStore(
|
|
263
|
-
adapter:
|
|
264
|
-
createRedisCacheAdapter({
|
|
265
|
-
client: redisClient,
|
|
266
|
-
}),
|
|
267
|
-
lock:
|
|
268
|
-
createRedisCacheLockAdapter({
|
|
269
|
-
client: redisClient,
|
|
270
|
-
}),
|
|
271
|
-
});
|
|
150
|
+
createCacheStore();
|
|
272
151
|
```
|
|
273
152
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
## Observability Platform v3 — 0.2.17+
|
|
153
|
+
Multi-instance applications can use Redis-compatible cache and lock adapters for distributed cache-fill coordination.
|
|
277
154
|
|
|
278
|
-
|
|
155
|
+
## Observability Platform v3
|
|
279
156
|
|
|
280
157
|
```ts
|
|
281
158
|
import {
|
|
282
|
-
createHealthRegistry,
|
|
283
|
-
createMetricsRegistry,
|
|
284
159
|
createTracer,
|
|
285
160
|
} from "bcp/observability";
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
Create a tracer:
|
|
289
161
|
|
|
290
|
-
```ts
|
|
291
162
|
export const tracer =
|
|
292
163
|
createTracer({
|
|
293
164
|
serviceName: "my-app",
|
|
294
165
|
});
|
|
295
166
|
```
|
|
296
167
|
|
|
297
|
-
|
|
168
|
+
Tracing supports W3C `traceparent`, correlation IDs, request middleware, explicit carriers for jobs/workflows/events/realtime and provider-neutral exporters.
|
|
169
|
+
|
|
170
|
+
## Deployment Platform v2 — 0.2.18+
|
|
171
|
+
|
|
172
|
+
Use `bcp/deployment` to coordinate application resources in production:
|
|
298
173
|
|
|
299
174
|
```ts
|
|
300
175
|
import {
|
|
301
|
-
|
|
302
|
-
} from "bcp/
|
|
176
|
+
createDeploymentRuntime,
|
|
177
|
+
} from "bcp/deployment";
|
|
303
178
|
|
|
304
|
-
export const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
);
|
|
179
|
+
export const deployment =
|
|
180
|
+
createDeploymentRuntime({
|
|
181
|
+
serviceName: "my-app",
|
|
182
|
+
});
|
|
308
183
|
```
|
|
309
184
|
|
|
310
|
-
|
|
185
|
+
Register shared dependencies before components that use them:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
deployment.addResource({
|
|
189
|
+
name: "database",
|
|
190
|
+
|
|
191
|
+
async start() {
|
|
192
|
+
await db.connect();
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
ready() {
|
|
196
|
+
return db.status === "ready";
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
async stop() {
|
|
200
|
+
await db.close();
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
deployment.addResource({
|
|
205
|
+
name: "workers",
|
|
206
|
+
|
|
207
|
+
start() {
|
|
208
|
+
worker = jobs.startWorker();
|
|
209
|
+
},
|
|
311
210
|
|
|
312
|
-
|
|
211
|
+
async stop() {
|
|
212
|
+
await worker.stop();
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
await deployment.start();
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Startup follows registration order and shutdown reverses it. This naturally stops workers before database/cache/Redis connections.
|
|
220
|
+
|
|
221
|
+
Readiness endpoint:
|
|
313
222
|
|
|
314
223
|
```ts
|
|
315
224
|
import {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
} from "bcp/observability";
|
|
225
|
+
createDeploymentReadinessResponse,
|
|
226
|
+
} from "bcp/deployment";
|
|
319
227
|
|
|
320
|
-
|
|
321
|
-
|
|
228
|
+
export function GET() {
|
|
229
|
+
return createDeploymentReadinessResponse(
|
|
230
|
+
deployment
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
```
|
|
322
234
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
235
|
+
Runtime identity can use:
|
|
236
|
+
|
|
237
|
+
```text
|
|
238
|
+
BCP_DEPLOYMENT_ID
|
|
239
|
+
BCP_INSTANCE_ID
|
|
240
|
+
BCP_RELEASE
|
|
241
|
+
NODE_ENV
|
|
242
|
+
BCP_SHUTDOWN_TIMEOUT_MS
|
|
330
243
|
```
|
|
331
244
|
|
|
332
|
-
|
|
245
|
+
Install graceful signal handling with:
|
|
333
246
|
|
|
334
247
|
```ts
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
() =>
|
|
338
|
-
tracer.withSpan(
|
|
339
|
-
"job order.process",
|
|
340
|
-
handler,
|
|
341
|
-
{
|
|
342
|
-
kind: "consumer",
|
|
343
|
-
}
|
|
344
|
-
)
|
|
345
|
-
);
|
|
248
|
+
const removeSignals =
|
|
249
|
+
deployment.installSignalHandlers();
|
|
346
250
|
```
|
|
347
251
|
|
|
348
|
-
|
|
252
|
+
Default signals are `SIGTERM` and `SIGINT`.
|
|
349
253
|
|
|
350
|
-
|
|
254
|
+
## Stability & API Freeze — 0.2.19
|
|
351
255
|
|
|
352
|
-
|
|
256
|
+
`0.2.19` keeps the `0.2.x` public package surface stable before the next platform baseline.
|
|
353
257
|
|
|
354
|
-
|
|
258
|
+
Framework maintainers can validate the frozen contract with:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
npm run api:check
|
|
262
|
+
npm run release:readiness
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Generated applications do not need to run these framework-repository release commands. Application code should continue importing documented `bcp/*` entrypoints rather than private framework source paths.
|
|
355
266
|
|
|
356
267
|
## Application packaging
|
|
357
268
|
|
|
358
269
|
```bash
|
|
270
|
+
npm run build
|
|
359
271
|
npm run package
|
|
360
272
|
```
|
|
361
273
|
|
|
362
|
-
The deployment package excludes application `devDependencies` and project `.env` values. Supply
|
|
274
|
+
The deployment package excludes application `devDependencies` and project `.env` values. Supply secrets through the deployment environment.
|
|
275
|
+
|
|
276
|
+
BCP `0.2.19` prepared framework packages preserve the compiled ESM runtime map introduced by Deployment Platform v2 for the main server entrypoints including config, auth, observability, deployment, server and middleware.
|
|
363
277
|
|
|
364
278
|
## Project generators
|
|
365
279
|
|
|
@@ -387,5 +301,5 @@ npm run generate -- migration create_users
|
|
|
387
301
|
For prerelease/local package verification:
|
|
388
302
|
|
|
389
303
|
```bash
|
|
390
|
-
npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.
|
|
304
|
+
npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.19.tgz
|
|
391
305
|
```
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -27,113 +27,33 @@ npm run update
|
|
|
27
27
|
|
|
28
28
|
Generated projects include `bcp.project.json` with non-secret scaffold metadata. Commit it with the project, but never put passwords, tokens or access keys in it.
|
|
29
29
|
|
|
30
|
-
## Authentication
|
|
30
|
+
## Authentication and authorization
|
|
31
31
|
|
|
32
|
-
JWT Cookie projects can
|
|
32
|
+
JWT Cookie projects can use `createAuth()` and optional `AuthSessionStore` revocation. Permission guards/resource policies live in `bcp/auth`; same-origin/CSRF helpers live in `bcp/server`.
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## Database
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
MySQL, PostgreSQL and SQLite projects expose the BCP database platform through `bcp/database`.
|
|
37
37
|
|
|
38
|
-
##
|
|
39
|
-
|
|
40
|
-
```ts
|
|
41
|
-
import {
|
|
42
|
-
createHealthRegistry,
|
|
43
|
-
createMetricsRegistry,
|
|
44
|
-
} from "bcp/observability";
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Background jobs — BCP 0.2.8+
|
|
38
|
+
## Jobs, scheduling and workflows
|
|
48
39
|
|
|
49
40
|
```ts
|
|
50
41
|
import {
|
|
51
42
|
createJobQueue,
|
|
52
|
-
} from "bcp/jobs";
|
|
53
|
-
|
|
54
|
-
export const jobs =
|
|
55
|
-
createJobQueue();
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Job scheduling — BCP 0.2.9+
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
import {
|
|
62
43
|
createJobScheduler,
|
|
63
44
|
} from "bcp/jobs";
|
|
64
|
-
|
|
65
|
-
export const scheduler =
|
|
66
|
-
createJobScheduler({
|
|
67
|
-
queue: jobs,
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Durable jobs — BCP 0.2.10+
|
|
72
|
-
|
|
73
|
-
Workers can use visibility leases, heartbeat renewal, stale recovery and DLQ/requeue. Redis-compatible adapters are available without forcing a Redis client dependency.
|
|
74
|
-
|
|
75
|
-
```ts
|
|
76
|
-
const worker =
|
|
77
|
-
jobs.startWorker({
|
|
78
|
-
workerId: "worker-a",
|
|
79
|
-
concurrency: 4,
|
|
80
|
-
visibilityTimeoutMs: 30_000,
|
|
81
|
-
heartbeatIntervalMs: 10_000,
|
|
82
|
-
});
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
## Workflow orchestration — BCP 0.2.11+
|
|
86
|
-
|
|
87
|
-
```ts
|
|
88
45
|
import {
|
|
89
46
|
createWorkflow,
|
|
90
47
|
} from "bcp/workflow";
|
|
91
|
-
|
|
92
|
-
export const onboarding =
|
|
93
|
-
createWorkflow(
|
|
94
|
-
"user.onboarding",
|
|
95
|
-
workflow => {
|
|
96
|
-
workflow.step(
|
|
97
|
-
"profile",
|
|
98
|
-
createProfile
|
|
99
|
-
);
|
|
100
|
-
workflow.delay(
|
|
101
|
-
"cooldown",
|
|
102
|
-
1_000
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
);
|
|
106
48
|
```
|
|
107
49
|
|
|
108
|
-
Workflows support sequential/parallel steps, retries, persisted delays
|
|
50
|
+
Durable jobs support leases, heartbeat, stale recovery and DLQ. Workflows support sequential/parallel steps, retries, persisted delays and compensation.
|
|
109
51
|
|
|
110
|
-
## Transactional
|
|
52
|
+
## Transactional events
|
|
111
53
|
|
|
112
|
-
Use `bcp/events` when
|
|
54
|
+
Use `bcp/events` when business data and an integration event must commit in the same SQL transaction. The outbox dispatcher can deliver through durable jobs or an application publisher after commit.
|
|
113
55
|
|
|
114
|
-
|
|
115
|
-
await db.transaction(
|
|
116
|
-
async tx => {
|
|
117
|
-
await tx.execute(
|
|
118
|
-
"INSERT INTO orders ..."
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
await outbox.publish(
|
|
122
|
-
tx,
|
|
123
|
-
"order.created",
|
|
124
|
-
{
|
|
125
|
-
orderId: 42,
|
|
126
|
-
}
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
);
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
After commit, `createOutboxDispatcher()` can deliver through durable jobs or a custom publisher.
|
|
133
|
-
|
|
134
|
-
## Realtime Platform — BCP 0.2.13+
|
|
135
|
-
|
|
136
|
-
Create a server-side realtime hub:
|
|
56
|
+
## Realtime
|
|
137
57
|
|
|
138
58
|
```ts
|
|
139
59
|
import {
|
|
@@ -144,252 +64,143 @@ export const realtime =
|
|
|
144
64
|
createRealtime();
|
|
145
65
|
```
|
|
146
66
|
|
|
147
|
-
|
|
67
|
+
BCP does not install a WebSocket server library. Adapt the selected provider through `RealtimeSocket`; SSE is built in.
|
|
148
68
|
|
|
149
|
-
|
|
150
|
-
const connection =
|
|
151
|
-
await realtime.connect();
|
|
152
|
-
|
|
153
|
-
await connection.join(
|
|
154
|
-
"orders:42"
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
await realtime.broadcast(
|
|
158
|
-
"orders:42",
|
|
159
|
-
"order.updated",
|
|
160
|
-
{
|
|
161
|
-
status: "paid",
|
|
162
|
-
}
|
|
163
|
-
);
|
|
164
|
-
```
|
|
69
|
+
## Testing
|
|
165
70
|
|
|
166
|
-
|
|
71
|
+
`bcp/testing` provides request/route/page/auth/database/middleware/jobs/workflow/outbox/realtime/SSE test helpers without requiring Jest or Vitest.
|
|
167
72
|
|
|
168
|
-
|
|
73
|
+
## Plugins
|
|
169
74
|
|
|
170
|
-
|
|
75
|
+
`bcp/plugins` provides reusable server-side plugins/modules, dependency ordering, lifecycle hooks, config parsing, shared services and awaited hooks.
|
|
171
76
|
|
|
172
|
-
|
|
77
|
+
## Cache Platform v2
|
|
173
78
|
|
|
174
79
|
```ts
|
|
175
80
|
import {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
expectResponse,
|
|
179
|
-
} from "bcp/testing";
|
|
180
|
-
|
|
181
|
-
const app =
|
|
182
|
-
createTestApp({
|
|
183
|
-
handler:
|
|
184
|
-
createRouteTestHandler({
|
|
185
|
-
GET() {
|
|
186
|
-
return {
|
|
187
|
-
ok: true,
|
|
188
|
-
};
|
|
189
|
-
},
|
|
190
|
-
}),
|
|
191
|
-
});
|
|
81
|
+
createCacheStore,
|
|
82
|
+
} from "bcp/cache";
|
|
192
83
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
)
|
|
196
|
-
.status(200)
|
|
197
|
-
.json({
|
|
198
|
-
ok: true,
|
|
199
|
-
});
|
|
84
|
+
export const cache =
|
|
85
|
+
createCacheStore();
|
|
200
86
|
```
|
|
201
87
|
|
|
202
|
-
|
|
88
|
+
Use Redis-compatible cache/lock adapters for multi-instance cache-fill coordination when needed.
|
|
203
89
|
|
|
204
|
-
##
|
|
205
|
-
|
|
206
|
-
Use `bcp/plugins` to compose reusable server-only application services with explicit dependencies.
|
|
90
|
+
## Observability Platform v3
|
|
207
91
|
|
|
208
92
|
```ts
|
|
209
93
|
import {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
} from "bcp/plugins";
|
|
213
|
-
|
|
214
|
-
const databasePlugin =
|
|
215
|
-
definePlugin({
|
|
216
|
-
name: "database",
|
|
217
|
-
setup(context) {
|
|
218
|
-
context.services.provide(
|
|
219
|
-
"database",
|
|
220
|
-
db
|
|
221
|
-
);
|
|
222
|
-
},
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
const jobsPlugin =
|
|
226
|
-
definePlugin({
|
|
227
|
-
name: "jobs",
|
|
228
|
-
requires: [
|
|
229
|
-
"database",
|
|
230
|
-
],
|
|
231
|
-
});
|
|
94
|
+
createTracer,
|
|
95
|
+
} from "bcp/observability";
|
|
232
96
|
|
|
233
|
-
export const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
jobsPlugin,
|
|
237
|
-
databasePlugin,
|
|
238
|
-
],
|
|
97
|
+
export const tracer =
|
|
98
|
+
createTracer({
|
|
99
|
+
serviceName: "bcp-app",
|
|
239
100
|
});
|
|
240
101
|
```
|
|
241
102
|
|
|
242
|
-
|
|
103
|
+
Tracing supports AsyncLocalStorage context, W3C `traceparent`, correlation IDs, request tracing, trace carriers and provider-neutral exporters.
|
|
243
104
|
|
|
244
|
-
##
|
|
105
|
+
## Deployment Platform v2 — BCP 0.2.18+
|
|
245
106
|
|
|
246
|
-
Use `
|
|
107
|
+
Use `bcp/deployment` to manage production resource lifecycle:
|
|
247
108
|
|
|
248
109
|
```ts
|
|
249
110
|
import {
|
|
250
|
-
|
|
251
|
-
} from "bcp/
|
|
252
|
-
|
|
253
|
-
export const cache =
|
|
254
|
-
createCacheStore();
|
|
255
|
-
```
|
|
111
|
+
createDeploymentRuntime,
|
|
112
|
+
} from "bcp/deployment";
|
|
256
113
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
() => loadUser(42),
|
|
262
|
-
{
|
|
263
|
-
ttlMs: 60_000,
|
|
264
|
-
tags: ["users"],
|
|
265
|
-
paths: ["/users/42"],
|
|
266
|
-
}
|
|
267
|
-
);
|
|
114
|
+
export const deployment =
|
|
115
|
+
createDeploymentRuntime({
|
|
116
|
+
serviceName: "bcp-app",
|
|
117
|
+
});
|
|
268
118
|
```
|
|
269
119
|
|
|
270
|
-
|
|
120
|
+
Register dependencies first:
|
|
271
121
|
|
|
272
122
|
```ts
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
createRedisCacheLockAdapter,
|
|
276
|
-
} from "bcp/cache";
|
|
123
|
+
deployment.addResource({
|
|
124
|
+
name: "database",
|
|
277
125
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
});
|
|
126
|
+
async start() {
|
|
127
|
+
await db.connect();
|
|
128
|
+
},
|
|
282
129
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
});
|
|
130
|
+
ready() {
|
|
131
|
+
return db.status === "ready";
|
|
132
|
+
},
|
|
287
133
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
});
|
|
134
|
+
async stop() {
|
|
135
|
+
await db.close();
|
|
136
|
+
},
|
|
137
|
+
});
|
|
293
138
|
```
|
|
294
139
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
## Observability Platform v3 — BCP 0.2.17+
|
|
140
|
+
Register workers/realtime services afterward so reverse-order shutdown stops them before their shared database/cache/Redis dependencies.
|
|
298
141
|
|
|
299
|
-
|
|
142
|
+
Start runtime:
|
|
300
143
|
|
|
301
144
|
```ts
|
|
302
|
-
|
|
303
|
-
createTracer,
|
|
304
|
-
} from "bcp/observability";
|
|
305
|
-
|
|
306
|
-
export const tracer =
|
|
307
|
-
createTracer({
|
|
308
|
-
serviceName: "my-app",
|
|
309
|
-
});
|
|
145
|
+
await deployment.start();
|
|
310
146
|
```
|
|
311
147
|
|
|
312
|
-
|
|
148
|
+
Readiness endpoint:
|
|
313
149
|
|
|
314
150
|
```ts
|
|
315
151
|
import {
|
|
316
|
-
|
|
317
|
-
} from "bcp/
|
|
152
|
+
createDeploymentReadinessResponse,
|
|
153
|
+
} from "bcp/deployment";
|
|
318
154
|
|
|
319
|
-
export
|
|
320
|
-
|
|
321
|
-
|
|
155
|
+
export function GET() {
|
|
156
|
+
return createDeploymentReadinessResponse(
|
|
157
|
+
deployment
|
|
322
158
|
);
|
|
159
|
+
}
|
|
323
160
|
```
|
|
324
161
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
Create child spans for application work:
|
|
162
|
+
Install graceful signal handling when the app owns process signals:
|
|
328
163
|
|
|
329
164
|
```ts
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
async () => {
|
|
333
|
-
await tracer.withSpan(
|
|
334
|
-
"database.order.insert",
|
|
335
|
-
createOrder,
|
|
336
|
-
{
|
|
337
|
-
kind: "client",
|
|
338
|
-
}
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
);
|
|
165
|
+
const removeSignals =
|
|
166
|
+
deployment.installSignalHandlers();
|
|
342
167
|
```
|
|
343
168
|
|
|
344
|
-
|
|
169
|
+
Default signals are `SIGTERM` and `SIGINT`.
|
|
345
170
|
|
|
346
|
-
|
|
347
|
-
import {
|
|
348
|
-
createTraceCarrier,
|
|
349
|
-
runWithTraceCarrier,
|
|
350
|
-
} from "bcp/observability";
|
|
351
|
-
|
|
352
|
-
const trace =
|
|
353
|
-
createTraceCarrier();
|
|
171
|
+
Deployment identity can be supplied through:
|
|
354
172
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
);
|
|
173
|
+
```text
|
|
174
|
+
BCP_DEPLOYMENT_ID
|
|
175
|
+
BCP_INSTANCE_ID
|
|
176
|
+
BCP_RELEASE
|
|
177
|
+
NODE_ENV
|
|
178
|
+
BCP_SHUTDOWN_TIMEOUT_MS
|
|
362
179
|
```
|
|
363
180
|
|
|
364
|
-
|
|
181
|
+
## Stability baseline — BCP 0.2.19
|
|
365
182
|
|
|
366
|
-
|
|
367
|
-
await runWithTraceCarrier(
|
|
368
|
-
payload.trace,
|
|
369
|
-
() =>
|
|
370
|
-
tracer.withSpan(
|
|
371
|
-
"job order.process",
|
|
372
|
-
handler,
|
|
373
|
-
{
|
|
374
|
-
kind: "consumer",
|
|
375
|
-
}
|
|
376
|
-
)
|
|
377
|
-
);
|
|
378
|
-
```
|
|
183
|
+
BCP `0.2.19` freezes the documented `0.2.x` public `bcp/*` entrypoints and prepared package-resolution contract before the next `0.3.0` baseline.
|
|
379
184
|
|
|
380
|
-
|
|
185
|
+
Application code should import documented public entrypoints and avoid private framework `packages/*` paths. This keeps applications compatible with the frozen `0.2.19` surface.
|
|
381
186
|
|
|
382
|
-
|
|
187
|
+
## Production build
|
|
383
188
|
|
|
384
|
-
|
|
189
|
+
```bash
|
|
190
|
+
npm run build
|
|
191
|
+
npm start
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Deployment package
|
|
385
195
|
|
|
386
196
|
```bash
|
|
387
|
-
npm run
|
|
388
|
-
npm run generate -- api users
|
|
389
|
-
npm run generate -- middleware
|
|
390
|
-
npm run generate -- migration create_users
|
|
197
|
+
npm run package
|
|
391
198
|
```
|
|
392
199
|
|
|
200
|
+
BCP excludes project `.env` files and application `devDependencies` from the deployment package. Supply secrets through the deployment environment.
|
|
201
|
+
|
|
202
|
+
BCP 0.2.19 preserves compiled `.mjs` runtimes for the main server entrypoints, including config, auth, observability, deployment, server and middleware.
|
|
203
|
+
|
|
393
204
|
## Direct CLI usage
|
|
394
205
|
|
|
395
206
|
For PowerShell:
|
|
@@ -403,18 +214,3 @@ npm exec -- bcp-framework dev
|
|
|
403
214
|
npm exec -- bcp-framework build
|
|
404
215
|
npm exec -- bcp-framework package
|
|
405
216
|
```
|
|
406
|
-
|
|
407
|
-
## Production build
|
|
408
|
-
|
|
409
|
-
```bash
|
|
410
|
-
npm run build
|
|
411
|
-
npm start
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
## Deployment package
|
|
415
|
-
|
|
416
|
-
```bash
|
|
417
|
-
npm run package
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
BCP excludes project `.env` files and application `devDependencies` from the deployment package. Supply secrets through the deployment environment.
|