create-bcp-app 0.2.8 → 0.2.9
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 +53 -191
- package/package.json +1 -1
- package/template/README.md +59 -110
package/README.md
CHANGED
|
@@ -92,10 +92,10 @@ Example:
|
|
|
92
92
|
"schemaVersion": 1,
|
|
93
93
|
"framework": "bcp",
|
|
94
94
|
"projectName": "my-app",
|
|
95
|
-
"frameworkPackage": "npm:@chidchanun/bcp@0.2.
|
|
95
|
+
"frameworkPackage": "npm:@chidchanun/bcp@0.2.9",
|
|
96
96
|
"createdWith": {
|
|
97
97
|
"package": "create-bcp-app",
|
|
98
|
-
"version": "0.2.
|
|
98
|
+
"version": "0.2.9"
|
|
99
99
|
},
|
|
100
100
|
"packageManager": "npm",
|
|
101
101
|
"presets": {
|
|
@@ -133,14 +133,7 @@ npm exec -- bcp-framework update --check
|
|
|
133
133
|
|
|
134
134
|
## Tailwind CSS
|
|
135
135
|
|
|
136
|
-
When Tailwind is enabled, the project includes
|
|
137
|
-
|
|
138
|
-
- `tailwindcss`
|
|
139
|
-
- `@tailwindcss/cli`
|
|
140
|
-
- `concurrently`
|
|
141
|
-
- `app/globals.css`
|
|
142
|
-
- `/bcp.css` stylesheet setup
|
|
143
|
-
- starter utility classes
|
|
136
|
+
When Tailwind is enabled, the project includes `tailwindcss`, `@tailwindcss/cli`, `concurrently`, `app/globals.css`, `/bcp.css` stylesheet setup and starter utility classes.
|
|
144
137
|
|
|
145
138
|
Generated commands include:
|
|
146
139
|
|
|
@@ -162,9 +155,9 @@ The database choice adds starter configuration and the matching driver:
|
|
|
162
155
|
- MongoDB: `mongodb`
|
|
163
156
|
- None: no database dependency
|
|
164
157
|
|
|
165
|
-
For **MySQL**, **PostgreSQL** and **SQLite**, generated `lib/database.ts` exposes
|
|
158
|
+
For **MySQL**, **PostgreSQL** and **SQLite**, generated `lib/database.ts` exposes framework database primitives through `bcp/database`.
|
|
166
159
|
|
|
167
|
-
Generated
|
|
160
|
+
Generated examples:
|
|
168
161
|
|
|
169
162
|
```dotenv
|
|
170
163
|
DB_HOST=localhost
|
|
@@ -174,100 +167,25 @@ DB_PASSWORD=
|
|
|
174
167
|
DB_NAME=bcp_app
|
|
175
168
|
```
|
|
176
169
|
|
|
177
|
-
Generated PostgreSQL environment variable:
|
|
178
|
-
|
|
179
170
|
```dotenv
|
|
180
171
|
DATABASE_URL=postgresql://postgres:password@localhost:5432/bcp_app
|
|
181
172
|
```
|
|
182
173
|
|
|
183
|
-
Generated SQLite environment variable:
|
|
184
|
-
|
|
185
174
|
```dotenv
|
|
186
175
|
DATABASE_URL=./data/bcp.sqlite
|
|
187
176
|
```
|
|
188
177
|
|
|
189
|
-
`bcp/database` infers PostgreSQL from `postgres://` or `postgresql://` connection URLs. SQLite is inferred from `:memory:`, `sqlite:` / `file:` locations and common `.sqlite`, `.sqlite3` or `.db` file paths. Applications may also configure `DB_DRIVER` explicitly.
|
|
190
|
-
|
|
191
|
-
Placeholder syntax follows the selected provider:
|
|
192
|
-
|
|
193
|
-
```text
|
|
194
|
-
MySQL ?
|
|
195
|
-
SQLite ?
|
|
196
|
-
PostgreSQL $1, $2, ...
|
|
197
|
-
```
|
|
198
|
-
|
|
199
178
|
The generator intentionally does not force an ORM.
|
|
200
179
|
|
|
201
180
|
## Storage providers
|
|
202
181
|
|
|
203
|
-
Selecting a storage provider creates `lib/storage.ts` and
|
|
204
|
-
|
|
205
|
-
### Local Server
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
npx create-bcp-app my-app --storage local
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
Environment:
|
|
212
|
-
|
|
213
|
-
```dotenv
|
|
214
|
-
STORAGE_LOCAL_DIRECTORY=./storage
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
The generated helper uses `createLocalStorage()`.
|
|
218
|
-
|
|
219
|
-
### Amazon S3
|
|
220
|
-
|
|
221
|
-
```bash
|
|
222
|
-
npx create-bcp-app my-app --storage amazon-s3
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
Generated environment settings:
|
|
226
|
-
|
|
227
|
-
```dotenv
|
|
228
|
-
AWS_S3_BUCKET=
|
|
229
|
-
AWS_REGION=ap-southeast-1
|
|
230
|
-
AWS_ACCESS_KEY_ID=
|
|
231
|
-
AWS_SECRET_ACCESS_KEY=
|
|
232
|
-
AWS_SESSION_TOKEN=
|
|
233
|
-
AWS_S3_PREFIX=
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
The helper uses `createS3Storage()`. Explicit credentials can remain unset when deployment uses the AWS SDK server-side credential chain, such as an IAM role.
|
|
237
|
-
|
|
238
|
-
### Cloudflare R2
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
npx create-bcp-app my-app --storage cloudflare-r2
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
Generated environment settings:
|
|
245
|
-
|
|
246
|
-
```dotenv
|
|
247
|
-
R2_ACCOUNT_ID=
|
|
248
|
-
R2_BUCKET=
|
|
249
|
-
R2_ACCESS_KEY_ID=
|
|
250
|
-
R2_SECRET_ACCESS_KEY=
|
|
251
|
-
R2_PREFIX=
|
|
252
|
-
```
|
|
182
|
+
Selecting a storage provider creates `lib/storage.ts` and provider-specific environment settings. Supported presets are Local Server, Amazon S3 and Cloudflare R2.
|
|
253
183
|
|
|
254
184
|
Storage credentials are server-only. Do not expose them through `BCP_PUBLIC_*` variables.
|
|
255
185
|
|
|
256
186
|
## JWT Cookie authentication
|
|
257
187
|
|
|
258
|
-
Selecting `JWT Cookie` creates:
|
|
259
|
-
|
|
260
|
-
```text
|
|
261
|
-
lib/
|
|
262
|
-
└─ auth.ts
|
|
263
|
-
|
|
264
|
-
app/api/auth/
|
|
265
|
-
├─ login/route.ts
|
|
266
|
-
├─ logout/route.ts
|
|
267
|
-
└─ me/route.ts
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
and adds:
|
|
188
|
+
Selecting `JWT Cookie` creates `lib/auth.ts` and starter `/api/auth/login`, `/logout` and `/me` routes, and adds:
|
|
271
189
|
|
|
272
190
|
```dotenv
|
|
273
191
|
BCP_SESSION_SECRET=
|
|
@@ -275,54 +193,20 @@ BCP_SESSION_SECRET=
|
|
|
275
193
|
|
|
276
194
|
Set this to a cryptographically random secret of at least 32 bytes before real authentication use.
|
|
277
195
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
Generated auth stays in backward-compatible stateless JWT-cookie mode by default.
|
|
281
|
-
|
|
282
|
-
BCP `0.2.5+` can opt into revocable server-side auth state without changing the generated auth route structure:
|
|
196
|
+
BCP `0.2.5+` can opt into revocable server-side auth state:
|
|
283
197
|
|
|
284
198
|
```ts
|
|
285
199
|
import {
|
|
286
200
|
createAuth,
|
|
287
201
|
createMemoryAuthSessionStore,
|
|
288
202
|
} from "bcp/auth";
|
|
289
|
-
|
|
290
|
-
const sessionStore =
|
|
291
|
-
createMemoryAuthSessionStore();
|
|
292
|
-
|
|
293
|
-
const frameworkAuth =
|
|
294
|
-
createAuth<AuthenticatedUser>({
|
|
295
|
-
store: sessionStore,
|
|
296
|
-
idleTimeout: 60 * 30,
|
|
297
|
-
});
|
|
298
203
|
```
|
|
299
204
|
|
|
300
205
|
The memory store is intended for development/tests. Multi-process production deployments should implement `AuthSessionStore` using shared durable storage.
|
|
301
206
|
|
|
302
207
|
## Authorization & request security — 0.2.6+
|
|
303
208
|
|
|
304
|
-
Generated applications can
|
|
305
|
-
|
|
306
|
-
```ts
|
|
307
|
-
import {
|
|
308
|
-
createPermissionGuard,
|
|
309
|
-
hasPermission,
|
|
310
|
-
} from "bcp/auth";
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
For resource-specific decisions, use `defineAuthorizationPolicy()`, `can()` or `authorize()`.
|
|
314
|
-
|
|
315
|
-
Cookie-authenticated mutation routes can opt into same-origin and CSRF protection through `bcp/server`:
|
|
316
|
-
|
|
317
|
-
```ts
|
|
318
|
-
import {
|
|
319
|
-
createCsrfToken,
|
|
320
|
-
requireCsrfRequest,
|
|
321
|
-
requireSameOriginRequest,
|
|
322
|
-
} from "bcp/server";
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
`createCsrfToken()` uses `BCP_CSRF_SECRET` when configured and otherwise falls back to `BCP_SESSION_SECRET`, so the generated JWT auth preset does not require another environment variable to get started. Production applications may define a separate `BCP_CSRF_SECRET` for independent key rotation.
|
|
209
|
+
Generated applications can use permission guards and resource policies from `bcp/auth`, plus same-origin and CSRF protection from `bcp/server`.
|
|
326
210
|
|
|
327
211
|
Authorization and CSRF checks must remain on the server; hiding UI controls in client code is not an authorization boundary.
|
|
328
212
|
|
|
@@ -336,25 +220,8 @@ import {
|
|
|
336
220
|
createMetricsRegistry,
|
|
337
221
|
createRequestMetricsMiddleware,
|
|
338
222
|
} from "bcp/observability";
|
|
339
|
-
|
|
340
|
-
export const metrics =
|
|
341
|
-
createMetricsRegistry();
|
|
342
|
-
|
|
343
|
-
export const health =
|
|
344
|
-
createHealthRegistry();
|
|
345
|
-
|
|
346
|
-
export const requestMetrics =
|
|
347
|
-
createRequestMetricsMiddleware(
|
|
348
|
-
metrics
|
|
349
|
-
);
|
|
350
223
|
```
|
|
351
224
|
|
|
352
|
-
Expose metrics from an application API route with `createMetricsResponse(metrics)`. The response uses Prometheus-compatible text format.
|
|
353
|
-
|
|
354
|
-
Health endpoints can return `health.response()`, which uses HTTP `200` when all checks pass and `503` when any dependency check fails or times out.
|
|
355
|
-
|
|
356
|
-
The default HTTP request metrics use `method` and `status` labels only. Raw paths are intentionally excluded to avoid high-cardinality metric series.
|
|
357
|
-
|
|
358
225
|
`bcp/observability` is server-only. Protect metrics and operational health detail with an appropriate network or authorization boundary when needed.
|
|
359
226
|
|
|
360
227
|
## Background jobs — 0.2.8+
|
|
@@ -370,27 +237,58 @@ export const jobs =
|
|
|
370
237
|
createJobQueue();
|
|
371
238
|
```
|
|
372
239
|
|
|
373
|
-
|
|
240
|
+
Workers support concurrency, delayed jobs, retry/backoff and cancellation. The default memory adapter is process-local and should be replaced with a durable `JobQueueAdapter` for production workloads that must survive restarts or coordinate across instances.
|
|
241
|
+
|
|
242
|
+
## Job scheduling — 0.2.9+
|
|
243
|
+
|
|
244
|
+
Recurring schedules use the same `bcp/jobs` entrypoint:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
import {
|
|
248
|
+
createJobScheduler,
|
|
249
|
+
} from "bcp/jobs";
|
|
250
|
+
|
|
251
|
+
export const scheduler =
|
|
252
|
+
createJobScheduler({
|
|
253
|
+
queue: jobs,
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Interval schedule:
|
|
374
258
|
|
|
375
259
|
```ts
|
|
376
|
-
|
|
377
|
-
"
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
);
|
|
260
|
+
await scheduler.schedule(
|
|
261
|
+
"cache.cleanup",
|
|
262
|
+
{},
|
|
263
|
+
{
|
|
264
|
+
everyMs: 300_000,
|
|
382
265
|
}
|
|
383
266
|
);
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
UTC cron schedule:
|
|
384
270
|
|
|
385
|
-
|
|
386
|
-
|
|
271
|
+
```ts
|
|
272
|
+
await scheduler.schedule(
|
|
273
|
+
"report.weekday",
|
|
274
|
+
{},
|
|
387
275
|
{
|
|
388
|
-
|
|
276
|
+
cron: "30 9 * * 1-5",
|
|
389
277
|
}
|
|
390
278
|
);
|
|
391
279
|
```
|
|
392
280
|
|
|
393
|
-
|
|
281
|
+
Start the scheduler loop:
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
const runner =
|
|
285
|
+
scheduler.start({
|
|
286
|
+
pollIntervalMs: 1_000,
|
|
287
|
+
leaseMs: 30_000,
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The default schedule store is process-local. Multi-instance production deployments should implement a shared durable `JobScheduleStore`; its `acquireDue()` operation must atomically lease due schedules. A durable scheduler deployment normally also uses a shared durable `JobQueueAdapter`.
|
|
394
292
|
|
|
395
293
|
`bcp/jobs` is server-only and must not be imported into page/client bundles.
|
|
396
294
|
|
|
@@ -402,32 +300,8 @@ Generated projects include:
|
|
|
402
300
|
npm run package
|
|
403
301
|
```
|
|
404
302
|
|
|
405
|
-
This runs the BCP `standalone-node` application packaging flow and writes:
|
|
406
|
-
|
|
407
|
-
```text
|
|
408
|
-
.bcp-framework/package/
|
|
409
|
-
├─ client/
|
|
410
|
-
├─ server/
|
|
411
|
-
├─ public/ # when present
|
|
412
|
-
├─ package.json
|
|
413
|
-
├─ package-lock.json # when a safe production lock can be derived
|
|
414
|
-
├─ bcp.package.json
|
|
415
|
-
├─ bcp.deployment.json
|
|
416
|
-
├─ bcp.env.json
|
|
417
|
-
├─ Dockerfile
|
|
418
|
-
└─ README.md
|
|
419
|
-
```
|
|
420
|
-
|
|
421
303
|
The deployment package excludes application `devDependencies` and project `.env` values. Supply real secrets through the deployment environment.
|
|
422
304
|
|
|
423
|
-
For a package with a generated production lockfile:
|
|
424
|
-
|
|
425
|
-
```bash
|
|
426
|
-
cd .bcp-framework/package
|
|
427
|
-
npm ci --omit=dev
|
|
428
|
-
npm start
|
|
429
|
-
```
|
|
430
|
-
|
|
431
305
|
## Project generators after creation
|
|
432
306
|
|
|
433
307
|
```bash
|
|
@@ -455,25 +329,13 @@ bcp generate migration create_users
|
|
|
455
329
|
--database <database> none | mysql | postgresql | sqlite | mongodb
|
|
456
330
|
--auth <preset> none | jwt-cookie
|
|
457
331
|
--storage <provider> none | local | amazon-s3 | cloudflare-r2
|
|
458
|
-
-y, --yes Accept defaults
|
|
332
|
+
-y, --yes Accept defaults
|
|
459
333
|
--bcp <specifier> Override dependencies.bcp
|
|
460
334
|
-h, --help Show help
|
|
461
335
|
```
|
|
462
336
|
|
|
463
|
-
Examples:
|
|
464
|
-
|
|
465
|
-
```bash
|
|
466
|
-
npx create-bcp-app my-app --tailwind --database mysql --auth jwt-cookie --storage local
|
|
467
|
-
npx create-bcp-app my-app --database postgresql
|
|
468
|
-
npx create-bcp-app my-app --database sqlite
|
|
469
|
-
npx create-bcp-app my-app --storage amazon-s3
|
|
470
|
-
npx create-bcp-app my-app --storage cloudflare-r2
|
|
471
|
-
npx create-bcp-app my-app --no-tailwind --database mongodb
|
|
472
|
-
npx create-bcp-app my-app --yes
|
|
473
|
-
```
|
|
474
|
-
|
|
475
337
|
The `--bcp` option is mainly for prerelease/local package verification:
|
|
476
338
|
|
|
477
339
|
```bash
|
|
478
|
-
npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.
|
|
340
|
+
npx create-bcp-app my-app --bcp file:../chidchanun-bcp-0.2.9.tgz
|
|
479
341
|
```
|
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -43,54 +43,13 @@ Commit this file with the project. Do not put passwords, access keys, session se
|
|
|
43
43
|
|
|
44
44
|
Projects created with the `JWT Cookie` preset remain stateless by default and use the generated `lib/auth.ts` helpers.
|
|
45
45
|
|
|
46
|
-
BCP Authentication Platform v2 can opt into revocable server-side session state
|
|
47
|
-
|
|
48
|
-
```ts
|
|
49
|
-
import {
|
|
50
|
-
createAuth,
|
|
51
|
-
createMemoryAuthSessionStore,
|
|
52
|
-
} from "bcp/auth";
|
|
53
|
-
|
|
54
|
-
const sessionStore =
|
|
55
|
-
createMemoryAuthSessionStore();
|
|
56
|
-
|
|
57
|
-
export const appAuth =
|
|
58
|
-
createAuth({
|
|
59
|
-
store: sessionStore,
|
|
60
|
-
idleTimeout: 60 * 30,
|
|
61
|
-
});
|
|
62
|
-
```
|
|
46
|
+
BCP Authentication Platform v2 can opt into revocable server-side session state with `createAuth()` and `AuthSessionStore`.
|
|
63
47
|
|
|
64
48
|
The memory store is intended for local development/tests. Use a shared durable `AuthSessionStore` implementation for multi-process or multi-container production deployments.
|
|
65
49
|
|
|
66
50
|
## Authorization & request security — BCP 0.2.6+
|
|
67
51
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```ts
|
|
71
|
-
import {
|
|
72
|
-
createPermissionGuard,
|
|
73
|
-
} from "bcp/auth";
|
|
74
|
-
|
|
75
|
-
export const guard =
|
|
76
|
-
createPermissionGuard(
|
|
77
|
-
"dashboard.read"
|
|
78
|
-
);
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
For ownership or resource-specific rules, use `defineAuthorizationPolicy()`, `can()` and `authorize()` from `bcp/auth`.
|
|
82
|
-
|
|
83
|
-
Cookie-authenticated mutation routes can validate browser origin and CSRF state:
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
import {
|
|
87
|
-
createCsrfToken,
|
|
88
|
-
requireCsrfRequest,
|
|
89
|
-
requireSameOriginRequest,
|
|
90
|
-
} from "bcp/server";
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
`createCsrfToken()` uses `BCP_CSRF_SECRET` when configured and otherwise falls back to `BCP_SESSION_SECRET`.
|
|
52
|
+
Use permission guards and resource policies from `bcp/auth`, and same-origin/CSRF protection from `bcp/server`.
|
|
94
53
|
|
|
95
54
|
Authorization must always be enforced server-side. Client UI visibility is not a security boundary.
|
|
96
55
|
|
|
@@ -104,25 +63,8 @@ import {
|
|
|
104
63
|
createMetricsRegistry,
|
|
105
64
|
createRequestMetricsMiddleware,
|
|
106
65
|
} from "bcp/observability";
|
|
107
|
-
|
|
108
|
-
export const metrics =
|
|
109
|
-
createMetricsRegistry();
|
|
110
|
-
|
|
111
|
-
export const health =
|
|
112
|
-
createHealthRegistry();
|
|
113
|
-
|
|
114
|
-
export const requestMetrics =
|
|
115
|
-
createRequestMetricsMiddleware(
|
|
116
|
-
metrics
|
|
117
|
-
);
|
|
118
66
|
```
|
|
119
67
|
|
|
120
|
-
Expose Prometheus-compatible metrics with `createMetricsResponse(metrics)` from a server API route.
|
|
121
|
-
|
|
122
|
-
Use `health.response()` for readiness endpoints. It returns HTTP `200` when all checks pass and `503` when a check fails or times out.
|
|
123
|
-
|
|
124
|
-
The default request metrics use bounded `method` and `status` labels and do not include raw paths.
|
|
125
|
-
|
|
126
68
|
Protect operational endpoints when their contents should not be public.
|
|
127
69
|
|
|
128
70
|
## Background jobs — BCP 0.2.8+
|
|
@@ -138,10 +80,12 @@ export const jobs =
|
|
|
138
80
|
createJobQueue();
|
|
139
81
|
```
|
|
140
82
|
|
|
141
|
-
Register
|
|
83
|
+
Register typed work:
|
|
142
84
|
|
|
143
85
|
```ts
|
|
144
|
-
jobs.register
|
|
86
|
+
jobs.register<{
|
|
87
|
+
userId: number;
|
|
88
|
+
}>(
|
|
145
89
|
"email.welcome",
|
|
146
90
|
async ({ payload }) => {
|
|
147
91
|
await sendWelcomeEmail(
|
|
@@ -149,18 +93,65 @@ jobs.register(
|
|
|
149
93
|
);
|
|
150
94
|
}
|
|
151
95
|
);
|
|
96
|
+
```
|
|
152
97
|
|
|
153
|
-
|
|
154
|
-
|
|
98
|
+
Workers support delayed jobs, retry/backoff, cancellation and configurable concurrency.
|
|
99
|
+
|
|
100
|
+
The default memory adapter is process-local and not durable. For production jobs that must survive restarts or run across multiple processes/containers, implement `JobQueueAdapter` with shared durable infrastructure.
|
|
101
|
+
|
|
102
|
+
## Job scheduling — BCP 0.2.9+
|
|
103
|
+
|
|
104
|
+
Add recurring schedules on top of the same queue:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import {
|
|
108
|
+
createJobScheduler,
|
|
109
|
+
} from "bcp/jobs";
|
|
110
|
+
|
|
111
|
+
export const scheduler =
|
|
112
|
+
createJobScheduler({
|
|
113
|
+
queue: jobs,
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Interval schedule:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
await scheduler.schedule(
|
|
121
|
+
"cache.cleanup",
|
|
122
|
+
{},
|
|
155
123
|
{
|
|
156
|
-
|
|
124
|
+
everyMs: 300_000,
|
|
157
125
|
}
|
|
158
126
|
);
|
|
159
127
|
```
|
|
160
128
|
|
|
161
|
-
|
|
129
|
+
UTC cron schedule:
|
|
162
130
|
|
|
163
|
-
|
|
131
|
+
```ts
|
|
132
|
+
await scheduler.schedule(
|
|
133
|
+
"report.weekday",
|
|
134
|
+
{},
|
|
135
|
+
{
|
|
136
|
+
cron: "30 9 * * 1-5",
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Start and stop the scheduler lifecycle:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const schedulerRunner =
|
|
145
|
+
scheduler.start({
|
|
146
|
+
pollIntervalMs: 1_000,
|
|
147
|
+
leaseMs: 30_000,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await schedulerRunner.stop();
|
|
151
|
+
await scheduler.close();
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The default `createMemoryJobScheduleStore()` is process-local. Multi-instance production deployments should implement a shared durable `JobScheduleStore` whose `acquireDue()` atomically leases due schedules. Durable deployments normally also use a shared `JobQueueAdapter`.
|
|
164
155
|
|
|
165
156
|
`bcp/jobs` is server-only and cannot be imported into page/client bundles.
|
|
166
157
|
|
|
@@ -209,39 +200,15 @@ npm exec -- bcp-framework build
|
|
|
209
200
|
npm exec -- bcp-framework package
|
|
210
201
|
```
|
|
211
202
|
|
|
212
|
-
You can also execute the Windows command shim explicitly:
|
|
213
|
-
|
|
214
|
-
```powershell
|
|
215
|
-
.\node_modules\.bin\bcp-framework.cmd --version
|
|
216
|
-
```
|
|
217
|
-
|
|
218
203
|
Microsoft SQL Server can install another Windows executable named `bcp.exe`, so the `bcp-framework` alias avoids that command-name collision.
|
|
219
204
|
|
|
220
|
-
Use this convention:
|
|
221
|
-
|
|
222
|
-
```text
|
|
223
|
-
Inside npm scripts -> bcp ...
|
|
224
|
-
Direct PowerShell usage -> npm exec -- bcp-framework ...
|
|
225
|
-
```
|
|
226
|
-
|
|
227
205
|
## Project diagnostics
|
|
228
206
|
|
|
229
|
-
Run:
|
|
230
|
-
|
|
231
207
|
```powershell
|
|
232
208
|
npm exec -- bcp-framework doctor
|
|
233
209
|
npm exec -- bcp-framework inspect
|
|
234
210
|
```
|
|
235
211
|
|
|
236
|
-
Machine-readable reports:
|
|
237
|
-
|
|
238
|
-
```powershell
|
|
239
|
-
npm exec -- bcp-framework doctor --json
|
|
240
|
-
npm exec -- bcp-framework inspect --json
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
Doctor checks common project/runtime problems while Inspect shows the resolved configuration, routes, dependencies and project metadata BCP sees.
|
|
244
|
-
|
|
245
212
|
## Production build
|
|
246
213
|
|
|
247
214
|
Create the raw standalone production build:
|
|
@@ -256,8 +223,6 @@ Start it with:
|
|
|
256
223
|
npm start
|
|
257
224
|
```
|
|
258
225
|
|
|
259
|
-
The production build is written to `.bcp-framework/build` and runs as a standalone Node.js server.
|
|
260
|
-
|
|
261
226
|
## Deployment package — BCP 0.2.4+
|
|
262
227
|
|
|
263
228
|
Create a fresh production build and deployment-oriented package:
|
|
@@ -266,22 +231,6 @@ Create a fresh production build and deployment-oriented package:
|
|
|
266
231
|
npm run package
|
|
267
232
|
```
|
|
268
233
|
|
|
269
|
-
The output is written to
|
|
270
|
-
|
|
271
|
-
```text
|
|
272
|
-
.bcp-framework/package/
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
It contains the standalone client/server output, a production-only dependency manifest, deployment/environment metadata, file integrity hashes and a starter Dockerfile.
|
|
234
|
+
The output is written to `.bcp-framework/package/` and contains standalone output, production dependency metadata, deployment/environment manifests, integrity hashes and a starter Dockerfile.
|
|
276
235
|
|
|
277
236
|
BCP intentionally excludes project `.env` files and application `devDependencies` from the deployment package. Provide secrets through your deployment environment.
|
|
278
|
-
|
|
279
|
-
For a package with a generated production lockfile:
|
|
280
|
-
|
|
281
|
-
```bash
|
|
282
|
-
cd .bcp-framework/package
|
|
283
|
-
npm ci --omit=dev
|
|
284
|
-
npm start
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
If `bcp.package.json` reports that no lockfile was included, use the install command recorded in that manifest instead.
|