@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,447 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
fileURLToPath,
|
|
5
|
+
} from "node:url";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
build,
|
|
9
|
+
} from "esbuild";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
createServerEnvironmentDefines,
|
|
13
|
+
} from "../../env/src/index.js";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
findProjectMiddlewareFile,
|
|
17
|
+
} from "../../server/src/middleware-loader.js";
|
|
18
|
+
|
|
19
|
+
import type {
|
|
20
|
+
ApiRoute,
|
|
21
|
+
Route,
|
|
22
|
+
} from "../../router/src/index.js";
|
|
23
|
+
|
|
24
|
+
import type {
|
|
25
|
+
RevalidateValue,
|
|
26
|
+
} from "../../cache/src/index.js";
|
|
27
|
+
|
|
28
|
+
import type {
|
|
29
|
+
PartialHydrationBuildManifest,
|
|
30
|
+
} from "./partial-hydration.js";
|
|
31
|
+
|
|
32
|
+
import {
|
|
33
|
+
buildProductionServer as buildBaseProductionServer,
|
|
34
|
+
type ProductionServerBuildResult,
|
|
35
|
+
} from "./server-production.js";
|
|
36
|
+
|
|
37
|
+
interface CacheManifestRoute {
|
|
38
|
+
pathname: string;
|
|
39
|
+
segments: Route["segments"];
|
|
40
|
+
revalidate: RevalidateValue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface CacheManifest {
|
|
44
|
+
version: 1;
|
|
45
|
+
pages: CacheManifestRoute[];
|
|
46
|
+
apiRoutes: CacheManifestRoute[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function buildProductionServer(
|
|
50
|
+
pageRoutes: Route[],
|
|
51
|
+
apiRoutes: ApiRoute[],
|
|
52
|
+
rootDirectory: string,
|
|
53
|
+
clientManifest: PartialHydrationBuildManifest
|
|
54
|
+
): Promise<ProductionServerBuildResult> {
|
|
55
|
+
const baseResult =
|
|
56
|
+
await buildBaseProductionServer(
|
|
57
|
+
pageRoutes,
|
|
58
|
+
apiRoutes,
|
|
59
|
+
rootDirectory,
|
|
60
|
+
clientManifest
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
await bundleServerCacheRuntime(
|
|
64
|
+
baseResult.serverFile,
|
|
65
|
+
rootDirectory
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const serverDirectory =
|
|
69
|
+
path.dirname(
|
|
70
|
+
baseResult.serverFile
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
writeCacheManifest(
|
|
74
|
+
pageRoutes,
|
|
75
|
+
apiRoutes,
|
|
76
|
+
serverDirectory
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
await buildProductionMiddleware(
|
|
80
|
+
rootDirectory,
|
|
81
|
+
serverDirectory
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
...baseResult,
|
|
86
|
+
size:
|
|
87
|
+
fs.statSync(
|
|
88
|
+
baseResult.serverFile
|
|
89
|
+
).size,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function bundleServerCacheRuntime(
|
|
94
|
+
serverFile: string,
|
|
95
|
+
rootDirectory: string
|
|
96
|
+
): Promise<void> {
|
|
97
|
+
const temporaryFile =
|
|
98
|
+
`${serverFile}.cache-runtime.mjs`;
|
|
99
|
+
|
|
100
|
+
const sourceMaps =
|
|
101
|
+
process.env
|
|
102
|
+
.BCP_BUILD_SOURCE_MAPS ===
|
|
103
|
+
"1";
|
|
104
|
+
|
|
105
|
+
const frameworkDirectory =
|
|
106
|
+
path.dirname(
|
|
107
|
+
fileURLToPath(
|
|
108
|
+
import.meta.url
|
|
109
|
+
)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const frameworkCacheEntry =
|
|
113
|
+
path.resolve(
|
|
114
|
+
frameworkDirectory,
|
|
115
|
+
"../../cache/src/index.ts"
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
await build({
|
|
120
|
+
absWorkingDir:
|
|
121
|
+
rootDirectory,
|
|
122
|
+
entryPoints: [
|
|
123
|
+
serverFile,
|
|
124
|
+
],
|
|
125
|
+
outfile:
|
|
126
|
+
temporaryFile,
|
|
127
|
+
bundle:
|
|
128
|
+
true,
|
|
129
|
+
platform:
|
|
130
|
+
"node",
|
|
131
|
+
format:
|
|
132
|
+
"esm",
|
|
133
|
+
target: [
|
|
134
|
+
"node24",
|
|
135
|
+
],
|
|
136
|
+
minify:
|
|
137
|
+
process.env
|
|
138
|
+
.BCP_BUILD_MINIFY !==
|
|
139
|
+
"0",
|
|
140
|
+
sourcemap:
|
|
141
|
+
sourceMaps
|
|
142
|
+
? "inline"
|
|
143
|
+
: false,
|
|
144
|
+
treeShaking:
|
|
145
|
+
true,
|
|
146
|
+
packages:
|
|
147
|
+
"external",
|
|
148
|
+
plugins: [
|
|
149
|
+
{
|
|
150
|
+
name:
|
|
151
|
+
"bcp-cache-runtime",
|
|
152
|
+
setup(buildApi) {
|
|
153
|
+
buildApi.onResolve(
|
|
154
|
+
{
|
|
155
|
+
filter:
|
|
156
|
+
/^bcp\/cache$/,
|
|
157
|
+
},
|
|
158
|
+
() => ({
|
|
159
|
+
path:
|
|
160
|
+
frameworkCacheEntry,
|
|
161
|
+
})
|
|
162
|
+
);
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
legalComments:
|
|
167
|
+
"none",
|
|
168
|
+
logLevel:
|
|
169
|
+
"silent",
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
fs.copyFileSync(
|
|
173
|
+
temporaryFile,
|
|
174
|
+
serverFile
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
/*
|
|
178
|
+
* The base server build may have emitted an external map. The final
|
|
179
|
+
* cache-runtime rebundle uses an inline map so a stale server.mjs.map
|
|
180
|
+
* must not be shipped next to the rewritten bundle.
|
|
181
|
+
*/
|
|
182
|
+
fs.rmSync(
|
|
183
|
+
`${serverFile}.map`,
|
|
184
|
+
{
|
|
185
|
+
force: true,
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
} finally {
|
|
189
|
+
fs.rmSync(
|
|
190
|
+
temporaryFile,
|
|
191
|
+
{
|
|
192
|
+
force: true,
|
|
193
|
+
}
|
|
194
|
+
);
|
|
195
|
+
fs.rmSync(
|
|
196
|
+
`${temporaryFile}.map`,
|
|
197
|
+
{
|
|
198
|
+
force: true,
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function writeCacheManifest(
|
|
205
|
+
pageRoutes: Route[],
|
|
206
|
+
apiRoutes: ApiRoute[],
|
|
207
|
+
serverDirectory: string
|
|
208
|
+
): void {
|
|
209
|
+
const manifest:
|
|
210
|
+
CacheManifest = {
|
|
211
|
+
version: 1,
|
|
212
|
+
pages:
|
|
213
|
+
collectCacheRoutes(
|
|
214
|
+
pageRoutes
|
|
215
|
+
),
|
|
216
|
+
apiRoutes:
|
|
217
|
+
collectCacheRoutes(
|
|
218
|
+
apiRoutes
|
|
219
|
+
),
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const outputFile =
|
|
223
|
+
path.join(
|
|
224
|
+
serverDirectory,
|
|
225
|
+
"cache-manifest.json"
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
fs.writeFileSync(
|
|
229
|
+
outputFile,
|
|
230
|
+
JSON.stringify(
|
|
231
|
+
manifest,
|
|
232
|
+
null,
|
|
233
|
+
2
|
|
234
|
+
),
|
|
235
|
+
"utf8"
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
console.log(
|
|
239
|
+
`[BCP Build] Cache routes: ${manifest.pages.length} page(s), ${manifest.apiRoutes.length} API route(s)`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function collectCacheRoutes<
|
|
244
|
+
T extends Route | ApiRoute
|
|
245
|
+
>(
|
|
246
|
+
routes: T[]
|
|
247
|
+
): CacheManifestRoute[] {
|
|
248
|
+
const result:
|
|
249
|
+
CacheManifestRoute[] = [];
|
|
250
|
+
|
|
251
|
+
for (const route of routes) {
|
|
252
|
+
const revalidate =
|
|
253
|
+
readRouteRevalidate(
|
|
254
|
+
route.filePath
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
if (
|
|
258
|
+
revalidate === undefined ||
|
|
259
|
+
revalidate === 0
|
|
260
|
+
) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
result.push({
|
|
265
|
+
pathname:
|
|
266
|
+
route.pathname,
|
|
267
|
+
segments:
|
|
268
|
+
route.segments,
|
|
269
|
+
revalidate,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function readRouteRevalidate(
|
|
277
|
+
filePath: string
|
|
278
|
+
): RevalidateValue | undefined {
|
|
279
|
+
const source =
|
|
280
|
+
fs.readFileSync(
|
|
281
|
+
filePath,
|
|
282
|
+
"utf8"
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
const declaration =
|
|
286
|
+
/\bexport\s+const\s+revalidate\b/.test(
|
|
287
|
+
source
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (!declaration) {
|
|
291
|
+
return undefined;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const match =
|
|
295
|
+
/\bexport\s+const\s+revalidate\s*(?::[^=;]+)?=\s*(false|(?:\d+(?:\.\d+)?))\s*;?/.exec(
|
|
296
|
+
source
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
if (!match) {
|
|
300
|
+
throw new Error(
|
|
301
|
+
`BCP Framework: revalidate in "${filePath}" must be a literal false or non-negative number.`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (
|
|
306
|
+
match[1] === "false"
|
|
307
|
+
) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const value =
|
|
312
|
+
Number(
|
|
313
|
+
match[1]
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
if (
|
|
317
|
+
!Number.isFinite(value) ||
|
|
318
|
+
value < 0
|
|
319
|
+
) {
|
|
320
|
+
throw new Error(
|
|
321
|
+
`BCP Framework: invalid revalidate value in "${filePath}".`
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return value;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function buildProductionMiddleware(
|
|
329
|
+
rootDirectory: string,
|
|
330
|
+
serverDirectory: string
|
|
331
|
+
): Promise<void> {
|
|
332
|
+
const outputFile =
|
|
333
|
+
path.join(
|
|
334
|
+
serverDirectory,
|
|
335
|
+
"middleware.mjs"
|
|
336
|
+
);
|
|
337
|
+
|
|
338
|
+
fs.rmSync(
|
|
339
|
+
outputFile,
|
|
340
|
+
{
|
|
341
|
+
force: true,
|
|
342
|
+
}
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
const middlewareFile =
|
|
346
|
+
findProjectMiddlewareFile(
|
|
347
|
+
rootDirectory
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
if (!middlewareFile) {
|
|
351
|
+
console.log(
|
|
352
|
+
"[BCP Build] Middleware: none"
|
|
353
|
+
);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const frameworkDirectory =
|
|
358
|
+
path.dirname(
|
|
359
|
+
fileURLToPath(
|
|
360
|
+
import.meta.url
|
|
361
|
+
)
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
const frameworkMiddlewareEntry =
|
|
365
|
+
path.resolve(
|
|
366
|
+
frameworkDirectory,
|
|
367
|
+
"../../server/src/middleware.ts"
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const frameworkCacheEntry =
|
|
371
|
+
path.resolve(
|
|
372
|
+
frameworkDirectory,
|
|
373
|
+
"../../cache/src/index.ts"
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
await build({
|
|
377
|
+
absWorkingDir:
|
|
378
|
+
rootDirectory,
|
|
379
|
+
entryPoints: [
|
|
380
|
+
middlewareFile,
|
|
381
|
+
],
|
|
382
|
+
outfile:
|
|
383
|
+
outputFile,
|
|
384
|
+
bundle:
|
|
385
|
+
true,
|
|
386
|
+
platform:
|
|
387
|
+
"node",
|
|
388
|
+
format:
|
|
389
|
+
"esm",
|
|
390
|
+
target: [
|
|
391
|
+
"node24",
|
|
392
|
+
],
|
|
393
|
+
minify:
|
|
394
|
+
process.env
|
|
395
|
+
.BCP_BUILD_MINIFY !==
|
|
396
|
+
"0",
|
|
397
|
+
sourcemap:
|
|
398
|
+
process.env
|
|
399
|
+
.BCP_BUILD_SOURCE_MAPS ===
|
|
400
|
+
"1",
|
|
401
|
+
treeShaking:
|
|
402
|
+
true,
|
|
403
|
+
packages:
|
|
404
|
+
"external",
|
|
405
|
+
plugins: [
|
|
406
|
+
{
|
|
407
|
+
name:
|
|
408
|
+
"bcp-middleware-runtime",
|
|
409
|
+
setup(buildApi) {
|
|
410
|
+
buildApi.onResolve(
|
|
411
|
+
{
|
|
412
|
+
filter:
|
|
413
|
+
/^bcp\/middleware$/,
|
|
414
|
+
},
|
|
415
|
+
() => ({
|
|
416
|
+
path:
|
|
417
|
+
frameworkMiddlewareEntry,
|
|
418
|
+
})
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
buildApi.onResolve(
|
|
422
|
+
{
|
|
423
|
+
filter:
|
|
424
|
+
/^bcp\/cache$/,
|
|
425
|
+
},
|
|
426
|
+
() => ({
|
|
427
|
+
path:
|
|
428
|
+
frameworkCacheEntry,
|
|
429
|
+
})
|
|
430
|
+
);
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
],
|
|
434
|
+
define:
|
|
435
|
+
createServerEnvironmentDefines(
|
|
436
|
+
"production"
|
|
437
|
+
),
|
|
438
|
+
legalComments:
|
|
439
|
+
"none",
|
|
440
|
+
logLevel:
|
|
441
|
+
"silent",
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
console.log(
|
|
445
|
+
`[BCP Build] Middleware: ${path.relative(rootDirectory, middlewareFile).replace(/\\/g, "/")} -> ${path.relative(rootDirectory, outputFile).replace(/\\/g, "/")}`
|
|
446
|
+
);
|
|
447
|
+
}
|