@chidchanun/bcp 0.2.13 → 0.2.15
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 +224 -99
- package/docs/README.md +40 -35
- package/docs/api-manifest.json +26 -10
- package/docs/api-reference.md +173 -29
- package/docs/docs-web-manifest.json +8 -4
- package/docs/platform-manifest.json +33 -4
- package/docs/plugin-module-platform.md +391 -0
- package/docs/releases/0.2.14.md +241 -0
- package/docs/releases/0.2.15.md +118 -0
- package/docs/testing-platform.md +602 -0
- package/package.json +11 -1
- package/packages/bundler/src/client-boundary.ts +2 -0
- package/packages/client/src/plugins.mjs +811 -0
- package/packages/client/src/plugins.ts +26 -0
- package/packages/client/src/realtime.mjs +67 -30
- package/packages/client/src/testing.mjs +2357 -0
- package/packages/client/src/testing.ts +52 -0
- package/packages/server/src/plugins.ts +1225 -0
- package/packages/server/src/realtime.ts +95 -41
- package/packages/server/src/testing-page.ts +274 -0
- package/packages/server/src/testing.ts +1884 -0
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# BCP Framework
|
|
2
2
|
|
|
3
|
-
BCP Framework is a React full-stack framework for file-based routing, SSR, SPA navigation, server data loading, API routes, authentication, authorization, SQL databases, background jobs, scheduling, workflow orchestration, transactional events, realtime delivery, observability, uploads, storage and standalone Node.js deployment.
|
|
3
|
+
BCP Framework is a React full-stack framework for file-based routing, SSR, SPA navigation, server data loading, API routes, authentication, authorization, SQL databases, background jobs, scheduling, workflow orchestration, transactional events, realtime delivery, framework-native testing, plugin/module composition, observability, uploads, storage and standalone Node.js deployment.
|
|
4
4
|
|
|
5
|
-
> **Development target:** `0.2.
|
|
5
|
+
> **Development target:** `0.2.15 — Plugin & Module Platform`
|
|
6
6
|
>
|
|
7
|
-
> `0.2.
|
|
7
|
+
> `0.2.15` remains unreleased until local validation, RC checks, tagging and npm publication complete.
|
|
8
8
|
|
|
9
9
|
## Current platform
|
|
10
10
|
|
|
@@ -25,6 +25,8 @@ BCP Framework is a React full-stack framework for file-based routing, SSR, SPA n
|
|
|
25
25
|
| Workflows | Sequential/parallel steps, retries, persisted delays, compensation and run leases |
|
|
26
26
|
| Events | Transactional outbox, SQL persistence, dispatcher leases, retries, event bus and durable queue handoff |
|
|
27
27
|
| Realtime | Channels/rooms, presence, broker delivery, WebSocket adapter contract, SSE and heartbeat |
|
|
28
|
+
| Testing | Request/route/page/auth/database/middleware/jobs/workflow/outbox/realtime/SSE test harnesses |
|
|
29
|
+
| Plugins & modules | Dependency ordering, lifecycle hooks, config parsing, service registry and async extension hooks |
|
|
28
30
|
| Observability | Structured logs, metrics, Prometheus output and health/readiness checks |
|
|
29
31
|
| Uploads & storage | Multipart streaming, Local/S3-compatible storage and signed URLs |
|
|
30
32
|
| Caching | Response cache and revalidation primitives |
|
|
@@ -73,6 +75,8 @@ import { createJobQueue } from "bcp/jobs";
|
|
|
73
75
|
import { createWorkflow } from "bcp/workflow";
|
|
74
76
|
import { createTransactionalOutbox } from "bcp/events";
|
|
75
77
|
import { createRealtime } from "bcp/realtime";
|
|
78
|
+
import { createTestApp } from "bcp/testing";
|
|
79
|
+
import { createPluginHost } from "bcp/plugins";
|
|
76
80
|
import { createMetricsRegistry } from "bcp/observability";
|
|
77
81
|
```
|
|
78
82
|
|
|
@@ -165,10 +169,6 @@ Read more: [Transactional Outbox & Events](docs/transactional-outbox-events.md)
|
|
|
165
169
|
|
|
166
170
|
## Realtime Platform — 0.2.13
|
|
167
171
|
|
|
168
|
-
`0.2.13` adds the server-only `bcp/realtime` public entrypoint.
|
|
169
|
-
|
|
170
|
-
Create a hub:
|
|
171
|
-
|
|
172
172
|
```ts
|
|
173
173
|
import {
|
|
174
174
|
createRealtime,
|
|
@@ -178,7 +178,7 @@ export const realtime =
|
|
|
178
178
|
createRealtime();
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
Join a channel and broadcast:
|
|
182
182
|
|
|
183
183
|
```ts
|
|
184
184
|
const connection =
|
|
@@ -197,135 +197,254 @@ await realtime.broadcast(
|
|
|
197
197
|
);
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
|
|
200
|
+
BCP intentionally does not install a WebSocket server library. Applications adapt `ws`, uWebSockets.js or another transport to `RealtimeSocket`. SSE is built in through Web `Response`.
|
|
201
|
+
|
|
202
|
+
Read more: [Realtime Platform](docs/realtime-platform.md)
|
|
203
|
+
|
|
204
|
+
## Testing Platform — 0.2.14
|
|
205
|
+
|
|
206
|
+
`0.2.14` adds the server-only `bcp/testing` entrypoint. It is test-runner neutral and does not add Jest or Vitest as framework dependencies.
|
|
201
207
|
|
|
202
|
-
###
|
|
208
|
+
### Request and route tests
|
|
203
209
|
|
|
204
210
|
```ts
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
211
|
+
import {
|
|
212
|
+
createRouteTestHandler,
|
|
213
|
+
createTestApp,
|
|
214
|
+
expectResponse,
|
|
215
|
+
} from "bcp/testing";
|
|
216
|
+
|
|
217
|
+
const handler =
|
|
218
|
+
createRouteTestHandler({
|
|
219
|
+
GET() {
|
|
220
|
+
return {
|
|
221
|
+
ok: true,
|
|
222
|
+
};
|
|
210
223
|
},
|
|
211
|
-
}
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
const members =
|
|
215
|
-
await realtime.members(
|
|
216
|
-
"project:7"
|
|
217
|
-
);
|
|
218
|
-
```
|
|
224
|
+
});
|
|
219
225
|
|
|
220
|
-
|
|
226
|
+
const app =
|
|
227
|
+
createTestApp({
|
|
228
|
+
handler,
|
|
229
|
+
});
|
|
221
230
|
|
|
222
|
-
|
|
231
|
+
const response =
|
|
232
|
+
await app.get(
|
|
233
|
+
"/api/health"
|
|
234
|
+
);
|
|
223
235
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
async ({ request }) =>
|
|
229
|
-
request
|
|
230
|
-
? loadRealtimeUser(
|
|
231
|
-
request
|
|
232
|
-
)
|
|
233
|
-
: null,
|
|
234
|
-
|
|
235
|
-
getUserId:
|
|
236
|
-
user => user.id,
|
|
237
|
-
|
|
238
|
-
authorizeChannel:
|
|
239
|
-
({ connection, channel }) =>
|
|
240
|
-
!channel.startsWith(
|
|
241
|
-
"private:"
|
|
242
|
-
) ||
|
|
243
|
-
Boolean(
|
|
244
|
-
connection.user
|
|
245
|
-
),
|
|
236
|
+
await expectResponse(response)
|
|
237
|
+
.status(200)
|
|
238
|
+
.json({
|
|
239
|
+
ok: true,
|
|
246
240
|
});
|
|
247
241
|
```
|
|
248
242
|
|
|
249
|
-
|
|
243
|
+
`createTestApp()` keeps an in-memory cookie jar, supports default headers and can send JSON bodies directly.
|
|
250
244
|
|
|
251
|
-
|
|
245
|
+
### Authentication tests
|
|
252
246
|
|
|
253
|
-
|
|
247
|
+
Create a real signed BCP session token instead of a fake test-only user header:
|
|
254
248
|
|
|
255
249
|
```ts
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
250
|
+
import {
|
|
251
|
+
createTestAuthSession,
|
|
252
|
+
} from "bcp/testing";
|
|
253
|
+
|
|
254
|
+
const session =
|
|
255
|
+
await createTestAuthSession(
|
|
259
256
|
{
|
|
260
|
-
|
|
257
|
+
id: 42,
|
|
258
|
+
role: "admin",
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
secret:
|
|
262
|
+
process.env.BCP_SESSION_SECRET,
|
|
263
|
+
store:
|
|
264
|
+
authSessionStore,
|
|
261
265
|
}
|
|
262
266
|
);
|
|
263
|
-
```
|
|
264
267
|
|
|
265
|
-
|
|
268
|
+
app.setCookie(
|
|
269
|
+
session.cookieName,
|
|
270
|
+
session.token
|
|
271
|
+
);
|
|
272
|
+
```
|
|
266
273
|
|
|
267
|
-
|
|
274
|
+
When `store` is provided, the matching server-side auth session record is inserted as well.
|
|
268
275
|
|
|
269
|
-
|
|
276
|
+
### Rollback database tests
|
|
270
277
|
|
|
271
278
|
```ts
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
279
|
+
import {
|
|
280
|
+
withTestTransaction,
|
|
281
|
+
} from "bcp/testing";
|
|
282
|
+
|
|
283
|
+
await withTestTransaction(
|
|
284
|
+
db,
|
|
285
|
+
async tx => {
|
|
286
|
+
await tx.execute(
|
|
287
|
+
"INSERT INTO users ..."
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
// assertions run here
|
|
291
|
+
}
|
|
292
|
+
);
|
|
283
293
|
```
|
|
284
294
|
|
|
285
|
-
|
|
295
|
+
The callback uses the real BCP transaction and is deliberately rolled back after the test callback succeeds.
|
|
286
296
|
|
|
287
|
-
|
|
297
|
+
### Infrastructure harnesses
|
|
288
298
|
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
299
|
+
```ts
|
|
300
|
+
import {
|
|
301
|
+
createJobTestHarness,
|
|
302
|
+
createOutboxTestHarness,
|
|
303
|
+
createRealtimeTestHarness,
|
|
304
|
+
createWorkflowTestHarness,
|
|
305
|
+
} from "bcp/testing";
|
|
295
306
|
```
|
|
296
307
|
|
|
297
|
-
|
|
308
|
+
These harnesses use the real platform contracts rather than separate mock implementations.
|
|
309
|
+
|
|
310
|
+
Background jobs:
|
|
298
311
|
|
|
299
312
|
```ts
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
313
|
+
const jobTest =
|
|
314
|
+
createJobTestHarness(
|
|
315
|
+
jobs
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
await jobTest.drain();
|
|
304
319
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
320
|
+
await jobTest.expectCount(
|
|
321
|
+
1,
|
|
322
|
+
{
|
|
323
|
+
name: "email.welcome",
|
|
324
|
+
state: "succeeded",
|
|
325
|
+
}
|
|
326
|
+
);
|
|
308
327
|
```
|
|
309
328
|
|
|
310
|
-
|
|
329
|
+
Realtime:
|
|
311
330
|
|
|
312
|
-
|
|
331
|
+
```ts
|
|
332
|
+
const realtimeTest =
|
|
333
|
+
createRealtimeTestHarness(
|
|
334
|
+
realtime
|
|
335
|
+
);
|
|
313
336
|
|
|
314
|
-
|
|
337
|
+
const {
|
|
338
|
+
socket,
|
|
339
|
+
connection,
|
|
340
|
+
} =
|
|
341
|
+
await realtimeTest.connect();
|
|
342
|
+
|
|
343
|
+
await connection.join(
|
|
344
|
+
"orders:42"
|
|
345
|
+
);
|
|
315
346
|
|
|
316
|
-
```ts
|
|
317
347
|
await realtime.broadcast(
|
|
318
|
-
|
|
319
|
-
"
|
|
348
|
+
"orders:42",
|
|
349
|
+
"order.updated",
|
|
320
350
|
{
|
|
321
|
-
|
|
351
|
+
status: "paid",
|
|
322
352
|
}
|
|
323
353
|
);
|
|
354
|
+
|
|
355
|
+
realtimeTest.expectEvent(
|
|
356
|
+
socket,
|
|
357
|
+
"order.updated",
|
|
358
|
+
"orders:42"
|
|
359
|
+
);
|
|
324
360
|
```
|
|
325
361
|
|
|
326
|
-
|
|
362
|
+
Other testing primitives include:
|
|
327
363
|
|
|
328
|
-
|
|
364
|
+
```text
|
|
365
|
+
createFakeClock()
|
|
366
|
+
createSequenceIdFactory()
|
|
367
|
+
runTestMiddleware()
|
|
368
|
+
createRealtimeTestSocket()
|
|
369
|
+
readSseEvents()
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Read more: [Testing Platform](docs/testing-platform.md)
|
|
373
|
+
|
|
374
|
+
## Plugin & Module Platform — 0.2.15
|
|
375
|
+
|
|
376
|
+
`0.2.15` adds the server-only `bcp/plugins` entrypoint for reusable application/framework extensions.
|
|
377
|
+
|
|
378
|
+
Define plugins with explicit dependencies:
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
import {
|
|
382
|
+
createPluginHost,
|
|
383
|
+
definePlugin,
|
|
384
|
+
} from "bcp/plugins";
|
|
385
|
+
|
|
386
|
+
const databasePlugin =
|
|
387
|
+
definePlugin({
|
|
388
|
+
name: "database",
|
|
389
|
+
setup(context) {
|
|
390
|
+
context.services.provide(
|
|
391
|
+
"database",
|
|
392
|
+
db
|
|
393
|
+
);
|
|
394
|
+
},
|
|
395
|
+
start() {
|
|
396
|
+
return db.connect();
|
|
397
|
+
},
|
|
398
|
+
stop() {
|
|
399
|
+
return db.disconnect();
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const jobsPlugin =
|
|
404
|
+
definePlugin({
|
|
405
|
+
name: "jobs",
|
|
406
|
+
requires: [
|
|
407
|
+
"database",
|
|
408
|
+
],
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const host =
|
|
412
|
+
createPluginHost({
|
|
413
|
+
plugins: [
|
|
414
|
+
jobsPlugin,
|
|
415
|
+
databasePlugin,
|
|
416
|
+
],
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
await host.start();
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Dependency order is resolved automatically. Startup follows dependency order while stop/dispose runs in reverse order.
|
|
423
|
+
|
|
424
|
+
Modules group reusable plugin sets:
|
|
425
|
+
|
|
426
|
+
```ts
|
|
427
|
+
import {
|
|
428
|
+
defineModule,
|
|
429
|
+
} from "bcp/plugins";
|
|
430
|
+
|
|
431
|
+
const backendModule =
|
|
432
|
+
defineModule({
|
|
433
|
+
name: "backend",
|
|
434
|
+
plugins: [
|
|
435
|
+
databasePlugin,
|
|
436
|
+
jobsPlugin,
|
|
437
|
+
],
|
|
438
|
+
});
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Plugin configuration can be parsed at setup time and overridden through `createPluginHost({ configs })`.
|
|
442
|
+
|
|
443
|
+
Plugins share a service registry and awaited in-process hook bus through `context.services` and `context.hooks`.
|
|
444
|
+
|
|
445
|
+
If startup fails, already-started plugins are stopped in reverse order before the lifecycle error is propagated.
|
|
446
|
+
|
|
447
|
+
Read more: [Plugin & Module Platform](docs/plugin-module-platform.md)
|
|
329
448
|
|
|
330
449
|
## Public entrypoints
|
|
331
450
|
|
|
@@ -342,6 +461,8 @@ bcp/jobs
|
|
|
342
461
|
bcp/workflow
|
|
343
462
|
bcp/events
|
|
344
463
|
bcp/realtime
|
|
464
|
+
bcp/testing
|
|
465
|
+
bcp/plugins
|
|
345
466
|
bcp/observability
|
|
346
467
|
bcp/server
|
|
347
468
|
bcp/server-only
|
|
@@ -390,13 +511,15 @@ Browser / API / Realtime clients
|
|
|
390
511
|
|
|
|
391
512
|
security + auth
|
|
392
513
|
|
|
|
393
|
-
|
|
514
|
+
Plugin Host
|
|
394
515
|
/ | \
|
|
395
516
|
database workflows realtime
|
|
396
517
|
| | ^
|
|
397
518
|
outbox jobs |
|
|
398
519
|
\__________|_________/
|
|
399
520
|
durable state
|
|
521
|
+
|
|
522
|
+
Testing Platform exercises these server contracts without becoming part of browser runtime.
|
|
400
523
|
```
|
|
401
524
|
|
|
402
525
|
## Packaging
|
|
@@ -424,7 +547,7 @@ docs/api-manifest.json
|
|
|
424
547
|
|
|
425
548
|
## Release validation
|
|
426
549
|
|
|
427
|
-
Before publishing `0.2.
|
|
550
|
+
Before publishing `0.2.15`:
|
|
428
551
|
|
|
429
552
|
```bash
|
|
430
553
|
npm run typecheck
|
|
@@ -435,7 +558,7 @@ npm run test:package
|
|
|
435
558
|
npm run rc:check
|
|
436
559
|
```
|
|
437
560
|
|
|
438
|
-
`0.2.
|
|
561
|
+
`0.2.15` adds unit and prepared-package smoke coverage for plugin dependency ordering, missing/cyclic dependencies, modules, config parsing, shared services, async hooks, lifecycle rollback, compiled `plugins.mjs` execution and browser boundary enforcement.
|
|
439
562
|
|
|
440
563
|
Do not tag or publish until the exact final release commit passes the full RC sequence.
|
|
441
564
|
|
|
@@ -463,12 +586,14 @@ Do not tag or publish until the exact final release commit passes the full RC se
|
|
|
463
586
|
| `0.2.11` | Workflow Orchestration |
|
|
464
587
|
| `0.2.12` | Transactional Outbox & Events |
|
|
465
588
|
| `0.2.13` | Realtime Platform |
|
|
589
|
+
| `0.2.14` | Testing Platform |
|
|
590
|
+
| `0.2.15` | Plugin & Module Platform |
|
|
466
591
|
|
|
467
592
|
## Roadmap
|
|
468
593
|
|
|
469
|
-
`0.2.
|
|
594
|
+
`0.2.15` establishes reusable server-side extension composition while keeping BCP subsystem contracts provider-neutral and independently testable.
|
|
470
595
|
|
|
471
|
-
The next logical milestone is **`0.2.
|
|
596
|
+
The next logical milestone is **`0.2.16 — Cache Platform v2`**, focused on distributed cache adapters, Redis-compatible caching, locking, stampede protection and production cache observability.
|
|
472
597
|
|
|
473
598
|
Native desktop/mobile compilation remains later roadmap work.
|
|
474
599
|
|
package/docs/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The `docs/` directory is the documentation source of truth for BCP Framework and is organized for **`bcp-docs-web`**.
|
|
4
4
|
|
|
5
|
-
> **Documentation target:** BCP Framework `0.2.
|
|
5
|
+
> **Documentation target:** BCP Framework `0.2.15 — Plugin & Module Platform`
|
|
6
6
|
>
|
|
7
7
|
> **Release state:** unreleased development target until RC validation, tagging and npm publication complete.
|
|
8
8
|
|
|
@@ -39,56 +39,57 @@ Framework source and tests remain authoritative for runtime behavior.
|
|
|
39
39
|
| `0.2.11` | Workflow Orchestration |
|
|
40
40
|
| `0.2.12` | Transactional Outbox & Events |
|
|
41
41
|
| `0.2.13` | Realtime Platform |
|
|
42
|
+
| `0.2.14` | Testing Platform |
|
|
43
|
+
| `0.2.15` | Plugin & Module Platform |
|
|
42
44
|
|
|
43
|
-
## 0.2.
|
|
45
|
+
## 0.2.15 — Plugin & Module Platform
|
|
44
46
|
|
|
45
|
-
`0.2.
|
|
47
|
+
`0.2.15` adds the server-only `bcp/plugins` public entrypoint.
|
|
46
48
|
|
|
47
49
|
Primary APIs:
|
|
48
50
|
|
|
49
51
|
```ts
|
|
50
52
|
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
createPluginHookBus,
|
|
54
|
+
createPluginHost,
|
|
55
|
+
createPluginServiceRegistry,
|
|
56
|
+
defineModule,
|
|
57
|
+
definePlugin,
|
|
58
|
+
} from "bcp/plugins";
|
|
56
59
|
```
|
|
57
60
|
|
|
58
61
|
Runtime model:
|
|
59
62
|
|
|
60
63
|
```text
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
+-- RealtimeSocket
|
|
75
|
-
| -> WebSocket provider adapter
|
|
76
|
-
|
|
|
77
|
-
+-- SSE Response
|
|
64
|
+
Plugin Host
|
|
65
|
+
|
|
|
66
|
+
+-- dependency graph
|
|
67
|
+
| -> required / optional dependencies
|
|
68
|
+
|
|
|
69
|
+
+-- lifecycle
|
|
70
|
+
| -> setup -> start -> stop -> dispose
|
|
71
|
+
|
|
|
72
|
+
+-- service registry
|
|
73
|
+
| -> typed shared application services
|
|
74
|
+
|
|
|
75
|
+
+-- async hook bus
|
|
76
|
+
-> in-process extension points
|
|
78
77
|
```
|
|
79
78
|
|
|
80
|
-
|
|
79
|
+
Startup follows topological dependency order. Stop/dispose runs in reverse order. A failed startup rolls back plugins that already started.
|
|
80
|
+
|
|
81
|
+
Modules are named bundles of plugins; they do not create a separate lifecycle graph.
|
|
81
82
|
|
|
82
83
|
New/updated sources:
|
|
83
84
|
|
|
84
85
|
| Source | Purpose |
|
|
85
86
|
| --- | --- |
|
|
86
|
-
| `
|
|
87
|
-
| `api-reference.md` | `bcp/
|
|
88
|
-
| `platform-manifest.json` |
|
|
89
|
-
| `api-manifest.json` | `bcp/
|
|
90
|
-
| `docs-web-manifest.json` |
|
|
91
|
-
| `releases/0.2.
|
|
87
|
+
| `plugin-module-platform.md` | Plugin definitions, modules, dependency order, lifecycle, config, services and hooks |
|
|
88
|
+
| `api-reference.md` | `bcp/plugins` public APIs |
|
|
89
|
+
| `platform-manifest.json` | Plugin capability flags and public entrypoint |
|
|
90
|
+
| `api-manifest.json` | `bcp/plugins` source/guide ownership |
|
|
91
|
+
| `docs-web-manifest.json` | Plugin docs navigation and `0.2.15` release route |
|
|
92
|
+
| `releases/0.2.15.md` | Plugin & Module Platform release notes |
|
|
92
93
|
|
|
93
94
|
## Update rule
|
|
94
95
|
|
|
@@ -114,8 +115,10 @@ When framework behavior or public surface changes:
|
|
|
114
115
|
| `/docs/workflow-orchestration` | `workflow-orchestration.md` |
|
|
115
116
|
| `/docs/transactional-outbox-events` | `transactional-outbox-events.md` |
|
|
116
117
|
| `/docs/realtime-platform` | `realtime-platform.md` |
|
|
118
|
+
| `/docs/testing-platform` | `testing-platform.md` |
|
|
119
|
+
| `/docs/plugin-module-platform` | `plugin-module-platform.md` |
|
|
117
120
|
| `/docs/api-reference` | `api-reference.md` |
|
|
118
|
-
| `/releases/0.2.
|
|
121
|
+
| `/releases/0.2.15` | `releases/0.2.15.md` |
|
|
119
122
|
|
|
120
123
|
Every route/source pair is validated by unit tests.
|
|
121
124
|
|
|
@@ -134,6 +137,8 @@ bcp/jobs
|
|
|
134
137
|
bcp/workflow
|
|
135
138
|
bcp/events
|
|
136
139
|
bcp/realtime
|
|
140
|
+
bcp/testing
|
|
141
|
+
bcp/plugins
|
|
137
142
|
bcp/observability
|
|
138
143
|
bcp/server
|
|
139
144
|
bcp/server-only
|
|
@@ -144,7 +149,7 @@ The API-manifest entrypoint set must match the platform public-entrypoint set ex
|
|
|
144
149
|
|
|
145
150
|
## Release validation
|
|
146
151
|
|
|
147
|
-
Before publishing `0.2.
|
|
152
|
+
Before publishing `0.2.15`:
|
|
148
153
|
|
|
149
154
|
```bash
|
|
150
155
|
npm run typecheck
|
|
@@ -155,6 +160,6 @@ npm run test:package
|
|
|
155
160
|
npm run rc:check
|
|
156
161
|
```
|
|
157
162
|
|
|
158
|
-
|
|
163
|
+
Plugin Platform validation covers dependency ordering, missing/cyclic dependencies, module composition, typed config parsing, service sharing, async hooks, reverse shutdown, startup rollback, server-only boundaries, compiled `plugins.mjs` package execution and docs/platform/API parity.
|
|
159
164
|
|
|
160
165
|
The final release tag must point to the exact commit that passed the complete RC sequence.
|