create-bcp-app 0.2.11 → 0.2.13

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 +100 -195
  2. package/package.json +1 -1
  3. package/template/README.md +74 -198
package/README.md CHANGED
@@ -28,16 +28,6 @@ Generated npm scripts use `bcp` because npm places `node_modules/.bin` on the sc
28
28
  }
29
29
  ```
30
30
 
31
- When Tailwind CSS is selected, the generated packaging script preserves the production CSS step:
32
-
33
- ```json
34
- {
35
- "scripts": {
36
- "package": "npm run css:build:prod && bcp package"
37
- }
38
- }
39
- ```
40
-
41
31
  For direct PowerShell usage, prefer the collision-free local alias:
42
32
 
43
33
  ```powershell
@@ -75,27 +65,21 @@ Select storage provider:
75
65
  Cloudflare R2
76
66
  ```
77
67
 
78
- Equivalent non-interactive flags are available for CI/scaffolding automation.
79
-
80
68
  ## Generated project metadata
81
69
 
82
- New projects include:
83
-
84
- ```text
85
- bcp.project.json
86
- ```
70
+ New projects include `bcp.project.json`.
87
71
 
88
- Example:
72
+ Example for the `0.2.13` target:
89
73
 
90
74
  ```json
91
75
  {
92
76
  "schemaVersion": 1,
93
77
  "framework": "bcp",
94
78
  "projectName": "my-app",
95
- "frameworkPackage": "npm:@chidchanun/bcp@0.2.11",
79
+ "frameworkPackage": "npm:@chidchanun/bcp@0.2.13",
96
80
  "createdWith": {
97
81
  "package": "create-bcp-app",
98
- "version": "0.2.11"
82
+ "version": "0.2.13"
99
83
  },
100
84
  "packageManager": "npm",
101
85
  "presets": {
@@ -109,43 +93,9 @@ Example:
109
93
 
110
94
  This manifest records scaffold identity only. It must not contain secrets and should normally be committed to source control.
111
95
 
112
- ## Generated application defaults
113
-
114
- Generated applications include the project-root `@/` alias and TypeScript settings compatible with the BCP bundler.
115
-
116
- Modules that use React client hooks such as `useState` or `useEffect` must declare `"use client"` at the top of the module.
117
-
118
- The generated BCP dependency is pinned to the exact framework release selected by the generator.
119
-
120
- Update later with:
121
-
122
- ```bash
123
- npm run update
124
- ```
125
-
126
- Check without modifying files:
127
-
128
- ```powershell
129
- npm exec -- bcp-framework update --check
130
- ```
131
-
132
- ## Tailwind CSS
133
-
134
- When Tailwind is enabled, the project includes `tailwindcss`, `@tailwindcss/cli`, `concurrently`, `app/globals.css`, `/bcp.css` stylesheet setup and starter utility classes.
135
-
136
- Generated commands include:
137
-
138
- ```text
139
- npm run css:build
140
- npm run css:watch
141
- npm run css:build:prod
142
- ```
143
-
144
- `npm run build` and `npm run package` create the production stylesheet before the BCP production build/package flow.
145
-
146
96
  ## Database presets
147
97
 
148
- The database choice adds starter configuration and the matching driver:
98
+ Database choices add starter configuration and the matching driver:
149
99
 
150
100
  - MySQL: `mysql2`
151
101
  - PostgreSQL: `pg`
@@ -153,71 +103,31 @@ The database choice adds starter configuration and the matching driver:
153
103
  - MongoDB: `mongodb`
154
104
  - None: no database dependency
155
105
 
156
- For **MySQL**, **PostgreSQL** and **SQLite**, generated `lib/database.ts` exposes framework database primitives through `bcp/database`.
157
-
158
- The generator intentionally does not force an ORM.
159
-
160
- ## Storage providers
161
-
162
- Selecting a storage provider creates `lib/storage.ts` and provider-specific environment settings. Supported presets are Local Server, Amazon S3 and Cloudflare R2.
163
-
164
- Storage credentials are server-only. Do not expose them through `BCP_PUBLIC_*` variables.
106
+ For MySQL, PostgreSQL and SQLite, generated `lib/database.ts` exposes BCP database primitives through `bcp/database`.
165
107
 
166
- ## JWT Cookie authentication
108
+ ## Authentication and security
167
109
 
168
- Selecting `JWT Cookie` creates `lib/auth.ts` and starter `/api/auth/login`, `/logout` and `/me` routes, and adds:
169
-
170
- ```dotenv
171
- BCP_SESSION_SECRET=
172
- ```
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.
173
111
 
174
- Set this to a cryptographically random secret of at least 32 bytes before real authentication use.
175
-
176
- BCP `0.2.5+` can opt into revocable server-side auth state through `AuthSessionStore`.
177
-
178
- ## Authorization & request security — 0.2.6+
179
-
180
- Generated applications can use permission guards and resource policies from `bcp/auth`, plus same-origin and CSRF protection from `bcp/server`.
181
-
182
- Authorization and CSRF checks must remain on the server; hiding UI controls in client code is not an authorization boundary.
183
-
184
- ## Observability — 0.2.7+
185
-
186
- Generated projects can opt into process-local metrics and health/readiness without adding another dependency:
112
+ ## Observability
187
113
 
188
114
  ```ts
189
115
  import {
190
116
  createHealthRegistry,
191
117
  createMetricsRegistry,
192
- createRequestMetricsMiddleware,
193
118
  } from "bcp/observability";
194
119
  ```
195
120
 
196
- `bcp/observability` is server-only. Protect metrics and operational health detail with an appropriate network or authorization boundary when needed.
197
-
198
- ## Background jobs — 0.2.8+
199
-
200
- Generated projects can create a server-only background job queue:
121
+ ## Background jobs and scheduling
201
122
 
202
123
  ```ts
203
124
  import {
204
125
  createJobQueue,
126
+ createJobScheduler,
205
127
  } from "bcp/jobs";
206
128
 
207
129
  export const jobs =
208
130
  createJobQueue();
209
- ```
210
-
211
- Workers support concurrency, delayed jobs, retry/backoff and cancellation.
212
-
213
- ## Job scheduling — 0.2.9+
214
-
215
- Recurring schedules use the same `bcp/jobs` entrypoint:
216
-
217
- ```ts
218
- import {
219
- createJobScheduler,
220
- } from "bcp/jobs";
221
131
 
222
132
  export const scheduler =
223
133
  createJobScheduler({
@@ -225,82 +135,23 @@ export const scheduler =
225
135
  });
226
136
  ```
227
137
 
228
- Interval schedule:
229
-
230
- ```ts
231
- await scheduler.schedule(
232
- "cache.cleanup",
233
- {},
234
- {
235
- everyMs: 300_000,
236
- }
237
- );
238
- ```
239
-
240
- UTC cron schedule:
241
-
242
- ```ts
243
- await scheduler.schedule(
244
- "report.weekday",
245
- {},
246
- {
247
- cron: "30 9 * * 1-5",
248
- }
249
- );
250
- ```
251
-
252
- ## Durable jobs — 0.2.10+
253
-
254
- BCP `0.2.10` adds worker visibility leases, heartbeat renewal, stale-running recovery, DLQ/requeue, retention cleanup and queue statistics.
255
-
256
- ```ts
257
- const worker =
258
- jobs.startWorker({
259
- workerId: "worker-a",
260
- concurrency: 4,
261
- visibilityTimeoutMs: 30_000,
262
- heartbeatIntervalMs: 10_000,
263
- });
264
- ```
265
-
266
- BCP intentionally does not install a Redis client library. Applications own the Redis connection and can pass a minimal `RedisCommandClient` to `createRedisJobQueueAdapter()` and `createRedisJobScheduleStore()`.
267
-
268
- `bcp/jobs` is server-only and must not be imported into page/client bundles.
138
+ `0.2.10+` adds visibility leases, heartbeat renewal, stale-running recovery, DLQ/requeue, retention cleanup and Redis-compatible durable adapters.
269
139
 
270
140
  ## Workflow orchestration — 0.2.11+
271
141
 
272
- Generated applications can define persistent backend workflows with the new server-only `bcp/workflow` entrypoint:
273
-
274
142
  ```ts
275
143
  import {
276
144
  createWorkflow,
277
145
  } from "bcp/workflow";
278
146
 
279
147
  export const onboarding =
280
- createWorkflow<{
281
- userId: number;
282
- }>(
148
+ createWorkflow(
283
149
  "user.onboarding",
284
150
  workflow => {
285
151
  workflow.step(
286
152
  "profile",
287
153
  createProfile
288
154
  );
289
-
290
- workflow.parallel(
291
- "initialize",
292
- parallel => {
293
- parallel.step(
294
- "preferences",
295
- createPreferences
296
- );
297
- parallel.step(
298
- "workspace",
299
- createWorkspace
300
- );
301
- }
302
- );
303
-
304
155
  workflow.delay(
305
156
  "cooldown",
306
157
  1_000
@@ -309,45 +160,108 @@ export const onboarding =
309
160
  );
310
161
  ```
311
162
 
312
- Step-level retry and compensation are supported:
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+
166
+
167
+ Applications using the SQL Database Platform can persist integration events in the same transaction as business data:
313
168
 
314
169
  ```ts
315
- workflow.step(
316
- "reserve-stock",
317
- reserveStock,
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:
192
+
193
+ ```ts
194
+ import {
195
+ createRealtime,
196
+ } from "bcp/realtime";
197
+
198
+ export const realtime =
199
+ createRealtime();
200
+ ```
201
+
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",
318
215
  {
319
- maxAttempts: 3,
320
- retryDelayMs: 1_000,
321
- compensate:
322
- releaseStock,
216
+ status: "paid",
323
217
  }
324
218
  );
325
219
  ```
326
220
 
327
- For durable queue-backed execution, pass an existing `BackgroundJobQueue` and a durable shared `WorkflowStore`:
221
+ Presence metadata can be attached during `join()` and read with `realtime.members(channel)`.
222
+
223
+ For private channels, configure `authenticate`, `getUserId` and `authorizeChannel` on `createRealtime()`.
224
+
225
+ ### WebSocket integration
226
+
227
+ BCP does not install a WebSocket library. Adapt your selected provider to `RealtimeSocket` and pass it to:
328
228
 
329
229
  ```ts
330
- const fulfillment =
331
- createWorkflow(
332
- "order.fulfillment",
333
- defineWorkflow,
230
+ await realtime.attachSocket(
231
+ socketAdapter,
232
+ {
233
+ request,
234
+ }
235
+ );
236
+ ```
237
+
238
+ ### Server-Sent Events
239
+
240
+ SSE is available without another dependency:
241
+
242
+ ```ts
243
+ export function GET(
244
+ request: Request
245
+ ) {
246
+ return realtime.sse(
247
+ "jobs:42",
334
248
  {
335
- queue: jobs,
336
- store:
337
- workflowStore,
249
+ signal:
250
+ request.signal,
338
251
  }
339
252
  );
253
+ }
340
254
  ```
341
255
 
342
- The built-in `createMemoryWorkflowStore()` is intended for development/tests. Multi-instance production stores should make `claim()` atomic so only one executor owns a workflow run lease at a time.
256
+ The memory broker/presence store are local-only. Multi-instance production deployments should provide shared `RealtimeBroker` and `RealtimePresenceStore` implementations.
343
257
 
344
- External side effects should remain idempotent because durable queue execution is at-least-once.
258
+ `bcp/realtime` is server-only and cannot be imported into page/client bundles.
345
259
 
346
- `bcp/workflow` is server-only and cannot be imported into page/client bundles.
260
+ ## Storage providers
347
261
 
348
- ## Application Packaging 0.2.4+
262
+ Supported presets are Local Server, Amazon S3 and Cloudflare R2. Storage credentials are server-only and must not use `BCP_PUBLIC_*` variables.
349
263
 
350
- Generated projects include:
264
+ ## Application packaging
351
265
 
352
266
  ```bash
353
267
  npm run package
@@ -355,7 +269,7 @@ npm run package
355
269
 
356
270
  The deployment package excludes application `devDependencies` and project `.env` values. Supply real secrets through the deployment environment.
357
271
 
358
- ## Project generators after creation
272
+ ## Project generators
359
273
 
360
274
  ```bash
361
275
  npm run generate -- page dashboard/users
@@ -364,15 +278,6 @@ npm run generate -- middleware
364
278
  npm run generate -- migration create_users
365
279
  ```
366
280
 
367
- Equivalent direct CLI:
368
-
369
- ```bash
370
- bcp generate page dashboard/users
371
- bcp generate api users
372
- bcp generate middleware
373
- bcp generate migration create_users
374
- ```
375
-
376
281
  ## Options
377
282
 
378
283
  ```text
@@ -387,8 +292,8 @@ bcp generate migration create_users
387
292
  -h, --help Show help
388
293
  ```
389
294
 
390
- The `--bcp` option is mainly for prerelease/local package verification:
295
+ For prerelease/local package verification:
391
296
 
392
297
  ```bash
393
- npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.11.tgz
298
+ npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.13.tgz
394
299
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bcp-app",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "description": "Create a new BCP Framework application.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -12,8 +12,6 @@ Open `http://localhost:3000`.
12
12
 
13
13
  ## Project commands
14
14
 
15
- Generated projects use the project-local BCP Framework CLI through npm scripts:
16
-
17
15
  ```bash
18
16
  npm run dev
19
17
  npm run routes
@@ -25,25 +23,17 @@ npm start
25
23
  npm run update
26
24
  ```
27
25
 
28
- The generated scripts call commands such as `bcp dev`, `bcp generate`, `bcp build`, `bcp package` and `bcp start`.
29
-
30
26
  ## Project metadata
31
27
 
32
- Projects created with BCP `0.1.29+` include `bcp.project.json` with non-secret scaffold metadata.
33
-
34
- Commit this file with the project. Do not put passwords, access keys, session secrets or tokens in it.
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.
35
29
 
36
30
  ## Authentication — BCP 0.2.5+
37
31
 
38
- Projects created with the `JWT Cookie` preset remain stateless by default and use the generated `lib/auth.ts` helpers.
39
-
40
- BCP Authentication Platform v2 can opt into revocable server-side session state with `createAuth()` and `AuthSessionStore`.
32
+ JWT Cookie projects can opt into revocable server-side session state with `createAuth()` and `AuthSessionStore`.
41
33
 
42
34
  ## Authorization & request security — BCP 0.2.6+
43
35
 
44
- Use permission guards and resource policies from `bcp/auth`, and same-origin/CSRF protection from `bcp/server`.
45
-
46
- Authorization must always be enforced server-side. Client UI visibility is not a security boundary.
36
+ Use permission guards/resource policies from `bcp/auth`, and same-origin/CSRF protection from `bcp/server`. Authorization must remain server-side.
47
37
 
48
38
  ## Observability — BCP 0.2.7+
49
39
 
@@ -51,16 +41,11 @@ Authorization must always be enforced server-side. Client UI visibility is not a
51
41
  import {
52
42
  createHealthRegistry,
53
43
  createMetricsRegistry,
54
- createRequestMetricsMiddleware,
55
44
  } from "bcp/observability";
56
45
  ```
57
46
 
58
- Protect operational endpoints when their contents should not be public.
59
-
60
47
  ## Background jobs — BCP 0.2.8+
61
48
 
62
- Create a server-only background queue:
63
-
64
49
  ```ts
65
50
  import {
66
51
  createJobQueue,
@@ -70,21 +55,6 @@ export const jobs =
70
55
  createJobQueue();
71
56
  ```
72
57
 
73
- Register typed work:
74
-
75
- ```ts
76
- jobs.register<{
77
- userId: number;
78
- }>(
79
- "email.welcome",
80
- async ({ payload }) => {
81
- await sendWelcomeEmail(
82
- payload.userId
83
- );
84
- }
85
- );
86
- ```
87
-
88
58
  ## Job scheduling — BCP 0.2.9+
89
59
 
90
60
  ```ts
@@ -98,21 +68,9 @@ export const scheduler =
98
68
  });
99
69
  ```
100
70
 
101
- Example UTC cron schedule:
102
-
103
- ```ts
104
- await scheduler.schedule(
105
- "report.weekday",
106
- {},
107
- {
108
- cron: "30 9 * * 1-5",
109
- }
110
- );
111
- ```
112
-
113
71
  ## Durable jobs — BCP 0.2.10+
114
72
 
115
- Workers can use visibility leases, heartbeat renewal and stale-running recovery:
73
+ Workers can use visibility leases, heartbeat renewal, stale recovery and DLQ/requeue. Redis-compatible adapters are available without forcing a Redis client dependency.
116
74
 
117
75
  ```ts
118
76
  const worker =
@@ -124,132 +82,21 @@ const worker =
124
82
  });
