@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,504 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
pathToFileURL,
|
|
5
|
+
} from "node:url";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
readResolvedBcpConfig,
|
|
9
|
+
} from "../../config/src/index.js";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
assertNoPageApiConflicts,
|
|
13
|
+
scanApiRoutes,
|
|
14
|
+
scanRoutes,
|
|
15
|
+
} from "../../router/src/index.js";
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
parseCliArgs,
|
|
19
|
+
resolveProjectRoot,
|
|
20
|
+
} from "./args.js";
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
getFrameworkVersion,
|
|
24
|
+
} from "./version.js";
|
|
25
|
+
|
|
26
|
+
const FRAMEWORK_VERSION =
|
|
27
|
+
getFrameworkVersion();
|
|
28
|
+
|
|
29
|
+
const cliOptions =
|
|
30
|
+
parseCliArgs(
|
|
31
|
+
process.argv.slice(2)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const frameworkConfig =
|
|
35
|
+
readResolvedBcpConfig();
|
|
36
|
+
|
|
37
|
+
switch (cliOptions.command) {
|
|
38
|
+
case "dev": {
|
|
39
|
+
await runDev();
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
case "build": {
|
|
44
|
+
await runBuild();
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
case "start": {
|
|
49
|
+
await runStart();
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
case "routes": {
|
|
54
|
+
runRoutes();
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
case "help": {
|
|
59
|
+
printHelp();
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
case "version": {
|
|
64
|
+
console.log(
|
|
65
|
+
`BCP Framework v${FRAMEWORK_VERSION}`
|
|
66
|
+
);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function runDev() {
|
|
72
|
+
process.env.NODE_ENV =
|
|
73
|
+
"development";
|
|
74
|
+
|
|
75
|
+
const {
|
|
76
|
+
createMiddlewareDevServer,
|
|
77
|
+
} =
|
|
78
|
+
await import(
|
|
79
|
+
"../../server/src/middleware-dev-server.js"
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const rootDirectory =
|
|
83
|
+
resolveProjectRoot(
|
|
84
|
+
cliOptions.rootDirectory
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
console.log(
|
|
88
|
+
`[BCP CLI] Project: ${rootDirectory}`
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const server =
|
|
92
|
+
createMiddlewareDevServer({
|
|
93
|
+
port:
|
|
94
|
+
frameworkConfig.server.port,
|
|
95
|
+
hostname:
|
|
96
|
+
frameworkConfig.server.hostname,
|
|
97
|
+
rootDirectory,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
installShutdownHandlers(
|
|
101
|
+
server
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
await server.start();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function runBuild() {
|
|
108
|
+
process.env.NODE_ENV =
|
|
109
|
+
"production";
|
|
110
|
+
|
|
111
|
+
const [
|
|
112
|
+
{
|
|
113
|
+
buildProductionClient,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
buildProductionServer,
|
|
117
|
+
},
|
|
118
|
+
] =
|
|
119
|
+
await Promise.all([
|
|
120
|
+
import(
|
|
121
|
+
"../../bundler/src/partial-hydration.js"
|
|
122
|
+
),
|
|
123
|
+
import(
|
|
124
|
+
"../../bundler/src/server-production-middleware.js"
|
|
125
|
+
),
|
|
126
|
+
]);
|
|
127
|
+
|
|
128
|
+
const rootDirectory =
|
|
129
|
+
resolveProjectRoot(
|
|
130
|
+
cliOptions.rootDirectory
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const appDirectory =
|
|
134
|
+
path.join(
|
|
135
|
+
rootDirectory,
|
|
136
|
+
"app"
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const pageRoutes =
|
|
140
|
+
scanRoutes(
|
|
141
|
+
appDirectory
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const apiRoutes =
|
|
145
|
+
scanApiRoutes(
|
|
146
|
+
appDirectory
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
assertNoPageApiConflicts(
|
|
150
|
+
pageRoutes,
|
|
151
|
+
apiRoutes
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
console.log("");
|
|
155
|
+
console.log(
|
|
156
|
+
`[BCP Build] Project: ${rootDirectory}`
|
|
157
|
+
);
|
|
158
|
+
console.log(
|
|
159
|
+
`[BCP Build] Pages: ${pageRoutes.length} | API: ${apiRoutes.length}`
|
|
160
|
+
);
|
|
161
|
+
console.log(
|
|
162
|
+
`[BCP Build] Config: minify=${frameworkConfig.build.minify} sourceMaps=${frameworkConfig.build.sourceMaps} compression=${frameworkConfig.compression}`
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const startedAt =
|
|
166
|
+
performance.now();
|
|
167
|
+
|
|
168
|
+
const manifest =
|
|
169
|
+
await buildProductionClient(
|
|
170
|
+
pageRoutes,
|
|
171
|
+
rootDirectory
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const serverBuild =
|
|
175
|
+
await buildProductionServer(
|
|
176
|
+
pageRoutes,
|
|
177
|
+
apiRoutes,
|
|
178
|
+
rootDirectory,
|
|
179
|
+
manifest
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const duration =
|
|
183
|
+
performance.now() -
|
|
184
|
+
startedAt;
|
|
185
|
+
|
|
186
|
+
console.log("");
|
|
187
|
+
|
|
188
|
+
for (
|
|
189
|
+
const [
|
|
190
|
+
pathname,
|
|
191
|
+
routeAsset,
|
|
192
|
+
]
|
|
193
|
+
of Object.entries(
|
|
194
|
+
manifest.routes
|
|
195
|
+
)
|
|
196
|
+
) {
|
|
197
|
+
console.log(
|
|
198
|
+
` ${pathname} -> ${routeAsset.entry}`
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
console.log(
|
|
202
|
+
` imports: ${routeAsset.imports.length} | raw ${formatBytes(routeAsset.size.raw)} | gzip ${formatBytes(routeAsset.size.gzip)} | br ${formatBytes(routeAsset.size.brotli)}`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const totalSize =
|
|
207
|
+
manifest.assets.reduce(
|
|
208
|
+
(
|
|
209
|
+
total,
|
|
210
|
+
asset
|
|
211
|
+
) => ({
|
|
212
|
+
raw:
|
|
213
|
+
total.raw +
|
|
214
|
+
asset.size.raw,
|
|
215
|
+
gzip:
|
|
216
|
+
total.gzip +
|
|
217
|
+
asset.size.gzip,
|
|
218
|
+
brotli:
|
|
219
|
+
total.brotli +
|
|
220
|
+
asset.size.brotli,
|
|
221
|
+
}),
|
|
222
|
+
{
|
|
223
|
+
raw: 0,
|
|
224
|
+
gzip: 0,
|
|
225
|
+
brotli: 0,
|
|
226
|
+
}
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
console.log("");
|
|
230
|
+
console.log(
|
|
231
|
+
`[BCP Build] Client assets: raw ${formatBytes(totalSize.raw)} | gzip ${formatBytes(totalSize.gzip)} | br ${formatBytes(totalSize.brotli)}`
|
|
232
|
+
);
|
|
233
|
+
console.log(
|
|
234
|
+
`[BCP Build] Server bundle: ${formatBytes(serverBuild.size)}`
|
|
235
|
+
);
|
|
236
|
+
console.log(
|
|
237
|
+
`[BCP Build] Server: ${serverBuild.serverFile}`
|
|
238
|
+
);
|
|
239
|
+
console.log(
|
|
240
|
+
`[BCP Build] Build ID: ${manifest.buildId}`
|
|
241
|
+
);
|
|
242
|
+
console.log(
|
|
243
|
+
`[BCP Build] Assets: ${manifest.assets.length}`
|
|
244
|
+
);
|
|
245
|
+
console.log(
|
|
246
|
+
`[BCP Build] Completed in ${duration.toFixed(2)}ms`
|
|
247
|
+
);
|
|
248
|
+
console.log("");
|
|
249
|
+
console.log(
|
|
250
|
+
"[BCP Build] Standalone run:"
|
|
251
|
+
);
|
|
252
|
+
console.log(
|
|
253
|
+
` node ${serverBuild.serverFile}`
|
|
254
|
+
);
|
|
255
|
+
console.log("");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async function runStart() {
|
|
259
|
+
process.env.NODE_ENV =
|
|
260
|
+
"production";
|
|
261
|
+
|
|
262
|
+
const rootDirectory =
|
|
263
|
+
resolveProjectRoot(
|
|
264
|
+
cliOptions.rootDirectory
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const serverFile =
|
|
268
|
+
path.join(
|
|
269
|
+
rootDirectory,
|
|
270
|
+
".bcp-framework",
|
|
271
|
+
"build",
|
|
272
|
+
"server",
|
|
273
|
+
"server.mjs"
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
if (
|
|
277
|
+
!fs.existsSync(
|
|
278
|
+
serverFile
|
|
279
|
+
)
|
|
280
|
+
) {
|
|
281
|
+
throw new Error(
|
|
282
|
+
"BCP Framework: standalone production build was not found. Run `bcp build` before `bcp start`."
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/*
|
|
287
|
+
* Keep build-time configuration frozen in server.mjs/config.json.
|
|
288
|
+
* Only explicit runtime environment values and CLI options should
|
|
289
|
+
* override the standalone artifact after it has been built.
|
|
290
|
+
*/
|
|
291
|
+
if (
|
|
292
|
+
cliOptions.port !==
|
|
293
|
+
undefined
|
|
294
|
+
) {
|
|
295
|
+
process.env.BCP_PORT =
|
|
296
|
+
String(
|
|
297
|
+
cliOptions.port
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (
|
|
302
|
+
cliOptions.hostname !==
|
|
303
|
+
undefined
|
|
304
|
+
) {
|
|
305
|
+
process.env.BCP_HOSTNAME =
|
|
306
|
+
cliOptions.hostname;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
console.log(
|
|
310
|
+
`[BCP CLI] Starting standalone build: ${serverFile}`
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
if (
|
|
314
|
+
cliOptions.hostname !== undefined ||
|
|
315
|
+
cliOptions.port !== undefined
|
|
316
|
+
) {
|
|
317
|
+
console.log(
|
|
318
|
+
`[BCP CLI] Runtime server override: ${cliOptions.hostname ?? process.env.BCP_HOSTNAME ?? "(frozen hostname)"}:${cliOptions.port ?? process.env.BCP_PORT ?? "(frozen port)"}`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
await import(
|
|
323
|
+
pathToFileURL(
|
|
324
|
+
serverFile
|
|
325
|
+
).href
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function installShutdownHandlers(
|
|
330
|
+
server: {
|
|
331
|
+
stop(): Promise<void>;
|
|
332
|
+
}
|
|
333
|
+
) {
|
|
334
|
+
process.once(
|
|
335
|
+
"SIGINT",
|
|
336
|
+
async () => {
|
|
337
|
+
console.log("");
|
|
338
|
+
console.log(
|
|
339
|
+
"Stopping BCP Framework..."
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
await server.stop();
|
|
343
|
+
|
|
344
|
+
process.exit(0);
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
process.once(
|
|
349
|
+
"SIGTERM",
|
|
350
|
+
async () => {
|
|
351
|
+
await server.stop();
|
|
352
|
+
|
|
353
|
+
process.exit(0);
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function runRoutes() {
|
|
359
|
+
const rootDirectory =
|
|
360
|
+
resolveProjectRoot(
|
|
361
|
+
cliOptions.rootDirectory
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
const appDirectory =
|
|
365
|
+
path.join(
|
|
366
|
+
rootDirectory,
|
|
367
|
+
"app"
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const pageRoutes =
|
|
371
|
+
scanRoutes(
|
|
372
|
+
appDirectory
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
const apiRoutes =
|
|
376
|
+
scanApiRoutes(
|
|
377
|
+
appDirectory
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
assertNoPageApiConflicts(
|
|
381
|
+
pageRoutes,
|
|
382
|
+
apiRoutes
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
console.log("");
|
|
386
|
+
console.log(
|
|
387
|
+
`BCP Framework Routes: ${rootDirectory}`
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
console.log("");
|
|
391
|
+
console.log(
|
|
392
|
+
"Pages:"
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
if (
|
|
396
|
+
pageRoutes.length === 0
|
|
397
|
+
) {
|
|
398
|
+
console.log(
|
|
399
|
+
" (none)"
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
for (
|
|
404
|
+
const route of pageRoutes
|
|
405
|
+
) {
|
|
406
|
+
console.log(
|
|
407
|
+
` ${route.pathname}`
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
console.log(
|
|
411
|
+
` ${route.filePath}`
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
console.log("");
|
|
416
|
+
console.log(
|
|
417
|
+
"API:"
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
if (
|
|
421
|
+
apiRoutes.length === 0
|
|
422
|
+
) {
|
|
423
|
+
console.log(
|
|
424
|
+
" (none)"
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
for (
|
|
429
|
+
const route of apiRoutes
|
|
430
|
+
) {
|
|
431
|
+
console.log(
|
|
432
|
+
` ${route.pathname}`
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
console.log(
|
|
436
|
+
` ${route.filePath}`
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
console.log("");
|
|
441
|
+
console.log(
|
|
442
|
+
`Total: ${pageRoutes.length} page(s), ${apiRoutes.length} API route(s)`
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function formatBytes(
|
|
447
|
+
value: number
|
|
448
|
+
): string {
|
|
449
|
+
if (
|
|
450
|
+
value < 1024
|
|
451
|
+
) {
|
|
452
|
+
return `${value} B`;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (
|
|
456
|
+
value < 1024 * 1024
|
|
457
|
+
) {
|
|
458
|
+
return `${(
|
|
459
|
+
value / 1024
|
|
460
|
+
).toFixed(1)} KiB`;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return `${(
|
|
464
|
+
value /
|
|
465
|
+
(1024 * 1024)
|
|
466
|
+
).toFixed(2)} MiB`;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function printHelp() {
|
|
470
|
+
console.log(`
|
|
471
|
+
BCP Framework v${FRAMEWORK_VERSION}
|
|
472
|
+
|
|
473
|
+
Usage:
|
|
474
|
+
bcp <command> [options]
|
|
475
|
+
|
|
476
|
+
Commands:
|
|
477
|
+
dev Start the development server
|
|
478
|
+
build Create optimized client assets and standalone server.mjs
|
|
479
|
+
start Start the standalone production build
|
|
480
|
+
routes Print discovered page and API routes
|
|
481
|
+
help Show this help message
|
|
482
|
+
version Show framework version
|
|
483
|
+
|
|
484
|
+
Options:
|
|
485
|
+
--root <path> Project root directory
|
|
486
|
+
--port <number> Override configured HTTP port
|
|
487
|
+
--hostname <host> Override configured HTTP hostname
|
|
488
|
+
--host <host> Alias for --hostname
|
|
489
|
+
-h, --help Show help
|
|
490
|
+
-v, --version Show version
|
|
491
|
+
|
|
492
|
+
Config precedence:
|
|
493
|
+
dev/build: CLI > BCP_* environment > bcp.config.ts > defaults
|
|
494
|
+
start: CLI > runtime BCP_* environment > frozen build config
|
|
495
|
+
|
|
496
|
+
Examples:
|
|
497
|
+
bcp dev
|
|
498
|
+
bcp dev --port 4000
|
|
499
|
+
bcp build
|
|
500
|
+
bcp start
|
|
501
|
+
bcp start --port 4000
|
|
502
|
+
bcp routes
|
|
503
|
+
`);
|
|
504
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
fileURLToPath,
|
|
5
|
+
} from "node:url";
|
|
6
|
+
|
|
7
|
+
export function getFrameworkVersion(): string {
|
|
8
|
+
const currentDirectory =
|
|
9
|
+
path.dirname(
|
|
10
|
+
fileURLToPath(
|
|
11
|
+
import.meta.url
|
|
12
|
+
)
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const packageFile =
|
|
16
|
+
path.resolve(
|
|
17
|
+
currentDirectory,
|
|
18
|
+
"../../../package.json"
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const packageJson =
|
|
23
|
+
JSON.parse(
|
|
24
|
+
fs.readFileSync(
|
|
25
|
+
packageFile,
|
|
26
|
+
"utf8"
|
|
27
|
+
)
|
|
28
|
+
) as {
|
|
29
|
+
version?: unknown;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
typeof packageJson.version ===
|
|
34
|
+
"string" &&
|
|
35
|
+
packageJson.version.trim() !==
|
|
36
|
+
""
|
|
37
|
+
) {
|
|
38
|
+
return packageJson.version;
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
// Fall through to a non-release development marker.
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return "0.0.0-dev";
|
|
45
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export {
|
|
2
|
+
applyResolvedBcpConfig,
|
|
3
|
+
defaultBcpConfig,
|
|
4
|
+
defineConfig,
|
|
5
|
+
getConfigFileNames,
|
|
6
|
+
loadBcpConfig,
|
|
7
|
+
readResolvedBcpConfig,
|
|
8
|
+
resolveBcpConfig,
|
|
9
|
+
type BcpBuildConfig,
|
|
10
|
+
type BcpCacheConfig,
|
|
11
|
+
type BcpConfig,
|
|
12
|
+
type BcpExperimentalConfig,
|
|
13
|
+
type BcpSecurityConfig,
|
|
14
|
+
type BcpServerConfig,
|
|
15
|
+
type LoadedBcpConfig,
|
|
16
|
+
type ResolveBcpConfigOverrides,
|
|
17
|
+
type ResolvedBcpConfig,
|
|
18
|
+
} from "../../config/src/index.js";
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Component,
|
|
3
|
+
createElement,
|
|
4
|
+
type ComponentType,
|
|
5
|
+
type ErrorInfo,
|
|
6
|
+
type ReactNode,
|
|
7
|
+
} from "react";
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
isNotFoundError,
|
|
11
|
+
} from "./not-found.js";
|
|
12
|
+
|
|
13
|
+
export interface BcpErrorComponentProps {
|
|
14
|
+
error: Error;
|
|
15
|
+
reset: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface BcpRouteErrorBoundaryProps {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
ErrorComponent?:
|
|
21
|
+
ComponentType<
|
|
22
|
+
BcpErrorComponentProps
|
|
23
|
+
> | null;
|
|
24
|
+
NotFoundComponent?:
|
|
25
|
+
ComponentType | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface BcpRouteErrorBoundaryState {
|
|
29
|
+
error: unknown | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class BcpRouteErrorBoundary
|
|
33
|
+
extends Component<
|
|
34
|
+
BcpRouteErrorBoundaryProps,
|
|
35
|
+
BcpRouteErrorBoundaryState
|
|
36
|
+
> {
|
|
37
|
+
state:
|
|
38
|
+
BcpRouteErrorBoundaryState = {
|
|
39
|
+
error: null,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
static getDerivedStateFromError(
|
|
43
|
+
error: unknown
|
|
44
|
+
):
|
|
45
|
+
BcpRouteErrorBoundaryState {
|
|
46
|
+
return {
|
|
47
|
+
error,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
componentDidCatch(
|
|
52
|
+
error: Error,
|
|
53
|
+
info: ErrorInfo
|
|
54
|
+
): void {
|
|
55
|
+
console.error(
|
|
56
|
+
"[BCP Route Error]",
|
|
57
|
+
error,
|
|
58
|
+
info.componentStack
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private reset = (): void => {
|
|
63
|
+
this.setState({
|
|
64
|
+
error: null,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
render(): ReactNode {
|
|
69
|
+
const {
|
|
70
|
+
error,
|
|
71
|
+
} = this.state;
|
|
72
|
+
|
|
73
|
+
if (error === null) {
|
|
74
|
+
return this.props.children;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
isNotFoundError(
|
|
79
|
+
error
|
|
80
|
+
)
|
|
81
|
+
) {
|
|
82
|
+
const NotFoundComponent =
|
|
83
|
+
this.props
|
|
84
|
+
.NotFoundComponent;
|
|
85
|
+
|
|
86
|
+
if (NotFoundComponent) {
|
|
87
|
+
return createElement(
|
|
88
|
+
NotFoundComponent
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return createElement(
|
|
93
|
+
"main",
|
|
94
|
+
null,
|
|
95
|
+
createElement(
|
|
96
|
+
"h1",
|
|
97
|
+
null,
|
|
98
|
+
"404"
|
|
99
|
+
),
|
|
100
|
+
createElement(
|
|
101
|
+
"p",
|
|
102
|
+
null,
|
|
103
|
+
"Page Not Found"
|
|
104
|
+
)
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const ErrorComponent =
|
|
109
|
+
this.props.ErrorComponent;
|
|
110
|
+
|
|
111
|
+
const normalizedError =
|
|
112
|
+
error instanceof Error
|
|
113
|
+
? error
|
|
114
|
+
: new Error(
|
|
115
|
+
"An unexpected client error occurred."
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
if (ErrorComponent) {
|
|
119
|
+
return createElement(
|
|
120
|
+
ErrorComponent,
|
|
121
|
+
{
|
|
122
|
+
error:
|
|
123
|
+
normalizedError,
|
|
124
|
+
reset:
|
|
125
|
+
this.reset,
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return createElement(
|
|
131
|
+
"main",
|
|
132
|
+
null,
|
|
133
|
+
createElement(
|
|
134
|
+
"h1",
|
|
135
|
+
null,
|
|
136
|
+
"Something went wrong"
|
|
137
|
+
),
|
|
138
|
+
createElement(
|
|
139
|
+
"button",
|
|
140
|
+
{
|
|
141
|
+
type: "button",
|
|
142
|
+
onClick:
|
|
143
|
+
this.reset,
|
|
144
|
+
},
|
|
145
|
+
"Try again"
|
|
146
|
+
)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|