create-bcp-app 0.2.16 → 0.2.17
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 +83 -158
- package/package.json +1 -1
- package/template/README.md +87 -47
package/README.md
CHANGED
|
@@ -34,7 +34,6 @@ For direct PowerShell usage, prefer the collision-free local alias:
|
|
|
34
34
|
npm exec -- bcp-framework --version
|
|
35
35
|
npm exec -- bcp-framework doctor
|
|
36
36
|
npm exec -- bcp-framework inspect
|
|
37
|
-
npm exec -- bcp-framework generate page dashboard/users
|
|
38
37
|
npm exec -- bcp-framework routes
|
|
39
38
|
npm exec -- bcp-framework dev
|
|
40
39
|
npm exec -- bcp-framework build
|
|
@@ -45,8 +44,6 @@ Microsoft SQL Server can install another Windows executable named `bcp.exe`, so
|
|
|
45
44
|
|
|
46
45
|
## Interactive choices
|
|
47
46
|
|
|
48
|
-
The generator asks for optional application presets:
|
|
49
|
-
|
|
50
47
|
```text
|
|
51
48
|
Use Tailwind CSS?
|
|
52
49
|
Select a database:
|
|
@@ -69,17 +66,17 @@ Select storage provider:
|
|
|
69
66
|
|
|
70
67
|
New projects include `bcp.project.json`.
|
|
71
68
|
|
|
72
|
-
Example for the `0.2.
|
|
69
|
+
Example for the `0.2.17` target:
|
|
73
70
|
|
|
74
71
|
```json
|
|
75
72
|
{
|
|
76
73
|
"schemaVersion": 1,
|
|
77
74
|
"framework": "bcp",
|
|
78
75
|
"projectName": "my-app",
|
|
79
|
-
"frameworkPackage": "npm:@chidchanun/bcp@0.2.
|
|
76
|
+
"frameworkPackage": "npm:@chidchanun/bcp@0.2.17",
|
|
80
77
|
"createdWith": {
|
|
81
78
|
"package": "create-bcp-app",
|
|
82
|
-
"version": "0.2.
|
|
79
|
+
"version": "0.2.17"
|
|
83
80
|
},
|
|
84
81
|
"packageManager": "npm",
|
|
85
82
|
"presets": {
|
|
@@ -109,15 +106,6 @@ For MySQL, PostgreSQL and SQLite, generated `lib/database.ts` exposes BCP databa
|
|
|
109
106
|
|
|
110
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.
|
|
111
108
|
|
|
112
|
-
## Observability
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
import {
|
|
116
|
-
createHealthRegistry,
|
|
117
|
-
createMetricsRegistry,
|
|
118
|
-
} from "bcp/observability";
|
|
119
|
-
```
|
|
120
|
-
|
|
121
109
|
## Background jobs and scheduling
|
|
122
110
|
|
|
123
111
|
```ts
|
|
@@ -160,12 +148,8 @@ export const onboarding =
|
|
|
160
148
|
);
|
|
161
149
|
```
|
|
162
150
|
|
|
163
|
-
`bcp/workflow` supports sequential/parallel steps, retry, persisted delays, compensation and optional execution through `bcp/jobs`.
|
|
164
|
-
|
|
165
151
|
## Transactional Outbox & Events — 0.2.12+
|
|
166
152
|
|
|
167
|
-
Applications using the SQL Database Platform can persist integration events in the same transaction as business data:
|
|
168
|
-
|
|
169
153
|
```ts
|
|
170
154
|
await db.transaction(
|
|
171
155
|
async tx => {
|
|
@@ -184,12 +168,8 @@ await db.transaction(
|
|
|
184
168
|
);
|
|
185
169
|
```
|
|
186
170
|
|
|
187
|
-
After commit, `createOutboxDispatcher()` can hand off events to durable jobs/custom publishers.
|
|
188
|
-
|
|
189
171
|
## Realtime Platform — 0.2.13+
|
|
190
172
|
|
|
191
|
-
Generated applications can add server-side realtime channels without changing the scaffold preset model:
|
|
192
|
-
|
|
193
173
|
```ts
|
|
194
174
|
import {
|
|
195
175
|
createRealtime,
|
|
@@ -199,35 +179,10 @@ export const realtime =
|
|
|
199
179
|
createRealtime();
|
|
200
180
|
```
|
|
201
181
|
|
|
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
|
-
```
|
|
220
|
-
|
|
221
182
|
BCP does not install a WebSocket library. Adapt your selected provider to `RealtimeSocket`. SSE is available directly through `realtime.sse()`.
|
|
222
183
|
|
|
223
|
-
The memory broker/presence store are local-only. Multi-instance production deployments should provide shared `RealtimeBroker` and `RealtimePresenceStore` implementations.
|
|
224
|
-
|
|
225
184
|
## Testing Platform — 0.2.14+
|
|
226
185
|
|
|
227
|
-
`bcp/testing` adds framework-native test helpers without requiring a specific test runner.
|
|
228
|
-
|
|
229
|
-
Request/route example:
|
|
230
|
-
|
|
231
186
|
```ts
|
|
232
187
|
import {
|
|
233
188
|
createRouteTestHandler,
|
|
@@ -256,72 +211,13 @@ await expectResponse(
|
|
|
256
211
|
});
|
|
257
212
|
```
|
|
258
213
|
|
|
259
|
-
|
|
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
|
-
```
|
|
283
|
-
|
|
284
|
-
Rollback database tests:
|
|
285
|
-
|
|
286
|
-
```ts
|
|
287
|
-
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:
|
|
302
|
-
|
|
303
|
-
```text
|
|
304
|
-
createJobTestHarness()
|
|
305
|
-
createWorkflowTestHarness()
|
|
306
|
-
createOutboxTestHarness()
|
|
307
|
-
createRealtimeTestSocket()
|
|
308
|
-
createRealtimeTestHarness()
|
|
309
|
-
readSseEvents()
|
|
310
|
-
createFakeClock()
|
|
311
|
-
createSequenceIdFactory()
|
|
312
|
-
runTestMiddleware()
|
|
313
|
-
```
|
|
314
|
-
|
|
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.
|
|
214
|
+
BCP testing helpers are runner-neutral and can be used with Node `node:test`, Vitest, Jest or another runner.
|
|
316
215
|
|
|
317
216
|
## Plugin & Module Platform — 0.2.15+
|
|
318
217
|
|
|
319
|
-
Use `bcp/plugins` to compose reusable server-side application modules with explicit lifecycle and dependencies.
|
|
320
|
-
|
|
321
218
|
```ts
|
|
322
219
|
import {
|
|
323
220
|
createPluginHost,
|
|
324
|
-
defineModule,
|
|
325
221
|
definePlugin,
|
|
326
222
|
} from "bcp/plugins";
|
|
327
223
|
|
|
@@ -344,85 +240,114 @@ const jobsPlugin =
|
|
|
344
240
|
],
|
|
345
241
|
});
|
|
346
242
|
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
name: "backend",
|
|
243
|
+
export const plugins =
|
|
244
|
+
createPluginHost({
|
|
350
245
|
plugins: [
|
|
351
|
-
databasePlugin,
|
|
352
246
|
jobsPlugin,
|
|
247
|
+
databasePlugin,
|
|
353
248
|
],
|
|
354
249
|
});
|
|
355
|
-
|
|
356
|
-
const host =
|
|
357
|
-
createPluginHost({
|
|
358
|
-
modules: [
|
|
359
|
-
backendModule,
|
|
360
|
-
],
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
await host.start();
|
|
364
250
|
```
|
|
365
251
|
|
|
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.
|
|
367
|
-
|
|
368
|
-
`bcp/plugins` is server-only and cannot be imported into page/client bundles.
|
|
369
|
-
|
|
370
252
|
## Cache Platform v2 — 0.2.16+
|
|
371
253
|
|
|
372
|
-
Use the existing `bcp/cache` entrypoint for provider-neutral shared caching while keeping the original `cache()` and `dedupe()` APIs available.
|
|
373
|
-
|
|
374
254
|
```ts
|
|
375
255
|
import {
|
|
376
256
|
createCacheStore,
|
|
257
|
+
createRedisCacheAdapter,
|
|
258
|
+
createRedisCacheLockAdapter,
|
|
377
259
|
} from "bcp/cache";
|
|
378
260
|
|
|
379
261
|
export const cache =
|
|
380
|
-
createCacheStore(
|
|
262
|
+
createCacheStore({
|
|
263
|
+
adapter:
|
|
264
|
+
createRedisCacheAdapter({
|
|
265
|
+
client: redisClient,
|
|
266
|
+
}),
|
|
267
|
+
lock:
|
|
268
|
+
createRedisCacheLockAdapter({
|
|
269
|
+
client: redisClient,
|
|
270
|
+
}),
|
|
271
|
+
});
|
|
381
272
|
```
|
|
382
273
|
|
|
383
|
-
|
|
274
|
+
BCP does not install or own the Redis client. Applications remain responsible for credentials, TLS, Cluster/Sentinel configuration, reconnect behavior and connection shutdown.
|
|
275
|
+
|
|
276
|
+
## Observability Platform v3 — 0.2.17+
|
|
277
|
+
|
|
278
|
+
Metrics and health remain available through the same entrypoint:
|
|
384
279
|
|
|
385
280
|
```ts
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
281
|
+
import {
|
|
282
|
+
createHealthRegistry,
|
|
283
|
+
createMetricsRegistry,
|
|
284
|
+
createTracer,
|
|
285
|
+
} from "bcp/observability";
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Create a tracer:
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
export const tracer =
|
|
292
|
+
createTracer({
|
|
293
|
+
serviceName: "my-app",
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Trace incoming HTTP requests with Middleware System v2:
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import {
|
|
301
|
+
createRequestTracingMiddleware,
|
|
302
|
+
} from "bcp/observability";
|
|
303
|
+
|
|
304
|
+
export const middleware =
|
|
305
|
+
createRequestTracingMiddleware(
|
|
306
|
+
tracer
|
|
395
307
|
);
|
|
396
308
|
```
|
|
397
309
|
|
|
398
|
-
|
|
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:
|
|
399
313
|
|
|
400
314
|
```ts
|
|
401
315
|
import {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
} from "bcp/
|
|
316
|
+
createTraceCarrier,
|
|
317
|
+
runWithTraceCarrier,
|
|
318
|
+
} from "bcp/observability";
|
|
405
319
|
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
client: redisClient,
|
|
409
|
-
});
|
|
320
|
+
const trace =
|
|
321
|
+
createTraceCarrier();
|
|
410
322
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
323
|
+
await jobs.enqueue(
|
|
324
|
+
"order.process",
|
|
325
|
+
{
|
|
326
|
+
orderId,
|
|
327
|
+
trace,
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
```
|
|
415
331
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
332
|
+
Consumer:
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
await runWithTraceCarrier(
|
|
336
|
+
payload.trace,
|
|
337
|
+
() =>
|
|
338
|
+
tracer.withSpan(
|
|
339
|
+
"job order.process",
|
|
340
|
+
handler,
|
|
341
|
+
{
|
|
342
|
+
kind: "consumer",
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
);
|
|
421
346
|
```
|
|
422
347
|
|
|
423
|
-
|
|
348
|
+
Use `getTraceLogFields()` to add `traceId`, `spanId` and `correlationId` to structured logs.
|
|
424
349
|
|
|
425
|
-
|
|
350
|
+
BCP does not install OpenTelemetry or a vendor APM package. Implement `TraceSpanExporter` when production spans need to be sent to an external collector.
|
|
426
351
|
|
|
427
352
|
## Storage providers
|
|
428
353
|
|
|
@@ -462,5 +387,5 @@ npm run generate -- migration create_users
|
|
|
462
387
|
For prerelease/local package verification:
|
|
463
388
|
|
|
464
389
|
```bash
|
|
465
|
-
npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.
|
|
390
|
+
npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.17.tgz
|
|
466
391
|
```
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -199,49 +199,6 @@ await expectResponse(
|
|
|
199
199
|
});
|
|
200
200
|
```
|
|
201
201
|
|
|
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
|
-
```
|
|
225
|
-
|
|
226
|
-
Database tests can force rollback after assertions:
|
|
227
|
-
|
|
228
|
-
```ts
|
|
229
|
-
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
|
-
```
|
|
242
|
-
|
|
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()`.
|
|
244
|
-
|
|
245
202
|
BCP does not require Jest or Vitest; these helpers work with Node `node:test` or another runner.
|
|
246
203
|
|
|
247
204
|
## Plugin & Module Platform — BCP 0.2.15+
|
|
@@ -284,10 +241,6 @@ export const plugins =
|
|
|
284
241
|
|
|
285
242
|
Plugin startup follows dependency order and shutdown reverses it. Plugins can use `setup/start/stop/dispose`, config parsers, shared services and async hooks.
|
|
286
243
|
|
|
287
|
-
Use `defineModule()` when a reusable package needs to bundle multiple plugin definitions into one named module.
|
|
288
|
-
|
|
289
|
-
`bcp/plugins` is server-only and cannot be imported from page/client bundles.
|
|
290
|
-
|
|
291
244
|
## Cache Platform v2 — BCP 0.2.16+
|
|
292
245
|
|
|
293
246
|
Use `createCacheStore()` for async cache-aside loading, shared adapters and distributed cache-fill coordination.
|
|
@@ -341,6 +294,93 @@ export const cache =
|
|
|
341
294
|
|
|
342
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.
|
|
343
296
|
|
|
297
|
+
## Observability Platform v3 — BCP 0.2.17+
|
|
298
|
+
|
|
299
|
+
Use the existing `bcp/observability` entrypoint for tracing as well as metrics and health.
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
import {
|
|
303
|
+
createTracer,
|
|
304
|
+
} from "bcp/observability";
|
|
305
|
+
|
|
306
|
+
export const tracer =
|
|
307
|
+
createTracer({
|
|
308
|
+
serviceName: "my-app",
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Trace incoming Middleware System v2 requests:
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
import {
|
|
316
|
+
createRequestTracingMiddleware,
|
|
317
|
+
} from "bcp/observability";
|
|
318
|
+
|
|
319
|
+
export const middleware =
|
|
320
|
+
createRequestTracingMiddleware(
|
|
321
|
+
tracer
|
|
322
|
+
);
|
|
323
|
+
```
|
|
324
|
+
|
|
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:
|
|
328
|
+
|
|
329
|
+
```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
|
+
);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
For jobs, workflows, events and realtime payloads, propagate context explicitly:
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
import {
|
|
348
|
+
createTraceCarrier,
|
|
349
|
+
runWithTraceCarrier,
|
|
350
|
+
} from "bcp/observability";
|
|
351
|
+
|
|
352
|
+
const trace =
|
|
353
|
+
createTraceCarrier();
|
|
354
|
+
|
|
355
|
+
await jobs.enqueue(
|
|
356
|
+
"order.process",
|
|
357
|
+
{
|
|
358
|
+
orderId,
|
|
359
|
+
trace,
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Consumer:
|
|
365
|
+
|
|
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
|
+
);
|
|
378
|
+
```
|
|
379
|
+
|
|
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
|
+
|
|
344
384
|
## Generate framework files
|
|
345
385
|
|
|
346
386
|
```bash
|