create-bcp-app 0.2.17 → 0.2.18

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 (3) hide show
  1. package/README.md +90 -189
  2. package/package.json +1 -1
  3. package/template/README.md +79 -289
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. It does not install the framework CLI globally.
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 local alias:
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.17` target:
67
+ Example for the `0.2.18` 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.17",
74
+ "frameworkPackage": "npm:@chidchanun/bcp@0.2.18",
77
75
  "createdWith": {
78
76
  "package": "create-bcp-app",
79
- "version": "0.2.17"
77
+ "version": "0.2.18"
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. It must not contain secrets and should normally be committed to source control.
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 `lib/auth.ts` and starter auth routes. BCP `0.2.5+` supports optional revocable server-side auth state, while `0.2.6+` adds permission/policy authorization plus same-origin/CSRF helpers.
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 scheduling
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
- ## Transactional Outbox & Events 0.2.12+
119
+ Durable Redis-compatible queues/schedules, workflow orchestration and transactional outbox/event delivery are available without forcing a Redis client dependency.
152
120
 
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
- ```
170
-
171
- ## Realtime Platform — 0.2.13+
121
+ ## Realtime
172
122
 
173
123
  ```ts
174
124
  import {
@@ -179,187 +129,138 @@ export const realtime =
179
129
  createRealtime();
180
130
  ```
181
131
 
182
- BCP does not install a WebSocket library. Adapt your selected provider to `RealtimeSocket`. SSE is available directly through `realtime.sse()`.
183
-
184
- ## Testing Platform — 0.2.14+
185
-
186
- ```ts
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
- });
204
-
205
- await expectResponse(
206
- await app.get("/api/health")
207
- )
208
- .status(200)
209
- .json({
210
- ok: true,
211
- });
212
- ```
213
-
214
- BCP testing helpers are runner-neutral and can be used with Node `node:test`, Vitest, Jest or another runner.
132
+ BCP does not install a WebSocket server library. Applications adapt their provider to `RealtimeSocket`; SSE is built in.
215
133
 
216
- ## Plugin & Module Platform — 0.2.15+
134
+ ## Testing
217
135
 
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
- });
136
+ `bcp/testing` provides request/route/page/auth/database/middleware/jobs/workflow/outbox/realtime test harnesses and does not require Jest or Vitest.
234
137
 
235
- const jobsPlugin =
236
- definePlugin({
237
- name: "jobs",
238
- requires: [
239
- "database",
240
- ],
241
- });
138
+ ## Plugins
242
139
 
243
- export const plugins =
244
- createPluginHost({
245
- plugins: [
246
- jobsPlugin,
247
- databasePlugin,
248
- ],
249
- });
250
- ```
140
+ `bcp/plugins` provides dependency ordering, module composition, lifecycle hooks, config parsing, shared services and async hooks.
251
141
 
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
- BCP does not install or own the Redis client. Applications remain responsible for credentials, TLS, Cluster/Sentinel configuration, reconnect behavior and connection shutdown.
153
+ Multi-instance applications can use Redis-compatible cache and lock adapters for distributed cache-fill coordination.
275
154
 
276
- ## Observability Platform v3 — 0.2.17+
277
-
278
- Metrics and health remain available through the same entrypoint:
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
161
 
288
- Create a tracer:
289
-
290
- ```ts
291
162
  export const tracer =
292
163
  createTracer({
293
164
  serviceName: "my-app",
294
165
  });
295
166
  ```
296
167
 
297
- Trace incoming HTTP requests with Middleware System v2:
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
- createRequestTracingMiddleware,
302
- } from "bcp/observability";
176
+ createDeploymentRuntime,
177
+ } from "bcp/deployment";
303
178
 
304
- export const middleware =
305
- createRequestTracingMiddleware(
306
- tracer
307
- );
179
+ export const deployment =
180
+ createDeploymentRuntime({
181
+ serviceName: "my-app",
182
+ });
308
183
  ```
309
184
 
310
- The middleware understands W3C `traceparent`, preserves `x-correlation-id`, creates a server span and returns the current trace headers on the response.
311
-
312
- For jobs/workflows/events/realtime payloads use explicit trace carriers:
185
+ Register shared dependencies before components that use them:
313
186
 