125
83
  ```
126
84
 
127
- Retry-exhausted jobs are available through the adapter DLQ contract:
128
-
129
- ```ts
130
- const deadLetters =
131
- await jobs.deadLetters();
132
-
133
- await jobs.requeueDeadLetter(
134
- deadLetters[0].id,
135
- {
136
- resetAttempts: true,
137
- }
138
- );
139
- ```
140
-
141
- Operational helpers:
142
-
143
- ```ts
144
- await jobs.recoverStale();
145
- const stats = await jobs.stats();
146
- await jobs.cleanup({
147
- before:
148
- Date.now() -
149
- 7 * 24 * 60 * 60 * 1000,
150
- });
151
- ```
152
-
153
- ### Redis-compatible adapters
154
-
155
- BCP does not install a Redis library. Supply an application-owned command client:
156
-
157
- ```ts
158
- interface RedisCommandClient {
159
- sendCommand(
160
- command: string[]
161
- ): Promise<unknown>;
162
- }
163
- ```
164
-
165
- Create a durable queue:
166
-
167
- ```ts
168
- import {
169
- createJobQueue,
170
- createRedisJobQueueAdapter,
171
- } from "bcp/jobs";
172
-
173
- const adapter =
174
- createRedisJobQueueAdapter({
175
- client: redisCommandClient,
176
- namespace: "my-app:{jobs}",
177
- });
178
-
179
- export const jobs =
180
- createJobQueue({
181
- adapter,
182
- });
183
- ```
184
-
185
- Create a shared schedule store:
186
-
187
- ```ts
188
- import {
189
- createJobScheduler,
190
- createRedisJobScheduleStore,
191
- } from "bcp/jobs";
192
-
193
- const store =
194
- createRedisJobScheduleStore({
195
- client: redisCommandClient,
196
- namespace: "my-app:{jobs}",
197
- });
198
-
199
- export const scheduler =
200
- createJobScheduler({
201
- queue: jobs,
202
- store,
203
- ownerId: "scheduler-a",
204
- });
205
- ```
206
-
207
- A typical deployment may use:
208
-
209
- ```dotenv
210
- REDIS_URL=redis://localhost:6379
211
- ```
212
-
213
- BCP does not read this variable automatically. The application owns Redis connection creation, credentials, TLS/Cluster configuration and shutdown.
214
-
215
- The processing model is at-least-once, so side-effecting job handlers should be idempotent when duplicate execution is unsafe.
216
-
217
- `bcp/jobs` is server-only and cannot be imported into page/client bundles.
218
-
219
85
  ## Workflow orchestration — BCP 0.2.11+
220
86
 
221
- Define persistent server-side workflows through `bcp/workflow`:
222
-
223
87
  ```ts
