@chidchanun/bcp 0.1.0
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/CHANGELOG.md +49 -0
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/docs/caching.md +76 -0
- package/docs/configuration.md +97 -0
- package/docs/deployment.md +74 -0
- package/docs/getting-started.md +82 -0
- package/docs/middleware.md +58 -0
- package/docs/releasing.md +299 -0
- package/docs/routing.md +103 -0
- package/docs/security.md +57 -0
- package/package.json +68 -0
- package/packages/bundler/src/client-islands.ts +1457 -0
- package/packages/bundler/src/incremental-context.ts +206 -0
- package/packages/bundler/src/index.ts +1991 -0
- package/packages/bundler/src/module-graph.ts +317 -0
- package/packages/bundler/src/partial-hydration.ts +414 -0
- package/packages/bundler/src/production.ts +974 -0
- package/packages/bundler/src/server-production-middleware.ts +447 -0
- package/packages/bundler/src/server-production.ts +1193 -0
- package/packages/bundler/src/special-files.ts +131 -0
- package/packages/cache/src/index.ts +761 -0
- package/packages/cli/bin/bcp.mjs +93 -0
- package/packages/cli/src/args.ts +305 -0
- package/packages/cli/src/bootstrap.ts +514 -0
- package/packages/cli/src/index.ts +504 -0
- package/packages/cli/src/version.ts +45 -0
- package/packages/client/src/cache.ts +11 -0
- package/packages/client/src/config.ts +18 -0
- package/packages/client/src/error-boundary.tsx +149 -0
- package/packages/client/src/hydration.ts +3 -0
- package/packages/client/src/index.tsx +57 -0
- package/packages/client/src/islands.tsx +315 -0
- package/packages/client/src/metadata.ts +281 -0
- package/packages/client/src/navigation-loading.ts +52 -0
- package/packages/client/src/navigation-state.ts +80 -0
- package/packages/client/src/not-found.ts +34 -0
- package/packages/client/src/persistent-layout-runtime.ts +273 -0
- package/packages/client/src/router-v2.tsx +969 -0
- package/packages/client/src/router.tsx +1 -0
- package/packages/config/src/index.ts +1038 -0
- package/packages/env/src/index.ts +593 -0
- package/packages/router/src/advanced-router.ts +1032 -0
- package/packages/router/src/index.ts +1 -0
- package/packages/server/src/compression.ts +249 -0
- package/packages/server/src/dev-document-metadata.ts +154 -0
- package/packages/server/src/dev-hmr.ts +225 -0
- package/packages/server/src/index.ts +2265 -0
- package/packages/server/src/metadata.ts +478 -0
- package/packages/server/src/middleware-dev-server.ts +260 -0
- package/packages/server/src/middleware-loader.ts +140 -0
- package/packages/server/src/middleware-proxy.ts +516 -0
- package/packages/server/src/middleware.ts +704 -0
- package/packages/server/src/navigation-payload.ts +471 -0
- package/packages/server/src/production-server.ts +1746 -0
- package/packages/server/src/response-cache-proxy.ts +828 -0
- package/packages/server/src/security-proxy.ts +406 -0
- package/packages/server/src/security.ts +451 -0
- package/packages/server/src/standalone-production-runtime-v2.ts +2047 -0
- package/packages/server/src/standalone-production-runtime-v3.ts +250 -0
- package/packages/server/src/standalone-production-runtime-v4.ts +289 -0
- package/packages/server/src/standalone-production-runtime-v5.ts +289 -0
- package/packages/server/src/standalone-production-runtime.ts +1951 -0
- package/packages/server/src/standalone-production-server.ts +6 -0
- package/packages/server/src/static-assets.ts +262 -0
- package/packages/server/src/static-dev-server.ts +854 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import {
|
|
2
|
+
spawn,
|
|
3
|
+
type ChildProcess,
|
|
4
|
+
} from "node:child_process";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import {
|
|
7
|
+
fileURLToPath,
|
|
8
|
+
} from "node:url";
|
|
9
|
+
|
|
10
|
+
import chokidar from "chokidar";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
applyResolvedBcpConfig,
|
|
14
|
+
getConfigFileNames,
|
|
15
|
+
resolveBcpConfig,
|
|
16
|
+
} from "../../config/src/index.js";
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
getEnvironmentFileNames,
|
|
20
|
+
loadEnvironment,
|
|
21
|
+
type EnvironmentMode,
|
|
22
|
+
} from "../../env/src/index.js";
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
parseCliArgs,
|
|
26
|
+
resolveProjectRoot,
|
|
27
|
+
type CliOptions,
|
|
28
|
+
} from "./args.js";
|
|
29
|
+
|
|
30
|
+
const options =
|
|
31
|
+
parseCliArgs(
|
|
32
|
+
process.argv.slice(2)
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
if (
|
|
36
|
+
options.command === "dev" &&
|
|
37
|
+
process.env.BCP_DEV_CHILD !== "1"
|
|
38
|
+
) {
|
|
39
|
+
await runDevSupervisor(
|
|
40
|
+
options
|
|
41
|
+
);
|
|
42
|
+
} else {
|
|
43
|
+
await runCli(
|
|
44
|
+
options
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function runCli(
|
|
49
|
+
cliOptions: CliOptions
|
|
50
|
+
): Promise<void> {
|
|
51
|
+
const mode =
|
|
52
|
+
resolveEnvironmentMode(
|
|
53
|
+
cliOptions.command
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
if (mode) {
|
|
57
|
+
process.env.NODE_ENV =
|
|
58
|
+
mode;
|
|
59
|
+
|
|
60
|
+
const rootDirectory =
|
|
61
|
+
resolveProjectRoot(
|
|
62
|
+
cliOptions.rootDirectory
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const result =
|
|
66
|
+
loadEnvironment(
|
|
67
|
+
rootDirectory,
|
|
68
|
+
mode
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (
|
|
72
|
+
result.files.length > 0
|
|
73
|
+
) {
|
|
74
|
+
console.log(
|
|
75
|
+
`[BCP Env] ${mode}: ${result.files.join(", ")}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
Object.keys(
|
|
81
|
+
result.publicValues
|
|
82
|
+
).length > 0
|
|
83
|
+
) {
|
|
84
|
+
console.log(
|
|
85
|
+
`[BCP Env] Public variables: ${Object.keys(result.publicValues).sort().join(", ")}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/*
|
|
90
|
+
* A standalone start uses the configuration frozen at build time.
|
|
91
|
+
* Runtime BCP_* environment variables and CLI server overrides stay
|
|
92
|
+
* available to server.mjs, but source bcp.config.* must not replace
|
|
93
|
+
* build-dependent settings after the artifact has been created.
|
|
94
|
+
*/
|
|
95
|
+
if (
|
|
96
|
+
cliOptions.command !==
|
|
97
|
+
"start"
|
|
98
|
+
) {
|
|
99
|
+
const resolved =
|
|
100
|
+
await resolveBcpConfig(
|
|
101
|
+
rootDirectory,
|
|
102
|
+
{
|
|
103
|
+
port:
|
|
104
|
+
cliOptions.port,
|
|
105
|
+
hostname:
|
|
106
|
+
cliOptions.hostname,
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
applyResolvedBcpConfig(
|
|
111
|
+
resolved.config
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
resolved.file
|
|
116
|
+
) {
|
|
117
|
+
console.log(
|
|
118
|
+
`[BCP Config] Loaded: ${path.basename(resolved.file)}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log(
|
|
123
|
+
`[BCP Config] Server: ${resolved.config.server.hostname}:${resolved.config.server.port}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await import(
|
|
129
|
+
"./index.js"
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function runDevSupervisor(
|
|
134
|
+
cliOptions: CliOptions
|
|
135
|
+
): Promise<void> {
|
|
136
|
+
const rootDirectory =
|
|
137
|
+
resolveProjectRoot(
|
|
138
|
+
cliOptions.rootDirectory
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const envFiles =
|
|
142
|
+
getEnvironmentFileNames(
|
|
143
|
+
"development"
|
|
144
|
+
).map(
|
|
145
|
+
(fileName) =>
|
|
146
|
+
path.join(
|
|
147
|
+
rootDirectory,
|
|
148
|
+
fileName
|
|
149
|
+
)
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const configFiles =
|
|
153
|
+
getConfigFileNames()
|
|
154
|
+
.map(
|
|
155
|
+
(fileName) =>
|
|
156
|
+
path.join(
|
|
157
|
+
rootDirectory,
|
|
158
|
+
fileName
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const watchedFiles = [
|
|
163
|
+
...envFiles,
|
|
164
|
+
...configFiles,
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
const bootstrapFile =
|
|
168
|
+
fileURLToPath(
|
|
169
|
+
import.meta.url
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const tsxImport =
|
|
173
|
+
import.meta.resolve(
|
|
174
|
+
"tsx"
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
let child:
|
|
178
|
+
ChildProcess | null =
|
|
179
|
+
null;
|
|
180
|
+
|
|
181
|
+
let stopping =
|
|
182
|
+
false;
|
|
183
|
+
|
|
184
|
+
let restarting =
|
|
185
|
+
false;
|
|
186
|
+
|
|
187
|
+
let restartQueued =
|
|
188
|
+
false;
|
|
189
|
+
|
|
190
|
+
let restartTimer:
|
|
191
|
+
NodeJS.Timeout | null =
|
|
192
|
+
null;
|
|
193
|
+
|
|
194
|
+
let restartGeneration =
|
|
195
|
+
0;
|
|
196
|
+
|
|
197
|
+
let resolveSupervisor:
|
|
198
|
+
(() => void) | null =
|
|
199
|
+
null;
|
|
200
|
+
|
|
201
|
+
const supervisorDone =
|
|
202
|
+
new Promise<void>(
|
|
203
|
+
(resolve) => {
|
|
204
|
+
resolveSupervisor =
|
|
205
|
+
resolve;
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const watcher =
|
|
210
|
+
chokidar.watch(
|
|
211
|
+
watchedFiles,
|
|
212
|
+
{
|
|
213
|
+
persistent: true,
|
|
214
|
+
ignoreInitial: true,
|
|
215
|
+
atomic: true,
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
function startChild(
|
|
220
|
+
configRestart: boolean
|
|
221
|
+
): void {
|
|
222
|
+
const restartToken =
|
|
223
|
+
configRestart
|
|
224
|
+
? `${Date.now()}-${++restartGeneration}`
|
|
225
|
+
: "0";
|
|
226
|
+
|
|
227
|
+
child =
|
|
228
|
+
spawn(
|
|
229
|
+
process.execPath,
|
|
230
|
+
[
|
|
231
|
+
"--import",
|
|
232
|
+
tsxImport,
|
|
233
|
+
bootstrapFile,
|
|
234
|
+
...process.argv.slice(2),
|
|
235
|
+
],
|
|
236
|
+
{
|
|
237
|
+
cwd:
|
|
238
|
+
process.cwd(),
|
|
239
|
+
stdio:
|
|
240
|
+
"inherit",
|
|
241
|
+
env: {
|
|
242
|
+
...process.env,
|
|
243
|
+
BCP_DEV_CHILD:
|
|
244
|
+
"1",
|
|
245
|
+
BCP_DEV_ENV_RESTART:
|
|
246
|
+
restartToken,
|
|
247
|
+
},
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
child.once(
|
|
252
|
+
"exit",
|
|
253
|
+
(
|
|
254
|
+
code,
|
|
255
|
+
signal
|
|
256
|
+
) => {
|
|
257
|
+
child =
|
|
258
|
+
null;
|
|
259
|
+
|
|
260
|
+
if (
|
|
261
|
+
stopping ||
|
|
262
|
+
restarting
|
|
263
|
+
) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (signal) {
|
|
268
|
+
console.error(
|
|
269
|
+
`[BCP Dev] Worker stopped by ${signal}.`
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
void shutdown(
|
|
274
|
+
code ?? 1
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async function stopChild(): Promise<void> {
|
|
281
|
+
const current =
|
|
282
|
+
child;
|
|
283
|
+
|
|
284
|
+
if (
|
|
285
|
+
!current ||
|
|
286
|
+
current.exitCode !== null ||
|
|
287
|
+
current.signalCode !== null
|
|
288
|
+
) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
await new Promise<void>(
|
|
293
|
+
(resolve) => {
|
|
294
|
+
let finished =
|
|
295
|
+
false;
|
|
296
|
+
|
|
297
|
+
const finish =
|
|
298
|
+
() => {
|
|
299
|
+
if (finished) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
finished =
|
|
304
|
+
true;
|
|
305
|
+
resolve();
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
current.once(
|
|
309
|
+
"exit",
|
|
310
|
+
finish
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
current.kill(
|
|
314
|
+
"SIGTERM"
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const forceTimer =
|
|
318
|
+
setTimeout(
|
|
319
|
+
() => {
|
|
320
|
+
if (
|
|
321
|
+
current.exitCode === null &&
|
|
322
|
+
current.signalCode === null
|
|
323
|
+
) {
|
|
324
|
+
current.kill(
|
|
325
|
+
"SIGKILL"
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
3000
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
forceTimer.unref();
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
async function restartChild(
|
|
338
|
+
changedPath: string
|
|
339
|
+
): Promise<void> {
|
|
340
|
+
if (stopping) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (restarting) {
|
|
345
|
+
restartQueued =
|
|
346
|
+
true;
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
restarting =
|
|
351
|
+
true;
|
|
352
|
+
|
|
353
|
+
try {
|
|
354
|
+
const fileName =
|
|
355
|
+
path.basename(
|
|
356
|
+
changedPath
|
|
357
|
+
);
|
|
358
|
+
const source =
|
|
359
|
+
fileName.startsWith(
|
|
360
|
+
"bcp.config."
|
|
361
|
+
)
|
|
362
|
+
? "Config"
|
|
363
|
+
: "Env";
|
|
364
|
+
|
|
365
|
+
console.log("");
|
|
366
|
+
console.log(
|
|
367
|
+
`[BCP ${source}] ${fileName} changed; restarting dev worker...`
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
await stopChild();
|
|
371
|
+
|
|
372
|
+
if (!stopping) {
|
|
373
|
+
startChild(
|
|
374
|
+
true
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
} finally {
|
|
378
|
+
restarting =
|
|
379
|
+
false;
|
|
380
|
+
|
|
381
|
+
if (
|
|
382
|
+
restartQueued &&
|
|
383
|
+
!stopping
|
|
384
|
+
) {
|
|
385
|
+
restartQueued =
|
|
386
|
+
false;
|
|
387
|
+
|
|
388
|
+
await restartChild(
|
|
389
|
+
changedPath
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function scheduleRestart(
|
|
396
|
+
changedPath: string
|
|
397
|
+
): void {
|
|
398
|
+
if (restartTimer) {
|
|
399
|
+
clearTimeout(
|
|
400
|
+
restartTimer
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
restartTimer =
|
|
405
|
+
setTimeout(
|
|
406
|
+
() => {
|
|
407
|
+
restartTimer =
|
|
408
|
+
null;
|
|
409
|
+
|
|
410
|
+
void restartChild(
|
|
411
|
+
changedPath
|
|
412
|
+
);
|
|
413
|
+
},
|
|
414
|
+
120
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
watcher.on(
|
|
419
|
+
"add",
|
|
420
|
+
scheduleRestart
|
|
421
|
+
);
|
|
422
|
+
watcher.on(
|
|
423
|
+
"change",
|
|
424
|
+
scheduleRestart
|
|
425
|
+
);
|
|
426
|
+
watcher.on(
|
|
427
|
+
"unlink",
|
|
428
|
+
scheduleRestart
|
|
429
|
+
);
|
|
430
|
+
watcher.on(
|
|
431
|
+
"error",
|
|
432
|
+
(error) => {
|
|
433
|
+
console.error(
|
|
434
|
+
"[BCP Dev] Configuration watcher error:",
|
|
435
|
+
error
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
async function shutdown(
|
|
441
|
+
exitCode = 0
|
|
442
|
+
): Promise<void> {
|
|
443
|
+
if (stopping) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
stopping =
|
|
448
|
+
true;
|
|
449
|
+
|
|
450
|
+
if (restartTimer) {
|
|
451
|
+
clearTimeout(
|
|
452
|
+
restartTimer
|
|
453
|
+
);
|
|
454
|
+
restartTimer =
|
|
455
|
+
null;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
await watcher.close();
|
|
459
|
+
await stopChild();
|
|
460
|
+
|
|
461
|
+
process.exitCode =
|
|
462
|
+
exitCode;
|
|
463
|
+
|
|
464
|
+
resolveSupervisor?.();
|
|
465
|
+
resolveSupervisor =
|
|
466
|
+
null;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
process.once(
|
|
470
|
+
"SIGINT",
|
|
471
|
+
() => {
|
|
472
|
+
void shutdown(0);
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
process.once(
|
|
477
|
+
"SIGTERM",
|
|
478
|
+
() => {
|
|
479
|
+
void shutdown(0);
|
|
480
|
+
}
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
console.log(
|
|
484
|
+
`[BCP Env] Watching: ${getEnvironmentFileNames("development").join(", ")}`
|
|
485
|
+
);
|
|
486
|
+
console.log(
|
|
487
|
+
`[BCP Config] Watching: ${getConfigFileNames().join(", ")}`
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
startChild(
|
|
491
|
+
false
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
await supervisorDone;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function resolveEnvironmentMode(
|
|
498
|
+
command: string
|
|
499
|
+
): EnvironmentMode | null {
|
|
500
|
+
if (
|
|
501
|
+
command === "dev"
|
|
502
|
+
) {
|
|
503
|
+
return "development";
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (
|
|
507
|
+
command === "build" ||
|
|
508
|
+
command === "start"
|
|
509
|
+
) {
|
|
510
|
+
return "production";
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return null;
|
|
514
|
+
}
|