314
187
  ```ts
315
- import {
316
- createTraceCarrier,
317
- runWithTraceCarrier,
318
- } from "bcp/observability";
188
+ deployment.addResource({
189
+ name: "database",
190
+
191
+ async start() {
192
+ await db.connect();
193
+ },
194
+
195
+ ready() {
196
+ return db.status === "ready";
197
+ },
319
198
 
320
- const trace =
321
- createTraceCarrier();
199
+ async stop() {
200
+ await db.close();
201
+ },
202
+ });
322
203
 
323
- await jobs.enqueue(
324
- "order.process",
325
- {
326
- orderId,
327
- trace,
328
- }
329
- );
204
+ deployment.addResource({
205
+ name: "workers",
206
+
207
+ start() {
208
+ worker = jobs.startWorker();
209
+ },
210
+
211
+ async stop() {
212
+ await worker.stop();
213
+ },
214
+ });
215
+
216
+ await deployment.start();
330
217
  ```
331
218
 
332
- Consumer:
219
+ Startup follows registration order and shutdown reverses it. This naturally stops workers before database/cache/Redis connections.
220
+
221
+ Readiness endpoint:
333
222
 
334
223
  ```ts
335
- await runWithTraceCarrier(
336
- payload.trace,
337
- () =>
338
- tracer.withSpan(
339
- "job order.process",
340
- handler,
341
- {
342
- kind: "consumer",
343
- }
344
- )
345
- );
224
+ import {
225
+ createDeploymentReadinessResponse,
226
+ } from "bcp/deployment";
227
+
228
+ export function GET() {
229
+ return createDeploymentReadinessResponse(
230
+ deployment
231
+ );
232
+ }
346
233
  ```
347
234
 
348
- Use `getTraceLogFields()` to add `traceId`, `spanId` and `correlationId` to structured logs.
235
+ Runtime identity can use:
349
236
 
350
- BCP does not install OpenTelemetry or a vendor APM package. Implement `TraceSpanExporter` when production spans need to be sent to an external collector.
237
+ ```text
238
+ BCP_DEPLOYMENT_ID
239
+ BCP_INSTANCE_ID
240
+ BCP_RELEASE
241
+ NODE_ENV
242
+ BCP_SHUTDOWN_TIMEOUT_MS
243
+ ```
351
244
 
352
- ## Storage providers
245
+ Install graceful signal handling with:
353
246
 
354
- Supported presets are Local Server, Amazon S3 and Cloudflare R2. Storage credentials are server-only and must not use `BCP_PUBLIC_*` variables.
247
+ ```ts
248
+ const removeSignals =
249
+ deployment.installSignalHandlers();
250
+ ```
251
+
252
+ Default signals are `SIGTERM` and `SIGINT`.
355
253
 
356
254
  ## Application packaging
357
255
 
358
256
  ```bash
257
+ npm run build
359
258
  npm run package
360
259
  ```
361
260
 
362
- The deployment package excludes application `devDependencies` and project `.env` values. Supply real secrets through the deployment environment.
261
+ The deployment package excludes application `devDependencies` and project `.env` values. Supply secrets through the deployment environment.
262
+
263
+ BCP `0.2.18` prepared framework packages use compiled ESM runtime files for the main server entrypoints including config, auth, observability, deployment, server and middleware.
363
264
 
364
265
  ## Project generators
365
266
 
@@ -387,5 +288,5 @@ npm run generate -- migration create_users
387
288
  For prerelease/local package verification:
388
289
 
