@chidchanun/bcp 0.2.10 → 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 +231 -286
- package/docs/README.md +60 -61
- package/docs/api-manifest.json +29 -2
- package/docs/api-reference.md +105 -85
- package/docs/docs-web-manifest.json +9 -5
- package/docs/platform-manifest.json +27 -4
- package/docs/releases/0.2.11.md +180 -0
- package/docs/releases/0.2.12.md +147 -0
- package/docs/transactional-outbox-events.md +465 -0
- package/docs/workflow-orchestration.md +374 -0
- package/package.json +11 -1
- package/packages/bundler/src/client-boundary.ts +2 -0
- package/packages/client/src/events.mjs +889 -0
- package/packages/client/src/events.ts +31 -0
- package/packages/client/src/workflow.mjs +601 -0
- package/packages/client/src/workflow.ts +23 -0
- package/packages/server/src/events.ts +1416 -0
- package/packages/server/src/workflow.ts +887 -0
package/README.md
CHANGED
|
@@ -1,54 +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
|
-
| Uploads |
|
|
46
|
-
| 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 |
|
|
47
31
|
| Caching | Response cache and revalidation primitives |
|
|
48
|
-
| Configuration | Typed
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
| 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 |
|
|
52
35
|
|
|
53
36
|
## Requirements
|
|
54
37
|
|
|
@@ -56,7 +39,7 @@ docs/api-manifest.json
|
|
|
56
39
|
- React `19`
|
|
57
40
|
- npm
|
|
58
41
|
|
|
59
|
-
|
|
42
|
+
Optional SQL drivers:
|
|
60
43
|
|
|
61
44
|
```text
|
|
62
45
|
MySQL mysql2
|
|
@@ -72,7 +55,7 @@ cd my-app
|
|
|
72
55
|
npm run dev
|
|
73
56
|
```
|
|
74
57
|
|
|
75
|
-
Generated projects normally
|
|
58
|
+
Generated projects normally use one framework dependency:
|
|
76
59
|
|
|
77
60
|
```json
|
|
78
61
|
{
|
|
@@ -82,55 +65,7 @@ Generated projects normally keep one framework dependency key:
|
|
|
82
65
|
}
|
|
83
66
|
```
|
|
84
67
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
## Configuration & environment
|
|
88
|
-
|
|
89
|
-
Framework configuration stays in one of:
|
|
90
|
-
|
|
91
|
-
```text
|
|
92
|
-
bcp.config.ts
|
|
93
|
-
bcp.config.mts
|
|
94
|
-
bcp.config.js
|
|
95
|
-
bcp.config.mjs
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Application environment validation can be declared in:
|
|
99
|
-
|
|
100
|
-
```text
|
|
101
|
-
bcp.environment.ts
|
|
102
|
-
bcp.environment.mts
|
|
103
|
-
bcp.environment.js
|
|
104
|
-
bcp.environment.mjs
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Configuration precedence is:
|
|
108
|
-
|
|
109
|
-
```text
|
|
110
|
-
CLI override
|
|
111
|
-
↓
|
|
112
|
-
BCP_* environment
|
|
113
|
-
↓
|
|
114
|
-
bcp.config.*
|
|
115
|
-
↓
|
|
116
|
-
framework defaults
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Validate configuration and declared environment values with:
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
bcp config check
|
|
123
|
-
bcp config check --json
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
Variables beginning with `BCP_PUBLIC_` may be embedded in browser output. Never expose application secrets through public-prefixed variables.
|
|
127
|
-
|
|
128
|
-
Read more:
|
|
129
|
-
|
|
130
|
-
- [Configuration](docs/configuration.md)
|
|
131
|
-
- [Environment Validation](docs/environment-validation.md)
|
|
132
|
-
|
|
133
|
-
## Database Platform v2 — 0.2.3
|
|
68
|
+
## Database Platform
|
|
134
69
|
|
|
135
70
|
```ts
|
|
136
71
|
import {
|
|
@@ -139,14 +74,6 @@ import {
|
|
|
139
74
|
} from "bcp/database";
|
|
140
75
|
```
|
|
141
76
|
|
|
142
|
-
Built-in SQL providers:
|
|
143
|
-
|
|
144
|
-
```text
|
|
145
|
-
mysql
|
|
146
|
-
postgresql
|
|
147
|
-
sqlite
|
|
148
|
-
```
|
|
149
|
-
|
|
150
77
|
Migration CLI:
|
|
151
78
|
|
|
152
79
|
```bash
|
|
@@ -156,61 +83,17 @@ bcp db status
|
|
|
156
83
|
bcp db rollback
|
|
157
84
|
```
|
|
158
85
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
- [Database](docs/database.md)
|
|
162
|
-
- [Database Migrations](docs/database-migrations.md)
|
|
163
|
-
|
|
164
|
-
## Application Packaging — 0.2.4
|
|
165
|
-
|
|
166
|
-
Create a fresh production build and deployment package:
|
|
167
|
-
|
|
168
|
-
```bash
|
|
169
|
-
bcp package
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
Output is written under:
|
|
173
|
-
|
|
174
|
-
```text
|
|
175
|
-
.bcp-framework/package/
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
Read more:
|
|
179
|
-
|
|
180
|
-
- [Application Packaging](docs/application-packaging.md)
|
|
181
|
-
- [Deployment](docs/deployment.md)
|
|
182
|
-
|
|
183
|
-
## Authentication Platform v2 — 0.2.5
|
|
86
|
+
## Authentication & authorization
|
|
184
87
|
|
|
185
88
|
```ts
|
|
186
89
|
import {
|
|
187
|
-
auth,
|
|
188
90
|
createAuth,
|
|
189
91
|
createMemoryAuthSessionStore,
|
|
190
|
-
login,
|
|
191
|
-
logout,
|
|
192
|
-
} from "bcp/auth";
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
Stateless signed JWT-cookie authentication remains supported. Applications that need centralized revocation can configure an `AuthSessionStore`.
|
|
196
|
-
|
|
197
|
-
Read more:
|
|
198
|
-
|
|
199
|
-
- [Authentication](docs/authentication.md)
|
|
200
|
-
- [Auth Session Stores](docs/auth-session-store.md)
|
|
201
|
-
- [Auth Route Guards](docs/auth-route-guards.md)
|
|
202
|
-
|
|
203
|
-
## Authorization & Security v2 — 0.2.6
|
|
204
|
-
|
|
205
|
-
```ts
|
|
206
|
-
import {
|
|
207
|
-
authorize,
|
|
208
|
-
hasPermission,
|
|
209
92
|
requirePermission,
|
|
210
93
|
} from "bcp/auth";
|
|
211
94
|
```
|
|
212
95
|
|
|
213
|
-
Request
|
|
96
|
+
Request security is available from `bcp/server`:
|
|
214
97
|
|
|
215
98
|
```ts
|
|
216
99
|
import {
|
|
@@ -220,9 +103,7 @@ import {
|
|
|
220
103
|
} from "bcp/server";
|
|
221
104
|
```
|
|
222
105
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
## Observability Platform v2 — 0.2.7
|
|
106
|
+
## Observability
|
|
226
107
|
|
|
227
108
|
```ts
|
|
228
109
|
import {
|
|
@@ -232,9 +113,7 @@ import {
|
|
|
232
113
|
} from "bcp/observability";
|
|
233
114
|
```
|
|
234
115
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
## Background Jobs Platform — 0.2.8
|
|
116
|
+
## Background jobs
|
|
238
117
|
|
|
239
118
|
```ts
|
|
240
119
|
import {
|
|
@@ -245,7 +124,7 @@ export const jobs =
|
|
|
245
124
|
createJobQueue();
|
|
246
125
|
```
|
|
247
126
|
|
|
248
|
-
Register work:
|
|
127
|
+
Register typed work:
|
|
249
128
|
|
|
250
129
|
```ts
|
|
251
130
|
jobs.register<{
|
|
@@ -260,24 +139,7 @@ jobs.register<{
|
|
|
260
139
|
);
|
|
261
140
|
```
|
|
262
141
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
```ts
|
|
266
|
-
await jobs.enqueue(
|
|
267
|
-
"email.welcome",
|
|
268
|
-
{
|
|
269
|
-
userId: 42,
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
delayMs: 5_000,
|
|
273
|
-
maxAttempts: 5,
|
|
274
|
-
}
|
|
275
|
-
);
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
Read more: [Background Jobs Platform](docs/background-jobs.md)
|
|
279
|
-
|
|
280
|
-
## Job Scheduling Platform — 0.2.9
|
|
142
|
+
## Job scheduling
|
|
281
143
|
|
|
282
144
|
```ts
|
|
283
145
|
import {
|
|
@@ -290,20 +152,7 @@ export const scheduler =
|
|
|
290
152
|
});
|
|
291
153
|
```
|
|
292
154
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
```ts
|
|
296
|
-
await scheduler.schedule(
|
|
297
|
-
"cache.cleanup",
|
|
298
|
-
{},
|
|
299
|
-
{
|
|
300
|
-
id: "cache-cleanup",
|
|
301
|
-
everyMs: 5 * 60 * 1000,
|
|
302
|
-
}
|
|
303
|
-
);
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
UTC cron schedule:
|
|
155
|
+
UTC cron example:
|
|
307
156
|
|
|
308
157
|
```ts
|
|
309
158
|
await scheduler.schedule(
|
|
@@ -315,11 +164,9 @@ await scheduler.schedule(
|
|
|
315
164
|
);
|
|
316
165
|
```
|
|
317
166
|
|
|
318
|
-
Read more: [Job Scheduling Platform](docs/job-scheduling.md)
|
|
319
|
-
|
|
320
167
|
## Durable Jobs Platform — 0.2.10
|
|
321
168
|
|
|
322
|
-
Workers
|
|
169
|
+
Workers support visibility leases, heartbeat renewal and stale-running recovery:
|
|
323
170
|
|
|
324
171
|
```ts
|
|
325
172
|
const worker =
|
|
@@ -328,104 +175,202 @@ const worker =
|
|
|
328
175
|
concurrency: 4,
|
|
329
176
|
visibilityTimeoutMs: 30_000,
|
|
330
177
|
heartbeatIntervalMs: 10_000,
|
|
331
|
-
pollIntervalMs: 250,
|
|
332
178
|
});
|
|
333
179
|
```
|
|
334
180
|
|
|
335
|
-
|
|
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.
|
|
182
|
+
|
|
183
|
+
## Workflow Orchestration — 0.2.11
|
|
336
184
|
|
|
337
185
|
```ts
|
|
338
|
-
|
|
339
|
-
|
|
186
|
+
import {
|
|
187
|
+
createWorkflow,
|
|
188
|
+
} from "bcp/workflow";
|
|
189
|
+
|
|
190
|
+
export const onboarding =
|
|
191
|
+
createWorkflow<{
|
|
192
|
+
userId: number;
|
|
193
|
+
}>(
|
|
194
|
+
"user.onboarding",
|
|
195
|
+
workflow => {
|
|
196
|
+
workflow.step(
|
|
197
|
+
"profile",
|
|
198
|
+
createProfile
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
workflow.parallel(
|
|
202
|
+
"initialize",
|
|
203
|
+
parallel => {
|
|
204
|
+
parallel.step(
|
|
205
|
+
"preferences",
|
|
206
|
+
createPreferences
|
|
207
|
+
);
|
|
208
|
+
parallel.step(
|
|
209
|
+
"workspace",
|
|
210
|
+
createWorkspace
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
workflow.delay(
|
|
216
|
+
"cooldown",
|
|
217
|
+
1_000
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
```
|
|
222
|
+
|
|
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:
|
|
340
230
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
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
|
+
);
|
|
346
279
|
}
|
|
347
280
|
);
|
|
348
281
|
```
|
|
349
282
|
|
|
350
|
-
|
|
283
|
+
Generate the outbox table migration for the configured provider:
|
|
351
284
|
|
|
352
285
|
```ts
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const stats =
|
|
358
|
-
await jobs.stats();
|
|
359
|
-
|
|
360
|
-
await jobs.cleanup({
|
|
361
|
-
before:
|
|
362
|
-
Date.now() -
|
|
363
|
-
7 * 24 * 60 * 60 * 1000,
|
|
364
|
-
});
|
|
365
|
-
```
|
|
286
|
+
import {
|
|
287
|
+
createOutboxMigrationSql,
|
|
288
|
+
} from "bcp/events";
|
|
366
289
|
|
|
367
|
-
|
|
290
|
+
const sql =
|
|
291
|
+
createOutboxMigrationSql(
|
|
292
|
+
"postgresql"
|
|
293
|
+
);
|
|
294
|
+
```
|
|
368
295
|
|
|
369
|
-
|
|
296
|
+
Supported providers:
|
|
370
297
|
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
): Promise<unknown>;
|
|
376
|
-
}
|
|
298
|
+
```text
|
|
299
|
+
mysql
|
|
300
|
+
postgresql
|
|
301
|
+
sqlite
|
|
377
302
|
```
|
|
378
303
|
|
|
379
|
-
|
|
304
|
+
### Dispatcher
|
|
305
|
+
|
|
306
|
+
After the SQL transaction commits, a dispatcher claims due events and delivers them:
|
|
380
307
|
|
|
381
308
|
```ts
|
|
382
309
|
import {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
createRedisJobQueueAdapter,
|
|
386
|
-
createRedisJobScheduleStore,
|
|
387
|
-
} from "bcp/jobs";
|
|
310
|
+
createOutboxDispatcher,
|
|
311
|
+
} from "bcp/events";
|
|
388
312
|
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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,
|
|
393
321
|
});
|
|
394
322
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
});
|
|
323
|
+
const runner =
|
|
324
|
+
dispatcher.start();
|
|
325
|
+
```
|
|
399
326
|
|
|
400
|
-
|
|
401
|
-
createRedisJobScheduleStore({
|
|
402
|
-
client: redisCommandClient,
|
|
403
|
-
namespace: "my-app:{jobs}",
|
|
404
|
-
});
|
|
327
|
+
With `queue: jobs`, event type:
|
|
405
328
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
queue: jobs,
|
|
409
|
-
store: scheduleStore,
|
|
410
|
-
ownerId: "scheduler-a",
|
|
411
|
-
});
|
|
329
|
+
```text
|
|
330
|
+
order.created
|
|
412
331
|
```
|
|
413
332
|
|
|
414
|
-
|
|
333
|
+
is handed off as:
|
|
415
334
|
|
|
416
|
-
|
|
335
|
+
```text
|
|
336
|
+
event.order.created
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Register its durable consumer:
|
|
417
340
|
|
|
418
|
-
```
|
|
419
|
-
|
|
341
|
+
```ts
|
|
342
|
+
jobs.register(
|
|
343
|
+
"event.order.created",
|
|
344
|
+
async ({ payload }) => {
|
|
345
|
+
await handleOrderCreated(
|
|
346
|
+
payload
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
);
|
|
420
350
|
```
|
|
421
351
|
|
|
422
|
-
|
|
352
|
+
Dispatcher features include:
|
|
353
|
+
|
|
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.
|
|
423
364
|
|
|
424
|
-
|
|
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)
|
|
425
370
|
|
|
426
371
|
## Public entrypoints
|
|
427
372
|
|
|
428
|
-
The current
|
|
373
|
+
The current documented platform surface is:
|
|
429
374
|
|
|
430
375
|
```text
|
|
431
376
|
bcp
|
|
@@ -437,24 +382,18 @@ bcp/error
|
|
|
437
382
|
bcp/database
|
|
438
383
|
bcp/auth
|
|
439
384
|
bcp/jobs
|
|
385
|
+
bcp/workflow
|
|
386
|
+
bcp/events
|
|
440
387
|
bcp/observability
|
|
441
388
|
bcp/server
|
|
442
389
|
bcp/server-only
|
|
443
390
|
bcp/middleware
|
|
444
391
|
```
|
|
445
392
|
|
|
446
|
-
Application code should use public entrypoints instead of importing
|
|
447
|
-
|
|
448
|
-
See:
|
|
449
|
-
|
|
450
|
-
- [API Reference](docs/api-reference.md)
|
|
451
|
-
- [Platform Manifest](docs/platform-manifest.json)
|
|
452
|
-
- [API Manifest](docs/api-manifest.json)
|
|
393
|
+
Application code should use public entrypoints instead of importing private `packages/*` implementation files.
|
|
453
394
|
|
|
454
395
|
## CLI
|
|
455
396
|
|
|
456
|
-
Core commands:
|
|
457
|
-
|
|
458
397
|
```bash
|
|
459
398
|
bcp dev
|
|
460
399
|
bcp build
|
|
@@ -468,16 +407,7 @@ bcp inspect
|
|
|
468
407
|
bcp version
|
|
469
408
|
```
|
|
470
409
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
```bash
|
|
474
|
-
bcp db create create_users
|
|
475
|
-
bcp db migrate
|
|
476
|
-
bcp db status
|
|
477
|
-
bcp db rollback
|
|
478
|
-
```
|
|
479
|
-
|
|
480
|
-
Project generators:
|
|
410
|
+
Generators:
|
|
481
411
|
|
|
482
412
|
```bash
|
|
483
413
|
bcp generate page dashboard/users
|
|
@@ -489,23 +419,35 @@ bcp generate migration create_users
|
|
|
489
419
|
## Production model
|
|
490
420
|
|
|
491
421
|
```text
|
|
492
|
-
Browser / API
|
|
493
|
-
|
|
494
|
-
security +
|
|
495
|
-
|
|
422
|
+
Browser / API
|
|
423
|
+
|
|
|
424
|
+
security + auth + middleware
|
|
425
|
+
|
|
|
496
426
|
loaders / actions / API routes
|
|
497
|
-
|
|
498
|
-
|
|
427
|
+
|
|
|
428
|
+
Database transaction
|
|
429
|
+
|\
|
|
430
|
+
| +--> transactional outbox
|
|
431
|
+
| |
|
|
432
|
+
| dispatcher
|
|
433
|
+
| |
|
|
434
|
+
| durable jobs
|
|
435
|
+
| |
|
|
436
|
+
| workers
|
|
437
|
+
|
|
|
438
|
+
SSR / response
|
|
499
439
|
|
|
500
|
-
|
|
501
|
-
|
|
440
|
+
Workflow + scheduler + logs + metrics + health
|
|
441
|
+
operate alongside the request path.
|
|
502
442
|
```
|
|
503
443
|
|
|
504
|
-
|
|
444
|
+
## Packaging
|
|
445
|
+
|
|
446
|
+
Raw production build:
|
|
505
447
|
|
|
506
448
|
```bash
|
|
507
449
|
npm run build
|
|
508
|
-
npm
|
|
450
|
+
npm start
|
|
509
451
|
```
|
|
510
452
|
|
|
511
453
|
Deployment package:
|
|
@@ -518,31 +460,30 @@ bcp package
|
|
|
518
460
|
|
|
519
461
|
The framework repository is the documentation source of truth.
|
|
520
462
|
|
|
521
|
-
|
|
463
|
+
Machine-readable contracts:
|
|
522
464
|
|
|
523
465
|
```text
|
|
524
|
-
docs/docs-web-manifest.json
|
|
525
466
|
docs/platform-manifest.json
|
|
467
|
+
docs/docs-web-manifest.json
|
|
526
468
|
docs/api-manifest.json
|
|
527
469
|
```
|
|
528
470
|
|
|
529
471
|
## Release validation
|
|
530
472
|
|
|
531
|
-
|
|
473
|
+
Before publishing `0.2.12`:
|
|
532
474
|
|
|
533
475
|
```bash
|
|
534
|
-
npm install
|
|
535
476
|
npm run typecheck
|
|
536
477
|
npm run test:unit
|
|
537
478
|
npm run test:integration
|
|
538
|
-
npm run test:package
|
|
539
479
|
npm run test:e2e
|
|
480
|
+
npm run test:package
|
|
540
481
|
npm run rc:check
|
|
541
482
|
```
|
|
542
483
|
|
|
543
|
-
`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.
|
|
544
485
|
|
|
545
|
-
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.
|
|
546
487
|
|
|
547
488
|
## Release history
|
|
548
489
|
|
|
@@ -565,12 +506,16 @@ Do not tag or publish until the final release commit passes the complete RC sequ
|
|
|
565
506
|
| `0.2.8` | Background Jobs Platform |
|
|
566
507
|
| `0.2.9` | Job Scheduling Platform |
|
|
567
508
|
| `0.2.10` | Durable Jobs Platform |
|
|
509
|
+
| `0.2.11` | Workflow Orchestration |
|
|
510
|
+
| `0.2.12` | Transactional Outbox & Events |
|
|
568
511
|
|
|
569
512
|
## Roadmap
|
|
570
513
|
|
|
571
|
-
`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.
|
|
572
517
|
|
|
573
|
-
|
|
518
|
+
Native desktop/mobile compilation remains later roadmap work.
|
|
574
519
|
|
|
575
520
|
## License
|
|
576
521
|
|