224
88
  import {
225
89
  createWorkflow,
226
90
  } from "bcp/workflow";
227
91
 
228
92
  export const onboarding =
229
- createWorkflow<{
230
- userId: number;
231
- }>(
93
+ createWorkflow(
232
94
  "user.onboarding",
233
95
  workflow => {
234
96
  workflow.step(
235
97
  "profile",
236
98
  createProfile
237
99
  );
238
-
239
- workflow.parallel(
240
- "initialize",
241
- parallel => {
242
- parallel.step(
243
- "preferences",
244
- createPreferences
245
- );
246
- parallel.step(
247
- "workspace",
248
- createWorkspace
249
- );
250
- }
251
- );
252
-
253
100
  workflow.delay(
254
101
  "cooldown",
255
102
  1_000
@@ -258,41 +105,87 @@ export const onboarding =
258
105
  );
259
106
  ```
260
107
 
261
- Step retry and compensation:
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.
262
113
 
263
114
  ```ts
264
- workflow.step(
265
- "reserve-stock",
266
- reserveStock,
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:
137
+
138
+ ```ts
139
+ import {
140
+ createRealtime,
141
+ } from "bcp/realtime";
142
+
143
+ export const realtime =
144
+ createRealtime();
145
+ ```
146
+
147
+ Channels/rooms:
148
+
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",
267
160
  {
268
- maxAttempts: 3,
269
- retryDelayMs: 1_000,
270
- compensate:
271
- releaseStock,
161
+ status: "paid",
272
162
  }
273
163
  );
274
164
  ```
275
165
 
276
- For queue-backed execution:
166
+ Presence metadata can be supplied during `join()` and queried with `realtime.members(channel)`.
167
+
168
+ BCP does not install a WebSocket server dependency. Adapt the selected provider to `RealtimeSocket` and call `realtime.attachSocket(socketAdapter, { request })`.
169
+
170
+ SSE is built in:
277
171
 
278
172
  ```ts
279
- const fulfillment =
280
- createWorkflow(
281
- "order.fulfillment",
282
- defineWorkflow,
173
+ export function GET(
174
+ request: Request
175
+ ) {
176
+ return realtime.sse(
177
+ "jobs:42",
283
178
  {
284
- queue: jobs,
285
- store:
286
- workflowStore,
179
+ signal:
180
+ request.signal,
287
181
  }
288
182
  );
183
+ }
289
184
  ```
290
185
 
291
- The default `createMemoryWorkflowStore()` is for local development/tests. Multi-instance production deployments should implement a shared durable `WorkflowStore` with atomic `claim()` behavior.
186
+ For multi-instance deployment, replace the memory broker/presence store with shared `RealtimeBroker` and `RealtimePresenceStore` implementations.
292
187
 
293
- Workflow handlers that perform external side effects should be idempotent because durable job execution is at-least-once.
294
-
295
- `bcp/workflow` is server-only and cannot be imported into page/client bundles.
188
+ `bcp/realtime` is server-only and cannot be imported into page/client bundles.
296
189
 
297
190
  ## Generate framework files
298
191
 
@@ -303,22 +196,9 @@ npm run generate -- middleware
303
196
  npm run generate -- migration create_users
304
197
  ```
305
198
 
306
- Equivalent direct commands:
307
-
308
- ```bash
309
- bcp generate page dashboard/users
310
- bcp generate api users
311
- bcp generate middleware
312
- bcp generate migration create_users
313
- ```
314
-
315
- Existing page/API/middleware targets are not replaced unless `--force` is supplied explicitly.
316
-
317
199
  ## Direct CLI usage
318
200
 
319
- BCP Framework is installed as a project-local dependency.
320
-
321
- For PowerShell direct usage:
201
+ For PowerShell:
322
202
 
323
203
  ```powershell
324
204
  npm exec -- bcp-framework --version
@@ -330,8 +210,6 @@ npm exec -- bcp-framework build
330
210
  npm exec -- bcp-framework package
331
211
  ```
332
212
 
333
- Microsoft SQL Server can install another Windows executable named `bcp.exe`, so the `bcp-framework` alias avoids that command-name collision.
334
-
335
213
  ## Production build
336
214
 
337
215
  ```bash
@@ -339,12 +217,10 @@ npm run build
339
217
  npm start
340
218
  ```
341
219
 
342
- ## Deployment package — BCP 0.2.4+
220
+ ## Deployment package
343
221
 
344
222
  ```bash
345
223
  npm run package
346
224
  ```
347
225
 
348
- The output is written to `.bcp-framework/package/` and contains standalone output, production dependency metadata, deployment/environment manifests, integrity hashes and a starter Dockerfile.
349
-
350
- BCP intentionally excludes project `.env` files and application `devDependencies` from the deployment package. Provide secrets through your deployment environment.
226
+ BCP excludes project `.env` files and application `devDependencies` from the deployment package. Supply secrets through the deployment environment.