389
290
  ```bash
390
- npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.17.tgz
291
+ npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.18.tgz
391
292
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bcp-app",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
4
4
  "description": "Create a new BCP Framework application.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -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 BCP 0.2.5+
30
+ ## Authentication and authorization
31
31
 
32
- JWT Cookie projects can opt into revocable server-side session state with `createAuth()` and `AuthSessionStore`.
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
- ## Authorization & request security — BCP 0.2.6+
34
+ ## Database
35
35
 
36
- Use permission guards/resource policies from `bcp/auth`, and same-origin/CSRF protection from `bcp/server`. Authorization must remain server-side.
36
+ MySQL, PostgreSQL and SQLite projects expose the BCP database platform through `bcp/database`.
37
37
 
38
- ## Observability BCP 0.2.7+
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, compensation, run leases and optional durable queue execution.
50
+ Durable jobs support leases, heartbeat, stale recovery and DLQ. Workflows support sequential/parallel steps, retries, persisted delays and compensation.
109
51
 
110
- ## Transactional Outbox & Events — BCP 0.2.12+
52
+ ## Transactional events
111
53
 
112
- Use `bcp/events` when application data and an integration event must commit atomically in the same SQL transaction.
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
- ```ts
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,137 @@ export const realtime =
144
64
  createRealtime();
145
65
  ```
146
66
 
147
- Channels/rooms:
67
+ BCP does not install a WebSocket server library. Adapt the selected provider through `RealtimeSocket`; SSE is built in.
148
68
 
149
- ```ts
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
- BCP does not install a WebSocket server dependency. Adapt the selected provider to `RealtimeSocket`. SSE is built in through `realtime.sse()`.
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
- For multi-instance deployment, replace the memory broker/presence store with shared `RealtimeBroker` and `RealtimePresenceStore` implementations.
73
+ ## Plugins
169
74
 
170
- ## Testing Platform BCP 0.2.14+
75
+ `bcp/plugins` provides reusable server-side plugins/modules, dependency ordering, lifecycle hooks, config parsing, shared services and awaited hooks.
171
76
 
172
- Use server-only `bcp/testing` to exercise framework contracts without adding a BCP-specific test runner.
77
+ ## Cache Platform v2
173
78
 
174
79
  ```ts
175
80
  import {
176
- createRouteTestHandler,
177
- createTestApp,
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
- await expectResponse(
194
- await app.get("/api/health")
195
- )
196
- .status(200)
197
- .json({
198
- ok: true,
199
- });
84
+ export const cache =
85
+ createCacheStore();
200
86
  ```
201
87
 
202
- BCP does not require Jest or Vitest; these helpers work with Node `node:test` or another runner.
88
+ Use Redis-compatible cache/lock adapters for multi-instance cache-fill coordination when needed.
203
89
 
