create-bcp-app 0.2.16 → 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 +89 -263
  2. package/package.json +1 -1
  3. package/template/README.md +90 -260
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,13 +26,12 @@ 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
35
33
  npm exec -- bcp-framework doctor
36
34
  npm exec -- bcp-framework inspect
37
- npm exec -- bcp-framework generate page dashboard/users
38
35
  npm exec -- bcp-framework routes
39
36
  npm exec -- bcp-framework dev
40
37
  npm exec -- bcp-framework build
@@ -45,8 +42,6 @@ Microsoft SQL Server can install another Windows executable named `bcp.exe`, so
45
42
 
46
43
  ## Interactive choices
47
44
 
48
- The generator asks for optional application presets:
49
-
50
45
  ```text
51
46
  Use Tailwind CSS?
52
47
  Select a database:
@@ -69,17 +64,17 @@ Select storage provider:
69
64
 
70
65
  New projects include `bcp.project.json`.
71
66
 
72
- Example for the `0.2.16` target:
67
+ Example for the `0.2.18` target:
73
68
 
74
69
  ```json
75
70
  {
76
71
  "schemaVersion": 1,
77
72
  "framework": "bcp",
78
73
  "projectName": "my-app",
79
- "frameworkPackage": "npm:@chidchanun/bcp@0.2.16",
74
+ "frameworkPackage": "npm:@chidchanun/bcp@0.2.18",
80
75
  "createdWith": {
81
76
  "package": "create-bcp-app",
82
- "version": "0.2.16"
77
+ "version": "0.2.18"
83
78
  },
84
79
  "packageManager": "npm",
85
80
  "presets": {
@@ -91,7 +86,7 @@ Example for the `0.2.16` target:
91
86
  }
92
87
  ```
93
88
 
94
- 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.
95
90
 
96
91
  ## Database presets
97
92
 
@@ -107,88 +102,23 @@ For MySQL, PostgreSQL and SQLite, generated `lib/database.ts` exposes BCP databa
107
102
 
108
103
  ## Authentication and security
109
104
 
110
- 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.
111
-
112
- ## Observability
113
-
114
- ```ts
115
- import {
116
- createHealthRegistry,
117
- createMetricsRegistry,
118
- } from "bcp/observability";
119
- ```
105
+ The JWT Cookie preset creates starter authentication code. BCP supports revocable session stores, permission/policy authorization, route guards and same-origin/CSRF helpers.
120
106
 
121
- ## Background jobs and scheduling
107
+ ## Background jobs, workflows and events
122
108
 
123
109
  ```ts
124
110
  import {
125
111
  createJobQueue,
126
112
  createJobScheduler,
127
113
  } from "bcp/jobs";
128
-
129
- export const jobs =
130
- createJobQueue();
131
-
132
- export const scheduler =
133
- createJobScheduler({
134
- queue: jobs,
135
- });
136
- ```
137
-
138
- `0.2.10+` adds visibility leases, heartbeat renewal, stale-running recovery, DLQ/requeue, retention cleanup and Redis-compatible durable adapters.
139
-
140
- ## Workflow orchestration — 0.2.11+
141
-
142
- ```ts
143
114
  import {
144
115
  createWorkflow,
145
116
  } from "bcp/workflow";
146
-
147
- export const onboarding =
148
- createWorkflow(
149
- "user.onboarding",
150
- workflow => {
151
- workflow.step(
152
- "profile",
153
- createProfile
154
- );
155
- workflow.delay(
156
- "cooldown",
157
- 1_000
158
- );
159
- }
160
- );
161
117
  ```
162
118
 
163
- `bcp/workflow` supports sequential/parallel steps, retry, persisted delays, compensation and optional execution through `bcp/jobs`.
164
-
165
- ## 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.
166
120
 
167
- Applications using the SQL Database Platform can persist integration events in the same transaction as business data:
168
-
169
- ```ts
170
- await db.transaction(
171
- async tx => {
172
- await tx.execute(
173
- "INSERT INTO orders ..."
174
- );
175
-
176
- await outbox.publish(
177
- tx,
178
- "order.created",
179
- {
180
- orderId: 42,
181
- }
182
- );
183
- }
184
- );
185
- ```
186
-
187
- After commit, `createOutboxDispatcher()` can hand off events to durable jobs/custom publishers.
188
-
189
- ## Realtime Platform — 0.2.13+
190
-
191
- Generated applications can add server-side realtime channels without changing the scaffold preset model:
121
+ ## Realtime
192
122
 
193
123
  ```ts
194
124
  import {
@@ -199,242 +129,138 @@ export const realtime =
199
129
  createRealtime();
200
130
  ```
201
131
 
202
- Channel/room usage:
203
-
204
- ```ts
205
- const connection =
206
- await realtime.connect();
207
-
208
- await connection.join(
209
- "orders:42"
210
- );
211
-
212
- await realtime.broadcast(
213
- "orders:42",
214
- "order.updated",
215
- {
216
- status: "paid",
217
- }
218
- );
219
- ```
132
+ BCP does not install a WebSocket server library. Applications adapt their provider to `RealtimeSocket`; SSE is built in.
220
133
 
221
- BCP does not install a WebSocket library. Adapt your selected provider to `RealtimeSocket`. SSE is available directly through `realtime.sse()`.
134
+ ## Testing
222
135
 
223
- The memory broker/presence store are local-only. Multi-instance production deployments should provide shared `RealtimeBroker` and `RealtimePresenceStore` implementations.
136
+ `bcp/testing` provides request/route/page/auth/database/middleware/jobs/workflow/outbox/realtime test harnesses and does not require Jest or Vitest.
224
137
 
225
- ## Testing Platform — 0.2.14+
138
+ ## Plugins
226
139
 
227
- `bcp/testing` adds framework-native test helpers without requiring a specific test runner.
140
+ `bcp/plugins` provides dependency ordering, module composition, lifecycle hooks, config parsing, shared services and async hooks.
228
141
 
229
- Request/route example:
142
+ ## Cache Platform v2
230
143
 
231
144
  ```ts
232
145
  import {
233
- createRouteTestHandler,
234
- createTestApp,
235
- expectResponse,
236
- } from "bcp/testing";
237
-
238
- const app =
239
- createTestApp({
240
- handler:
241
- createRouteTestHandler({
242
- GET() {
243
- return {
244
- ok: true,
245
- };
246
- },
247
- }),
248
- });
146
+ createCacheStore,
147
+ } from "bcp/cache";
249
148
 
250
- await expectResponse(
251
- await app.get("/api/health")
252
- )
253
- .status(200)
254
- .json({
255
- ok: true,
256
- });
149
+ export const cache =
150
+ createCacheStore();
257
151
  ```
258
152
 
259
- Create a real signed BCP auth session for authenticated requests:
260
-
261
- ```ts
262
- import {
263
- createTestAuthSession,
264
- } from "bcp/testing";
265
-
266
- const session =
267
- await createTestAuthSession(
268
- {
269
- id: 42,
270
- role: "admin",
271
- },
272
- {
273
- secret:
274
- process.env.BCP_SESSION_SECRET,
275
- }
276
- );
277
-
278
- app.setCookie(
279
- session.cookieName,
280
- session.token
281
- );
282
- ```
153
+ Multi-instance applications can use Redis-compatible cache and lock adapters for distributed cache-fill coordination.
283
154
 
284
- Rollback database tests:
155
+ ## Observability Platform v3
285
156
 
286
157
  ```ts
287
158
  import {
288
- withTestTransaction,
289
- } from "bcp/testing";
290
-
291
- await withTestTransaction(
292
- db,
293
- async tx => {
294
- await tx.execute(
295
- "INSERT INTO users ..."
296
- );
297
- }
298
- );
299
- ```
300
-
301
- Infrastructure helpers include:
159
+ createTracer,
160
+ } from "bcp/observability";
302
161
 
303
- ```text
304
- createJobTestHarness()
305
- createWorkflowTestHarness()
306
- createOutboxTestHarness()
307
- createRealtimeTestSocket()
308
- createRealtimeTestHarness()
309
- readSseEvents()
310
- createFakeClock()
311
- createSequenceIdFactory()
312
- runTestMiddleware()
162
+ export const tracer =
163
+ createTracer({
164
+ serviceName: "my-app",
165
+ });
313
166
  ```
314
167
 
315
- `bcp/testing` is server-only. It can be used with Node `node:test`, Vitest, Jest or another runner; BCP does not install those runners as framework dependencies.
168
+ Tracing supports W3C `traceparent`, correlation IDs, request middleware, explicit carriers for jobs/workflows/events/realtime and provider-neutral exporters.
316
169
 
317
- ## Plugin & Module Platform — 0.2.15+
170
+ ## Deployment Platform v2 — 0.2.18+
318
171
 
319
- Use `bcp/plugins` to compose reusable server-side application modules with explicit lifecycle and dependencies.
172
+ Use `bcp/deployment` to coordinate application resources in production:
320
173
 
321
174
  ```ts
322
175
  import {
323
- createPluginHost,
324
- defineModule,
325
- definePlugin,
326
- } from "bcp/plugins";
327
-
328
- const databasePlugin =
329
- definePlugin({
330
- name: "database",
331
- setup(context) {
332
- context.services.provide(
333
- "database",
334
- db
335
- );
336
- },
337
- });
176
+ createDeploymentRuntime,
177
+ } from "bcp/deployment";
338
178
 
