@chidchanun/bcp 0.2.11 → 0.2.12
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 +199 -327
- package/docs/README.md +53 -56
- package/docs/api-manifest.json +17 -2
- package/docs/api-reference.md +94 -118
- package/docs/docs-web-manifest.json +7 -5
- package/docs/platform-manifest.json +16 -4
- package/docs/releases/0.2.12.md +147 -0
- package/docs/transactional-outbox-events.md +465 -0
- package/package.json +6 -1
- package/packages/bundler/src/client-boundary.ts +1 -0
- package/packages/client/src/events.mjs +889 -0
- package/packages/client/src/events.ts +31 -0
- package/packages/server/src/events.ts +1416 -0
package/README.md
CHANGED
|
@@ -1,55 +1,37 @@
|
|
|
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,
|
|
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, observability, uploads, storage and standalone Node.js deployment.
|
|
4
4
|
|
|
5
|
-
> **Development target:** `0.2.
|
|
5
|
+
> **Development target:** `0.2.12 — Transactional Outbox & Events`
|
|
6
6
|
>
|
|
7
|
-
> `0.2.
|
|
7
|
+
> `0.2.12` remains unreleased until local validation, RC checks, tagging and npm publication complete.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Current platform
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Machine-readable platform contracts:
|
|
14
|
-
|
|
15
|
-
```text
|
|
16
|
-
docs/platform-manifest.json
|
|
17
|
-
-> runtime target, capabilities and compatibility
|
|
18
|
-
|
|
19
|
-
docs/docs-web-manifest.json
|
|
20
|
-
-> documentation navigation, routes and releases
|
|
21
|
-
|
|
22
|
-
docs/api-manifest.json
|
|
23
|
-
-> public package entrypoints and guide ownership
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Current capabilities
|
|
11
|
+
BCP `0.2.x` currently includes:
|
|
27
12
|
|
|
28
13
|
| Area | Capability |
|
|
29
14
|
| --- | --- |
|
|
30
15
|
| Application | React SSR, hydration, layouts, metadata and SPA navigation |
|
|
31
16
|
| Routing | Static, dynamic, catch-all, optional catch-all and route groups |
|
|
32
|
-
| Server data | Route
|
|
33
|
-
| Mutations | Route-owned
|
|
34
|
-
| Authentication | JWT cookie sessions, optional server-side
|
|
35
|
-
| Authorization | Auth/guest/role/permission
|
|
36
|
-
|
|
|
17
|
+
| Server data | Route loaders and request-scoped server APIs |
|
|
18
|
+
| Mutations | Route-owned actions and `<Form>` |
|
|
19
|
+
| Authentication | JWT cookie sessions, optional server-side stores, revocation, logout-all and idle timeout |
|
|
20
|
+
| Authorization | Auth/guest/role/permission guards and resource-aware policies |
|
|
21
|
+
| Security | Same-origin validation and signed CSRF tokens |
|
|
37
22
|
| Middleware | Middleware System v2 with onion execution |
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
| Uploads | Buffered multipart helpers and production multipart streaming |
|
|
47
|
-
| Storage | Local + S3-compatible storage, streaming, list/copy/move, metadata, bulk delete and signed URLs |
|
|
23
|
+
| Database | MySQL, PostgreSQL and SQLite adapters, transactions, lifecycle and migrations |
|
|
24
|
+
| Background jobs | Delay, retry/backoff, cancellation and concurrent workers |
|
|
25
|
+
| Scheduling | Interval/UTC cron schedules and scheduler leases |
|
|
26
|
+
| Durable jobs | Redis-compatible queue/schedule adapters, visibility timeout, heartbeat, stale recovery and DLQ |
|
|
27
|
+
| Workflows | Sequential/parallel steps, retries, persisted delays, compensation and run leases |
|
|
28
|
+
| Events | Transactional outbox, SQL persistence, dispatcher leases, retries, event bus and durable queue handoff |
|
|
29
|
+
| Observability | Structured logs, metrics, Prometheus output and health/readiness checks |
|
|
30
|
+
| Uploads & storage | Multipart streaming, Local/S3-compatible storage and signed URLs |
|
|
48
31
|
| Caching | Response cache and revalidation primitives |
|
|
49
|
-
| Configuration | Typed
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
| Documentation | Manifest-driven docs navigation, platform metadata and public API reference |
|
|
32
|
+
| Configuration | Typed config/environment validation and diagnostics |
|
|
33
|
+
| Production | Standalone Node.js build, packaging, dependency pruning, Docker starter and graceful shutdown |
|
|
34
|
+
| Documentation | Manifest-driven docs, platform metadata and API reference |
|
|
53
35
|
|
|
54
36
|
## Requirements
|
|
55
37
|
|
|
@@ -57,7 +39,7 @@ docs/api-manifest.json
|
|
|
57
39
|
- React `19`
|
|
58
40
|
- npm
|
|
59
41
|
|
|
60
|
-
|
|
42
|
+
Optional SQL drivers:
|
|
61
43
|
|
|
62
44
|
```text
|
|
63
45
|
MySQL mysql2
|
|
@@ -73,7 +55,7 @@ cd my-app
|
|
|
73
55
|
npm run dev
|
|
74
56
|
```
|
|
75
57
|
|
|
76
|
-
Generated projects normally
|
|
58
|
+
Generated projects normally use one framework dependency:
|
|
77
59
|
|
|
78
60
|
```json
|
|
79
61
|
{
|
|
@@ -83,55 +65,7 @@ Generated projects normally keep one framework dependency key:
|
|
|
83
65
|
}
|
|
84
66
|
```
|
|
85
67
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## Configuration & environment
|
|
89
|
-
|
|
90
|
-
Framework configuration stays in one of:
|
|
91
|
-
|
|
92
|
-
```text
|
|
93
|
-
bcp.config.ts
|
|
94
|
-
bcp.config.mts
|
|
95
|
-
bcp.config.js
|
|
96
|
-
bcp.config.mjs
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Application environment validation can be declared in:
|
|
100
|
-
|
|
101
|
-
```text
|
|
102
|
-
bcp.environment.ts
|
|
103
|
-
bcp.environment.mts
|
|
104
|
-
bcp.environment.js
|
|
105
|
-
bcp.environment.mjs
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Configuration precedence is:
|
|
109
|
-
|
|
110
|
-
```text
|
|
111
|
-
CLI override
|
|
112
|
-
↓
|
|
113
|
-
BCP_* environment
|
|
114
|
-
↓
|
|
115
|
-
bcp.config.*
|
|
116
|
-
↓
|
|
117
|
-
framework defaults
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
Validate configuration and declared environment values with:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
bcp config check
|
|
124
|
-
bcp config check --json
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Variables beginning with `BCP_PUBLIC_` may be embedded in browser output. Never expose application secrets through public-prefixed variables.
|
|
128
|
-
|
|
129
|
-
Read more:
|
|
130
|
-
|
|
131
|
-
- [Configuration](docs/configuration.md)
|
|
132
|
-
- [Environment Validation](docs/environment-validation.md)
|
|
133
|
-
|
|
134
|
-
## Database Platform v2 — 0.2.3
|
|
68
|
+
## Database Platform
|
|
135
69
|
|
|
136
70
|
```ts
|
|
137
71
|
import {
|
|
@@ -140,14 +74,6 @@ import {
|
|
|
140
74
|
} from "bcp/database";
|
|
141
75
|
```
|
|
142
76
|
|
|
143
|
-
Built-in SQL providers:
|
|
144
|
-
|
|
145
|
-
```text
|
|
146
|
-
mysql
|
|
147
|
-
postgresql
|
|
148
|
-
sqlite
|
|
149
|
-
```
|
|
150
|
-
|
|
151
77
|
Migration CLI:
|
|
152
78
|
|
|
153
79
|
```bash
|
|
@@ -157,61 +83,17 @@ bcp db status
|
|
|
157
83
|
bcp db rollback
|
|
158
84
|
```
|
|
159
85
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
- [Database](docs/database.md)
|
|
163
|
-
- [Database Migrations](docs/database-migrations.md)
|
|
164
|
-
|
|
165
|
-
## Application Packaging — 0.2.4
|
|
166
|
-
|
|
167
|
-
Create a fresh production build and deployment package:
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
bcp package
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
Output is written under:
|
|
174
|
-
|
|
175
|
-
```text
|
|
176
|
-
.bcp-framework/package/
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
Read more:
|
|
180
|
-
|
|
181
|
-
- [Application Packaging](docs/application-packaging.md)
|
|
182
|
-
- [Deployment](docs/deployment.md)
|
|
183
|
-
|
|
184
|
-
## Authentication Platform v2 — 0.2.5
|
|
86
|
+
## Authentication & authorization
|
|
185
87
|
|
|
186
88
|
```ts
|
|
187
89
|
import {
|
|
188
|
-
auth,
|
|
189
90
|
createAuth,
|
|
190
91
|
createMemoryAuthSessionStore,
|
|
191
|
-
login,
|
|
192
|
-
logout,
|
|
193
|
-
} from "bcp/auth";
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
Stateless signed JWT-cookie authentication remains supported. Applications that need centralized revocation can configure an `AuthSessionStore`.
|
|
197
|
-
|
|
198
|
-
Read more:
|
|
199
|
-
|
|
200
|
-
- [Authentication](docs/authentication.md)
|
|
201
|
-
- [Auth Session Stores](docs/auth-session-store.md)
|
|
202
|
-
- [Auth Route Guards](docs/auth-route-guards.md)
|
|
203
|
-
|
|
204
|
-
## Authorization & Security v2 — 0.2.6
|
|
205
|
-
|
|
206
|
-
```ts
|
|
207
|
-
import {
|
|
208
|
-
authorize,
|
|
209
|
-
hasPermission,
|
|
210
92
|
requirePermission,
|
|
211
93
|
} from "bcp/auth";
|
|
212
94
|
```
|
|
213
95
|
|
|
214
|
-
Request
|
|
96
|
+
Request security is available from `bcp/server`:
|
|
215
97
|
|
|
216
98
|
```ts
|
|
217
99
|
import {
|
|
@@ -221,9 +103,7 @@ import {
|
|
|
221
103
|
} from "bcp/server";
|
|
222
104
|
```
|
|
223
105
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
## Observability Platform v2 — 0.2.7
|
|
106
|
+
## Observability
|
|
227
107
|
|
|
228
108
|
```ts
|
|
229
109
|
import {
|
|
@@ -233,9 +113,7 @@ import {
|
|
|
233
113
|
} from "bcp/observability";
|
|
234
114
|
```
|
|
235
115
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
## Background Jobs Platform — 0.2.8
|
|
116
|
+
## Background jobs
|
|
239
117
|
|
|
240
118
|
```ts
|
|
241
119
|
import {
|
|
@@ -246,7 +124,7 @@ export const jobs =
|
|
|
246
124
|
createJobQueue();
|
|
247
125
|
```
|
|
248
126
|
|
|
249
|
-
Register work:
|
|
127
|
+
Register typed work:
|
|
250
128
|
|
|
251
129
|
```ts
|
|
252
130
|
jobs.register<{
|
|
@@ -261,24 +139,7 @@ jobs.register<{
|
|
|
261
139
|
);
|
|
262
140
|
```
|
|
263
141
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
```ts
|
|
267
|
-
await jobs.enqueue(
|
|
268
|
-
"email.welcome",
|
|
269
|
-
{
|
|
270
|
-
userId: 42,
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
delayMs: 5_000,
|
|
274
|
-
maxAttempts: 5,
|
|
275
|
-
}
|
|
276
|
-
);
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
Read more: [Background Jobs Platform](docs/background-jobs.md)
|
|
280
|
-
|
|
281
|
-
## Job Scheduling Platform — 0.2.9
|
|
142
|
+
## Job scheduling
|
|
282
143
|
|
|
283
144
|
```ts
|
|
284
145
|
import {
|
|
@@ -291,20 +152,7 @@ export const scheduler =
|
|
|
291
152
|
});
|
|
292
153
|
```
|
|
293
154
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
```ts
|
|
297
|
-
await scheduler.schedule(
|
|
298
|
-
"cache.cleanup",
|
|
299
|
-
{},
|
|
300
|
-
{
|
|
301
|
-
id: "cache-cleanup",
|
|
302
|
-
everyMs: 5 * 60 * 1000,
|
|
303
|
-
}
|
|
304
|
-
);
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
UTC cron schedule:
|
|
155
|
+
UTC cron example:
|
|
308
156
|
|
|
309
157
|
```ts
|
|
310
158
|
await scheduler.schedule(
|
|
@@ -316,11 +164,9 @@ await scheduler.schedule(
|
|
|
316
164
|
);
|
|
317
165
|
```
|
|
318
166
|
|
|
319
|
-
Read more: [Job Scheduling Platform](docs/job-scheduling.md)
|
|
320
|
-
|
|
321
167
|
## Durable Jobs Platform — 0.2.10
|
|
322
168
|
|
|
323
|
-
Workers support visibility leases, heartbeat renewal and stale-running recovery
|
|
169
|
+
Workers support visibility leases, heartbeat renewal and stale-running recovery:
|
|
324
170
|
|
|
325
171
|
```ts
|
|
326
172
|
const worker =
|
|
@@ -329,68 +175,13 @@ const worker =
|
|
|
329
175
|
concurrency: 4,
|
|
330
176
|
visibilityTimeoutMs: 30_000,
|
|
331
177
|
heartbeatIntervalMs: 10_000,
|
|
332
|
-
pollIntervalMs: 250,
|
|
333
|
-
});
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
Retry-exhausted jobs can be inspected and requeued:
|
|
337
|
-
|
|
338
|
-
```ts
|
|
339
|
-
const failed =
|
|
340
|
-
await jobs.deadLetters();
|
|
341
|
-
|
|
342
|
-
await jobs.requeueDeadLetter(
|
|
343
|
-
failed[0].id,
|
|
344
|
-
{
|
|
345
|
-
delayMs: 5_000,
|
|
346
|
-
resetAttempts: true,
|
|
347
|
-
}
|
|
348
|
-
);
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
Redis-compatible durable adapters:
|
|
352
|
-
|
|
353
|
-
```ts
|
|
354
|
-
import {
|
|
355
|
-
createJobQueue,
|
|
356
|
-
createJobScheduler,
|
|
357
|
-
createRedisJobQueueAdapter,
|
|
358
|
-
createRedisJobScheduleStore,
|
|
359
|
-
} from "bcp/jobs";
|
|
360
|
-
|
|
361
|
-
const queueAdapter =
|
|
362
|
-
createRedisJobQueueAdapter({
|
|
363
|
-
client: redisCommandClient,
|
|
364
|
-
namespace: "my-app:{jobs}",
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
export const jobs =
|
|
368
|
-
createJobQueue({
|
|
369
|
-
adapter: queueAdapter,
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
const scheduleStore =
|
|
373
|
-
createRedisJobScheduleStore({
|
|
374
|
-
client: redisCommandClient,
|
|
375
|
-
namespace: "my-app:{jobs}",
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
export const scheduler =
|
|
379
|
-
createJobScheduler({
|
|
380
|
-
queue: jobs,
|
|
381
|
-
store: scheduleStore,
|
|
382
|
-
ownerId: "scheduler-a",
|
|
383
178
|
});
|
|
384
179
|
```
|
|
385
180
|
|
|
386
|
-
BCP does not
|
|
387
|
-
|
|
388
|
-
Read more: [Durable Jobs Platform](docs/durable-jobs.md)
|
|
181
|
+
Redis-compatible adapters are available from `bcp/jobs`. BCP does not install or own the Redis client; applications provide a command client and manage credentials/TLS/Cluster/lifecycle themselves.
|
|
389
182
|
|
|
390
183
|
## Workflow Orchestration — 0.2.11
|
|
391
184
|
|
|
392
|
-
Create a server-only workflow with typed input:
|
|
393
|
-
|
|
394
185
|
```ts
|
|
395
186
|
import {
|
|
396
187
|
createWorkflow,
|
|
@@ -404,11 +195,7 @@ export const onboarding =
|
|
|
404
195
|
workflow => {
|
|
405
196
|
workflow.step(
|
|
406
197
|
"profile",
|
|
407
|
-
|
|
408
|
-
await createProfile(
|
|
409
|
-
input.userId
|
|
410
|
-
);
|
|
411
|
-
}
|
|
198
|
+
createProfile
|
|
412
199
|
);
|
|
413
200
|
|
|
414
201
|
workflow.parallel(
|
|
@@ -433,66 +220,157 @@ export const onboarding =
|
|
|
433
220
|
);
|
|
434
221
|
```
|
|
435
222
|
|
|
436
|
-
|
|
223
|
+
Workflows support retries, compensation and optional execution through the durable job queue.
|
|
224
|
+
|
|
225
|
+
## Transactional Outbox & Events — 0.2.12
|
|
226
|
+
|
|
227
|
+
`0.2.12` adds the server-only `bcp/events` entrypoint.
|
|
228
|
+
|
|
229
|
+
The problem it solves:
|
|
230
|
+
|
|
231
|
+
```text
|
|
232
|
+
DB commit succeeds
|
|
233
|
+
+
|
|
234
|
+
external publish fails
|
|
235
|
+
=
|
|
236
|
+
missing integration event
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The outbox writes the event in the **same SQL transaction** as the business data:
|
|
437
240
|
|
|
438
241
|
```ts
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
242
|
+
import {
|
|
243
|
+
db,
|
|
244
|
+
} from "bcp/database";
|
|
245
|
+
|
|
246
|
+
import {
|
|
247
|
+
createSqlOutboxStore,
|
|
248
|
+
createTransactionalOutbox,
|
|
249
|
+
} from "bcp/events";
|
|
250
|
+
|
|
251
|
+
const outboxStore =
|
|
252
|
+
createSqlOutboxStore({
|
|
253
|
+
database: db,
|
|
254
|
+
driver: "postgresql",
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const outbox =
|
|
258
|
+
createTransactionalOutbox({
|
|
259
|
+
store: outboxStore,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
await db.transaction(
|
|
263
|
+
async tx => {
|
|
264
|
+
await tx.execute(
|
|
265
|
+
"INSERT INTO orders ..."
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
await outbox.publish(
|
|
269
|
+
tx,
|
|
270
|
+
"order.created",
|
|
271
|
+
{
|
|
272
|
+
orderId: 42,
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
aggregateId: "42",
|
|
276
|
+
correlationId: requestId,
|
|
277
|
+
}
|
|
278
|
+
);
|
|
447
279
|
}
|
|
448
280
|
);
|
|
449
281
|
```
|
|
450
282
|
|
|
451
|
-
|
|
283
|
+
Generate the outbox table migration for the configured provider:
|
|
452
284
|
|
|
453
285
|
```ts
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
);
|
|
286
|
+
import {
|
|
287
|
+
createOutboxMigrationSql,
|
|
288
|
+
} from "bcp/events";
|
|
289
|
+
|
|
290
|
+
const sql =
|
|
291
|
+
createOutboxMigrationSql(
|
|
292
|
+
"postgresql"
|
|
293
|
+
);
|
|
462
294
|
```
|
|
463
295
|
|
|
464
|
-
|
|
296
|
+
Supported providers:
|
|
297
|
+
|
|
298
|
+
```text
|
|
299
|
+
mysql
|
|
300
|
+
postgresql
|
|
301
|
+
sqlite
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Dispatcher
|
|
305
|
+
|
|
306
|
+
After the SQL transaction commits, a dispatcher claims due events and delivers them:
|
|
465
307
|
|
|
466
308
|
```ts
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
309
|
+
import {
|
|
310
|
+
createOutboxDispatcher,
|
|
311
|
+
} from "bcp/events";
|
|
312
|
+
|
|
313
|
+
export const dispatcher =
|
|
314
|
+
createOutboxDispatcher({
|
|
315
|
+
store: outboxStore,
|
|
316
|
+
queue: jobs,
|
|
317
|
+
ownerId: "outbox-a",
|
|
318
|
+
leaseMs: 30_000,
|
|
319
|
+
batchSize: 100,
|
|
320
|
+
pollIntervalMs: 1_000,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
const runner =
|
|
324
|
+
dispatcher.start();
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
With `queue: jobs`, event type:
|
|
328
|
+
|
|
329
|
+
```text
|
|
330
|
+
order.created
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
is handed off as:
|
|
334
|
+
|
|
335
|
+
```text
|
|
336
|
+
event.order.created
|
|
470
337
|
```
|
|
471
338
|
|
|
472
|
-
|
|
339
|
+
Register its durable consumer:
|
|
473
340
|
|
|
474
341
|
```ts
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
}
|
|
484
|
-
);
|
|
342
|
+
jobs.register(
|
|
343
|
+
"event.order.created",
|
|
344
|
+
async ({ payload }) => {
|
|
345
|
+
await handleOrderCreated(
|
|
346
|
+
payload
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
);
|
|
485
350
|
```
|
|
486
351
|
|
|
487
|
-
|
|
352
|
+
Dispatcher features include:
|
|
488
353
|
|
|
489
|
-
|
|
354
|
+
- batched claims,
|
|
355
|
+
- lease ownership,
|
|
356
|
+
- stale lease recovery,
|
|
357
|
+
- retry/backoff,
|
|
358
|
+
- terminal failed state,
|
|
359
|
+
- queue delivery,
|
|
360
|
+
- custom publisher callbacks,
|
|
361
|
+
- local `EventBus`,
|
|
362
|
+
- retention cleanup,
|
|
363
|
+
- outbox statistics.
|
|
490
364
|
|
|
491
|
-
|
|
365
|
+
`published` means the configured destination accepted the event. For queue delivery, it means enqueue succeeded; it does not mean the downstream job handler has completed.
|
|
366
|
+
|
|
367
|
+
Delivery remains **at-least-once**, so consumers that perform non-idempotent side effects should use stable event IDs/idempotency controls.
|
|
368
|
+
|
|
369
|
+
Read more: [Transactional Outbox & Events](docs/transactional-outbox-events.md)
|
|
492
370
|
|
|
493
371
|
## Public entrypoints
|
|
494
372
|
|
|
495
|
-
The current
|
|
373
|
+
The current documented platform surface is:
|
|
496
374
|
|
|
497
375
|
```text
|
|
498
376
|
bcp
|
|
@@ -505,24 +383,17 @@ bcp/database
|
|
|
505
383
|
bcp/auth
|
|
506
384
|
bcp/jobs
|
|
507
385
|
bcp/workflow
|
|
386
|
+
bcp/events
|
|
508
387
|
bcp/observability
|
|
509
388
|
bcp/server
|
|
510
389
|
bcp/server-only
|
|
511
390
|
bcp/middleware
|
|
512
391
|
```
|
|
513
392
|
|
|
514
|
-
Application code should use public entrypoints instead of importing
|
|
515
|
-
|
|
516
|
-
See:
|
|
517
|
-
|
|
518
|
-
- [API Reference](docs/api-reference.md)
|
|
519
|
-
- [Platform Manifest](docs/platform-manifest.json)
|
|
520
|
-
- [API Manifest](docs/api-manifest.json)
|
|
393
|
+
Application code should use public entrypoints instead of importing private `packages/*` implementation files.
|
|
521
394
|
|
|
522
395
|
## CLI
|
|
523
396
|
|
|
524
|
-
Core commands:
|
|
525
|
-
|
|
526
397
|
```bash
|
|
527
398
|
bcp dev
|
|
528
399
|
bcp build
|
|
@@ -536,16 +407,7 @@ bcp inspect
|
|
|
536
407
|
bcp version
|
|
537
408
|
```
|
|
538
409
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
```bash
|
|
542
|
-
bcp db create create_users
|
|
543
|
-
bcp db migrate
|
|
544
|
-
bcp db status
|
|
545
|
-
bcp db rollback
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
Project generators:
|
|
410
|
+
Generators:
|
|
549
411
|
|
|
550
412
|
```bash
|
|
551
413
|
bcp generate page dashboard/users
|
|
@@ -557,27 +419,35 @@ bcp generate migration create_users
|
|
|
557
419
|
## Production model
|
|
558
420
|
|
|
559
421
|
```text
|
|
560
|
-
Browser / API
|
|
561
|
-
|
|
562
|
-
security +
|
|
563
|
-
|
|
422
|
+
Browser / API
|
|
423
|
+
|
|
|
424
|
+
security + auth + middleware
|
|
425
|
+
|
|
|
564
426
|
loaders / actions / API routes
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
427
|
+
|
|
|
428
|
+
Database transaction
|
|
429
|
+
|\
|
|
430
|
+
| +--> transactional outbox
|
|
431
|
+
| |
|
|
432
|
+
| dispatcher
|
|
433
|
+
| |
|
|
434
|
+
| durable jobs
|
|
435
|
+
| |
|
|
436
|
+
| workers
|
|
437
|
+
|
|
|
438
|
+
SSR / response
|
|
439
|
+
|
|
440
|
+
Workflow + scheduler + logs + metrics + health
|
|
441
|
+
operate alongside the request path.
|
|
574
442
|
```
|
|
575
443
|
|
|
576
|
-
|
|
444
|
+
## Packaging
|
|
445
|
+
|
|
446
|
+
Raw production build:
|
|
577
447
|
|
|
578
448
|
```bash
|
|
579
449
|
npm run build
|
|
580
|
-
npm
|
|
450
|
+
npm start
|
|
581
451
|
```
|
|
582
452
|
|
|
583
453
|
Deployment package:
|
|
@@ -590,31 +460,30 @@ bcp package
|
|
|
590
460
|
|
|
591
461
|
The framework repository is the documentation source of truth.
|
|
592
462
|
|
|
593
|
-
|
|
463
|
+
Machine-readable contracts:
|
|
594
464
|
|
|
595
465
|
```text
|
|
596
|
-
docs/docs-web-manifest.json
|
|
597
466
|
docs/platform-manifest.json
|
|
467
|
+
docs/docs-web-manifest.json
|
|
598
468
|
docs/api-manifest.json
|
|
599
469
|
```
|
|
600
470
|
|
|
601
471
|
## Release validation
|
|
602
472
|
|
|
603
|
-
|
|
473
|
+
Before publishing `0.2.12`:
|
|
604
474
|
|
|
605
475
|
```bash
|
|
606
|
-
npm install
|
|
607
476
|
npm run typecheck
|
|
608
477
|
npm run test:unit
|
|
609
478
|
npm run test:integration
|
|
610
|
-
npm run test:package
|
|
611
479
|
npm run test:e2e
|
|
480
|
+
npm run test:package
|
|
612
481
|
npm run rc:check
|
|
613
482
|
```
|
|
614
483
|
|
|
615
|
-
`0.2.
|
|
484
|
+
`0.2.12` adds unit and prepared-package smoke coverage for transaction-bound outbox writes, dispatcher queue handoff, retry/failure behavior, stale lease recovery, SQL migration generation, public export/runtime compilation and browser boundary enforcement.
|
|
616
485
|
|
|
617
|
-
Do not tag or publish until the final release commit passes the
|
|
486
|
+
Do not tag or publish until the exact final release commit passes the full RC sequence.
|
|
618
487
|
|
|
619
488
|
## Release history
|
|
620
489
|
|
|
@@ -638,12 +507,15 @@ Do not tag or publish until the final release commit passes the complete RC sequ
|
|
|
638
507
|
| `0.2.9` | Job Scheduling Platform |
|
|
639
508
|
| `0.2.10` | Durable Jobs Platform |
|
|
640
509
|
| `0.2.11` | Workflow Orchestration |
|
|
510
|
+
| `0.2.12` | Transactional Outbox & Events |
|
|
641
511
|
|
|
642
512
|
## Roadmap
|
|
643
513
|
|
|
644
|
-
`0.2.
|
|
514
|
+
`0.2.12` closes the database-commit / external-publish gap and establishes a provider-neutral event-delivery boundary on top of Database + Durable Jobs.
|
|
515
|
+
|
|
516
|
+
The next logical milestone is **`0.2.13 — Realtime Platform`**, adding WebSocket/SSE channels, rooms/presence, authenticated realtime connections and live delivery for workflow/job/event progress without changing the current outbox/job contracts.
|
|
645
517
|
|
|
646
|
-
|
|
518
|
+
Native desktop/mobile compilation remains later roadmap work.
|
|
647
519
|
|
|
648
520
|
## License
|
|
649
521
|
|