204
- ## Plugin & Module Platform — BCP 0.2.15+
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
- createPluginHost,
211
- definePlugin,
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 plugins =
234
- createPluginHost({
235
- plugins: [
236
- jobsPlugin,
237
- databasePlugin,
238
- ],
97
+ export const tracer =
98
+ createTracer({
99
+ serviceName: "bcp-app",
239
100
  });
240
101
  ```
241
102
 
242
- Plugin startup follows dependency order and shutdown reverses it. Plugins can use `setup/start/stop/dispose`, config parsers, shared services and async hooks.
103
+ Tracing supports AsyncLocalStorage context, W3C `traceparent`, correlation IDs, request tracing, trace carriers and provider-neutral exporters.
243
104
 
244
- ## Cache Platform v2 — BCP 0.2.16+
105
+ ## Deployment Platform v2 — BCP 0.2.18+
245
106
 
246
- Use `createCacheStore()` for async cache-aside loading, shared adapters and distributed cache-fill coordination.
107
+ Use `bcp/deployment` to manage production resource lifecycle:
247
108
 
248
109
  ```ts
249
110
  import {
250
- createCacheStore,
251
- } from "bcp/cache";
111
+ createDeploymentRuntime,
112
+ } from "bcp/deployment";
252
113
 
253
- export const cache =
254
- createCacheStore();
255
- ```
256
-
257
- ```ts
258
- const user =
259
- await cache.getOrSet(
260
- "user:42",
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
- For multiple instances, connect a shared cache and lock provider:
120
+ Register dependencies first:
271
121
 
272
122
  ```ts
273
- import {
274
- createRedisCacheAdapter,
275
- createRedisCacheLockAdapter,
276
- } from "bcp/cache";
123
+ deployment.addResource({
124
+ name: "database",
277
125
 
278
- const redisCache =
279
- createRedisCacheAdapter({
280
- client: redisClient,
281
- });
126
+ async start() {
127
+ await db.connect();
128
+ },
282
129
 
283
- const redisLock =
284
- createRedisCacheLockAdapter({
285
- client: redisClient,
286
- });
130
+ ready() {
131
+ return db.status === "ready";
132
+ },
287
133
 
288
- export const cache =
289
- createCacheStore({
290
- adapter: redisCache,
291
- lock: redisLock,
292
- });
134
+ async stop() {
135
+ await db.close();
136
+ },
137
+ });
293
138
  ```
294
139
 
295
- BCP does not install or own a Redis client. The default adapter namespace is `bcp:{cache}`. The original `cache()` and `dedupe()` APIs remain available for backward-compatible process-local caching.
140
+ Register workers/realtime services afterward so reverse-order shutdown stops them before their shared database/cache/Redis dependencies.
296
141
 
297
- ## Observability Platform v3 — BCP 0.2.17+
298
-
299
- Use the existing `bcp/observability` entrypoint for tracing as well as metrics and health.
142
+ Start runtime:
300
143
 
301
144
  ```ts
302
- import {
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
- Trace incoming Middleware System v2 requests:
148
+ Readiness endpoint:
313
149
 
314
150
  ```ts
315
151
  import {
316
- createRequestTracingMiddleware,
317
- } from "bcp/observability";
152
+ createDeploymentReadinessResponse,
153
+ } from "bcp/deployment";
318
154
 
319
- export const middleware =
320
- createRequestTracingMiddleware(
321
- tracer
155
+ export function GET() {
156
+ return createDeploymentReadinessResponse(
157
+ deployment
322
158
  );
159
+ }
323
160
  ```
324
161
 
325
- The middleware continues valid W3C `traceparent` headers, preserves `x-correlation-id`, creates a server span and includes active trace headers in the response.
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
- await tracer.withSpan(
331
- "order.checkout",
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
- For jobs, workflows, events and realtime payloads, propagate context explicitly:
169
+ Default signals are `SIGTERM` and `SIGINT`.
345
170
 
346
- ```ts
347
- import {
348
- createTraceCarrier,
349
- runWithTraceCarrier,
350
- } from "bcp/observability";
171
+ Deployment identity can be supplied through:
351
172
 
352
- const trace =
353
- createTraceCarrier();
354
-
355
- await jobs.enqueue(
356
- "order.process",
357
- {
358
- orderId,
359
- trace,
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
- Consumer:
181
+ ## Production build
365
182
 
366
- ```ts
367
- await runWithTraceCarrier(
368
- payload.trace,
369
- () =>
370
- tracer.withSpan(
371
- "job order.process",
372
- handler,
373
- {
374
- kind: "consumer",
375
- }
376
- )
377
- );
183
+ ```bash
184
+ npm run build
185
+ npm start
378
186
  ```
379
187
 
380
- Use `getTraceLogFields()` to attach `traceId`, `spanId` and `correlationId` to structured logs.
381
-
382
- BCP does not install OpenTelemetry or a vendor APM SDK. Production collector integration is application-owned through `TraceSpanExporter`.
383
-
384
- ## Generate framework files
188
+ ## Deployment package
385
189
 
386
190
  ```bash
387
- npm run generate -- page dashboard/users
388
- npm run generate -- api users
389
- npm run generate -- middleware
390
- npm run generate -- migration create_users
191
+ npm run package
391
192
  ```
392
193
 
194
+ BCP excludes project `.env` files and application `devDependencies` from the deployment package. Supply secrets through the deployment environment.
195
+
196
+ BCP 0.2.18 prepared framework packages use compiled `.mjs` runtimes for the main server entrypoints, including config, auth, observability, deployment, server and middleware.
197
+
393
198
  ## Direct CLI usage
394
199
 
395
200
  For PowerShell:
@@ -403,18 +208,3 @@ npm exec -- bcp-framework dev
403
208
  npm exec -- bcp-framework build
404
209
  npm exec -- bcp-framework package
405
210
  ```
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.