339
- const jobsPlugin =
340
- definePlugin({
341
- name: "jobs",
342
- requires: [
343
- "database",
344
- ],
179
+ export const deployment =
180
+ createDeploymentRuntime({
181
+ serviceName: "my-app",
345
182
  });
183
+ ```
346
184
 
347
- const backendModule =
348
- defineModule({
349
- name: "backend",
350
- plugins: [
351
- databasePlugin,
352
- jobsPlugin,
353
- ],
354
- });
185
+ Register shared dependencies before components that use them:
355
186
 
356
- const host =
357
- createPluginHost({
358
- modules: [
359
- backendModule,
360
- ],
361
- });
187
+ ```ts
188
+ deployment.addResource({
189
+ name: "database",
362
190
 
363
- await host.start();
364
- ```
191
+ async start() {
192
+ await db.connect();
193
+ },
365
194
 
366
- Plugins can use `setup/start/stop/dispose`, typed config parsers, a shared service registry and an awaited in-process hook bus. Required dependencies start first; shutdown runs in reverse order.
195
+ ready() {
196
+ return db.status === "ready";
197
+ },
367
198
 
368
- `bcp/plugins` is server-only and cannot be imported into page/client bundles.
199
+ async stop() {
200
+ await db.close();
201
+ },
202
+ });
369
203
 
370
- ## Cache Platform v2 — 0.2.16+
204
+ deployment.addResource({
205
+ name: "workers",
371
206
 
372
- Use the existing `bcp/cache` entrypoint for provider-neutral shared caching while keeping the original `cache()` and `dedupe()` APIs available.
207
+ start() {
208
+ worker = jobs.startWorker();
209
+ },
373
210
 
374
- ```ts
375
- import {
376
- createCacheStore,
377
- } from "bcp/cache";
211
+ async stop() {
212
+ await worker.stop();
213
+ },
214
+ });
378
215
 
379
- export const cache =
380
- createCacheStore();
216
+ await deployment.start();
381
217
  ```
382
218
 
383
- Cache-aside loading:
384
-
385
- ```ts
386
- const user =
387
- await cache.getOrSet(
388
- "user:42",
389
- () => loadUser(42),
390
- {
391
- ttlMs: 60_000,
392
- tags: ["users"],
393
- paths: ["/users/42"],
394
- }
395
- );
396
- ```
219
+ Startup follows registration order and shutdown reverses it. This naturally stops workers before database/cache/Redis connections.
397
220
 
398
- For multi-instance deployments, applications can supply Redis-compatible cache and lock adapters:
221
+ Readiness endpoint:
399
222
 
400
223
  ```ts
401
224
  import {
402
- createRedisCacheAdapter,
403
- createRedisCacheLockAdapter,
404
- } from "bcp/cache";
225
+ createDeploymentReadinessResponse,
226
+ } from "bcp/deployment";
405
227
 
406
- const redisCache =
407
- createRedisCacheAdapter({
408
- client: redisClient,
409
- });
228
+ export function GET() {
229
+ return createDeploymentReadinessResponse(
230
+ deployment
231
+ );
232
+ }
233
+ ```
410
234
 
411
- const redisLock =
412
- createRedisCacheLockAdapter({
413
- client: redisClient,
414
- });
235
+ Runtime identity can use:
415
236
 
416
- export const cache =
417
- createCacheStore({
418
- adapter: redisCache,
419
- lock: redisLock,
420
- });
237
+ ```text
238
+ BCP_DEPLOYMENT_ID
239
+ BCP_INSTANCE_ID
240
+ BCP_RELEASE
241
+ NODE_ENV
242
+ BCP_SHUTDOWN_TIMEOUT_MS
421
243
  ```
422
244
 
423
- BCP does not install or own the Redis client. Applications remain responsible for credentials, TLS, Cluster/Sentinel configuration, reconnect behavior and connection shutdown.
245
+ Install graceful signal handling with:
424
246
 
425
- `getOrSet()` provides local singleflight and can use distributed lock leases with heartbeat renewal to reduce cache stampedes across instances.
426
-
427
- ## Storage providers
247
+ ```ts
248
+ const removeSignals =
249
+ deployment.installSignalHandlers();
250
+ ```
428
251
 
429
- Supported presets are Local Server, Amazon S3 and Cloudflare R2. Storage credentials are server-only and must not use `BCP_PUBLIC_*` variables.
252
+ Default signals are `SIGTERM` and `SIGINT`.
430
253
 
431
254
  ## Application packaging
432
255
 
433
256
  ```bash
257
+ npm run build
434
258
  npm run package
435
259
  ```
436
260
 
437
- 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.
438
264
 
439
265
  ## Project generators
440
266
 
@@ -462,5 +288,5 @@ npm run generate -- migration create_users
462
288
  For prerelease/local package verification:
463
289
 
464
290
  ```bash
465
- npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.16.tgz
291
+ npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.18.tgz
466
292
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bcp-app",
3
- "version": "0.2.16",
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.
109
-
110
- ## Transactional Outbox & Events — BCP 0.2.12+
111
-
112
- Use `bcp/events` when application data and an integration event must commit atomically in the same SQL transaction.
113
-
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
- ```
50
+ Durable jobs support leases, heartbeat, stale recovery and DLQ. Workflows support sequential/parallel steps, retries, persisted delays and compensation.
131
51
 
132
- After commit, `createOutboxDispatcher()` can deliver through durable jobs or a custom publisher.
52
+ ## Transactional events
133
53
 
134
- ## Realtime Platform BCP 0.2.13+
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.
135
55
 
136
- Create a server-side realtime hub:
56
+ ## Realtime
137
57
 
138
58
  ```ts
139
59
  import {
@@ -144,224 +64,118 @@ 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
- Authentication tests can create a real signed BCP session:
203
-
204
- ```ts
205
- import {
206
- createTestAuthSession,
207
- } from "bcp/testing";
208
-
209
- const session =
210
- await createTestAuthSession(
211
- {
212
- id: 42,
213
- },
214
- {
215
- secret:
216
- process.env.BCP_SESSION_SECRET,
217
- }
218
- );
219
-
220
- app.setCookie(
221
- session.cookieName,
222
- session.token
223
- );
224
- ```
88
+ Use Redis-compatible cache/lock adapters for multi-instance cache-fill coordination when needed.
225
89
 
226
- Database tests can force rollback after assertions:
90
+ ## Observability Platform v3
227
91
 
228
92
  ```ts
229
93
  import {
230
- withTestTransaction,
231
- } from "bcp/testing";
232
-
233
- await withTestTransaction(
234
- db,
235
- async tx => {
236
- await tx.execute(
237
- "INSERT INTO users ..."
238
- );
239
- }
240
- );
241
- ```
94
+ createTracer,
95
+ } from "bcp/observability";
242
96
 
243
- Additional helpers include job/workflow/outbox harnesses, `runTestMiddleware()`, page loader/guard/action helpers, fake clocks and IDs, a fake `RealtimeSocket`, realtime event assertions and `readSseEvents()`.
97
+ export const tracer =
98
+ createTracer({
99
+ serviceName: "bcp-app",
100
+ });
101
+ ```
244
102
 
245
- BCP does not require Jest or Vitest; these helpers work with Node `node:test` or another runner.
103
+ Tracing supports AsyncLocalStorage context, W3C `traceparent`, correlation IDs, request tracing, trace carriers and provider-neutral exporters.
246
104
 
247
- ## Plugin & Module Platform — BCP 0.2.15+
105
+ ## Deployment Platform v2 — BCP 0.2.18+
248
106
 
249
- Use `bcp/plugins` to compose reusable server-only application services with explicit dependencies.
107
+ Use `bcp/deployment` to manage production resource lifecycle:
250
108
 
251
109
  ```ts
252
110
  import {
253
- createPluginHost,
254
- definePlugin,
255
- } from "bcp/plugins";
256
-
257
- const databasePlugin =
258
- definePlugin({
259
- name: "database",
260
- setup(context) {
261
- context.services.provide(
262
- "database",
263
- db
264
- );
265
- },
266
- });
267
-
268
- const jobsPlugin =
269
- definePlugin({
270
- name: "jobs",
271
- requires: [
272
- "database",
273
- ],
274
- });
111
+ createDeploymentRuntime,
112
+ } from "bcp/deployment";
275
113
 
