create-bcp-app 0.2.14 → 0.2.16

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 CHANGED
@@ -69,17 +69,17 @@ Select storage provider:
69
69
 
70
70
  New projects include `bcp.project.json`.
71
71
 
72
- Example for the `0.2.14` target:
72
+ Example for the `0.2.16` target:
73
73
 
74
74
  ```json
75
75
  {
76
76
  "schemaVersion": 1,
77
77
  "framework": "bcp",
78
78
  "projectName": "my-app",
79
- "frameworkPackage": "npm:@chidchanun/bcp@0.2.14",
79
+ "frameworkPackage": "npm:@chidchanun/bcp@0.2.16",
80
80
  "createdWith": {
81
81
  "package": "create-bcp-app",
82
- "version": "0.2.14"
82
+ "version": "0.2.16"
83
83
  },
84
84
  "packageManager": "npm",
85
85
  "presets": {
@@ -314,6 +314,116 @@ runTestMiddleware()
314
314
 
315
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.
316
316
 
317
+ ## Plugin & Module Platform — 0.2.15+
318
+
319
+ Use `bcp/plugins` to compose reusable server-side application modules with explicit lifecycle and dependencies.
320
+
321
+ ```ts
322
+ 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
+ });
338
+
339
+ const jobsPlugin =
340
+ definePlugin({
341
+ name: "jobs",
342
+ requires: [
343
+ "database",
344
+ ],
345
+ });
346
+
347
+ const backendModule =
348
+ defineModule({
349
+ name: "backend",
350
+ plugins: [
351
+ databasePlugin,
352
+ jobsPlugin,
353
+ ],
354
+ });
355
+
356
+ const host =
357
+ createPluginHost({
358
+ modules: [
359
+ backendModule,
360
+ ],
361
+ });
362
+
363
+ await host.start();
364
+ ```
365
+
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
+ ## Cache Platform v2 — 0.2.16+
371
+
372
+ Use the existing `bcp/cache` entrypoint for provider-neutral shared caching while keeping the original `cache()` and `dedupe()` APIs available.
373
+
374
+ ```ts
375
+ import {
376
+ createCacheStore,
377
+ } from "bcp/cache";
378
+
379
+ export const cache =
380
+ createCacheStore();
381
+ ```
382
+
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
+ ```
397
+
398
+ For multi-instance deployments, applications can supply Redis-compatible cache and lock adapters:
399
+
400
+ ```ts
401
+ import {
402
+ createRedisCacheAdapter,
403
+ createRedisCacheLockAdapter,
404
+ } from "bcp/cache";
405
+
406
+ const redisCache =
407
+ createRedisCacheAdapter({
408
+ client: redisClient,
409
+ });
410
+
411
+ const redisLock =
412
+ createRedisCacheLockAdapter({
413
+ client: redisClient,
414
+ });
415
+
416
+ export const cache =
417
+ createCacheStore({
418
+ adapter: redisCache,
419
+ lock: redisLock,
420
+ });
421
+ ```
422
+
423
+ BCP does not install or own the Redis client. Applications remain responsible for credentials, TLS, Cluster/Sentinel configuration, reconnect behavior and connection shutdown.
424
+
425
+ `getOrSet()` provides local singleflight and can use distributed lock leases with heartbeat renewal to reduce cache stampedes across instances.
426
+
317
427
  ## Storage providers
318
428
 
319
429
  Supported presets are Local Server, Amazon S3 and Cloudflare R2. Storage credentials are server-only and must not use `BCP_PUBLIC_*` variables.
@@ -352,5 +462,5 @@ npm run generate -- migration create_users
352
462
  For prerelease/local package verification:
353
463
 
354
464
  ```bash
355
- npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.14.tgz
465
+ npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.16.tgz
356
466
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bcp-app",
3
- "version": "0.2.14",
3
+ "version": "0.2.16",
4
4
  "description": "Create a new BCP Framework application.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -240,10 +240,107 @@ await withTestTransaction(
240
240
  );
241
241
  ```
242
242
 
243
- Additional helpers include job/workflow/outbox harnesses, `runTestMiddleware()`, fake clocks and IDs, a fake `RealtimeSocket`, realtime event assertions and `readSseEvents()`.
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
244
 
245
245
  BCP does not require Jest or Vitest; these helpers work with Node `node:test` or another runner.
246
246
 
247
+ ## Plugin & Module Platform — BCP 0.2.15+
248
+
249
+ Use `bcp/plugins` to compose reusable server-only application services with explicit dependencies.
250
+
251
+ ```ts
252
+ 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
+ });
275
+
276
+ export const plugins =
277
+ createPluginHost({
278
+ plugins: [
279
+ jobsPlugin,
280
+ databasePlugin,
281
+ ],
282
+ });
283
+ ```
284
+
285
+ Plugin startup follows dependency order and shutdown reverses it. Plugins can use `setup/start/stop/dispose`, config parsers, shared services and async hooks.
286
+
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
+ ## Cache Platform v2 — BCP 0.2.16+
292
+
293
+ Use `createCacheStore()` for async cache-aside loading, shared adapters and distributed cache-fill coordination.
294
+
295
+ ```ts
296
+ import {
297
+ createCacheStore,
298
+ } from "bcp/cache";
299
+
300
+ export const cache =
301
+ createCacheStore();
302
+ ```
303
+
304
+ ```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
+ );
315
+ ```
316
+
317
+ For multiple instances, connect a shared cache and lock provider:
318
+
319
+ ```ts
320
+ import {
321
+ createRedisCacheAdapter,
322
+ createRedisCacheLockAdapter,
323
+ } from "bcp/cache";
324
+
325
+ const redisCache =
326
+ createRedisCacheAdapter({
327
+ client: redisClient,
328
+ });
329
+
330
+ const redisLock =
331
+ createRedisCacheLockAdapter({
332
+ client: redisClient,
333
+ });
334
+
335
+ export const cache =
336
+ createCacheStore({
337
+ adapter: redisCache,
338
+ lock: redisLock,
339
+ });
340
+ ```
341
+
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
+
247
344
  ## Generate framework files
248
345
 
249
346
  ```bash