276
- export const plugins =
277
- createPluginHost({
278
- plugins: [
279
- jobsPlugin,
280
- databasePlugin,
281
- ],
114
+ export const deployment =
115
+ createDeploymentRuntime({
116
+ serviceName: "bcp-app",
282
117
  });
283
118
  ```
284
119
 
285
- Plugin startup follows dependency order and shutdown reverses it. Plugins can use `setup/start/stop/dispose`, config parsers, shared services and async hooks.
120
+ Register dependencies first:
286
121
 
287
- Use `defineModule()` when a reusable package needs to bundle multiple plugin definitions into one named module.
122
+ ```ts
123
+ deployment.addResource({
124
+ name: "database",
288
125
 
289
- `bcp/plugins` is server-only and cannot be imported from page/client bundles.
126
+ async start() {
127
+ await db.connect();
128
+ },
290
129
 
291
- ## Cache Platform v2 — BCP 0.2.16+
130
+ ready() {
131
+ return db.status === "ready";
132
+ },
292
133
 
293
- Use `createCacheStore()` for async cache-aside loading, shared adapters and distributed cache-fill coordination.
134
+ async stop() {
135
+ await db.close();
136
+ },
137
+ });
138
+ ```
294
139
 
295
- ```ts
296
- import {
297
- createCacheStore,
298
- } from "bcp/cache";
140
+ Register workers/realtime services afterward so reverse-order shutdown stops them before their shared database/cache/Redis dependencies.
299
141
 
300
- export const cache =
301
- createCacheStore();
302
- ```
142
+ Start runtime:
303
143
 
304
144
  ```ts
305
- const user =
306
- await cache.getOrSet(
307
- "user:42",
308
- () => loadUser(42),
309
- {
310
- ttlMs: 60_000,
311
- tags: ["users"],
312
- paths: ["/users/42"],
313
- }
314
- );
145
+ await deployment.start();
315
146
  ```
316
147
 
317
- For multiple instances, connect a shared cache and lock provider:
148
+ Readiness endpoint:
318
149
 
319
150
  ```ts
320
151
  import {
321
- createRedisCacheAdapter,
322
- createRedisCacheLockAdapter,
323
- } from "bcp/cache";
324
-
325
- const redisCache =
326
- createRedisCacheAdapter({
327
- client: redisClient,
328
- });
152
+ createDeploymentReadinessResponse,
153
+ } from "bcp/deployment";
329
154
 
330
- const redisLock =
331
- createRedisCacheLockAdapter({
332
- client: redisClient,
333
- });
334
-
335
- export const cache =
336
- createCacheStore({
337
- adapter: redisCache,
338
- lock: redisLock,
339
- });
155
+ export function GET() {
156
+ return createDeploymentReadinessResponse(
157
+ deployment
158
+ );
159
+ }
340
160
  ```
341
161
 
342
- 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.
343
-
344
- ## Generate framework files
162
+ Install graceful signal handling when the app owns process signals:
345
163
 
346
- ```bash
347
- npm run generate -- page dashboard/users
348
- npm run generate -- api users
349
- npm run generate -- middleware
350
- npm run generate -- migration create_users
164
+ ```ts
165
+ const removeSignals =
166
+ deployment.installSignalHandlers();
351
167
  ```
352
168
 
353
- ## Direct CLI usage
169
+ Default signals are `SIGTERM` and `SIGINT`.
354
170
 
355
- For PowerShell:
171
+ Deployment identity can be supplied through:
356
172
 
357
- ```powershell
358
- npm exec -- bcp-framework --version
359
- npm exec -- bcp-framework doctor
360
- npm exec -- bcp-framework inspect
361
- npm exec -- bcp-framework routes
362
- npm exec -- bcp-framework dev
363
- npm exec -- bcp-framework build
364
- npm exec -- bcp-framework package
173
+ ```text
174
+ BCP_DEPLOYMENT_ID
175
+ BCP_INSTANCE_ID
176
+ BCP_RELEASE
177
+ NODE_ENV
178
+ BCP_SHUTDOWN_TIMEOUT_MS
365
179
  ```
366
180
 
367
181
  ## Production build
@@ -378,3 +192,19 @@ npm run package
378
192
  ```
379
193
 
380
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
+
198
+ ## Direct CLI usage
199
+
200
+ For PowerShell:
201
+
202
+ ```powershell
203
+ npm exec -- bcp-framework --version
204
+ npm exec -- bcp-framework doctor
205
+ npm exec -- bcp-framework inspect
206
+ npm exec -- bcp-framework routes
207
+ npm exec -- bcp-framework dev
208
+ npm exec -- bcp-framework build
209
+ npm exec -- bcp-framework package
210
+ ```