@reckona/mreact-router 0.0.175 → 0.0.177
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/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +5 -49
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/build.d.ts +1 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +90 -0
- package/dist/build.js.map +1 -1
- package/dist/built-assets.d.ts +11 -0
- package/dist/built-assets.d.ts.map +1 -0
- package/dist/built-assets.js +130 -0
- package/dist/built-assets.js.map +1 -0
- package/dist/built-runtime.d.ts +53 -0
- package/dist/built-runtime.d.ts.map +1 -0
- package/dist/built-runtime.js +178 -0
- package/dist/built-runtime.js.map +1 -0
- package/dist/built-server-module-artifacts.d.ts +19 -0
- package/dist/built-server-module-artifacts.d.ts.map +1 -0
- package/dist/built-server-module-artifacts.js +217 -0
- package/dist/built-server-module-artifacts.js.map +1 -0
- package/dist/client-manifest-assets.d.ts +16 -0
- package/dist/client-manifest-assets.d.ts.map +1 -0
- package/dist/client-manifest-assets.js +60 -0
- package/dist/client-manifest-assets.js.map +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +79 -13
- package/dist/client.js.map +1 -1
- package/dist/node-server.d.ts +29 -0
- package/dist/node-server.d.ts.map +1 -0
- package/dist/node-server.js +81 -0
- package/dist/node-server.js.map +1 -0
- package/dist/render.d.ts +9 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +20 -41
- package/dist/render.js.map +1 -1
- package/dist/route-dispatch.d.ts +2 -0
- package/dist/route-dispatch.d.ts.map +1 -0
- package/dist/route-dispatch.js +16 -0
- package/dist/route-dispatch.js.map +1 -0
- package/dist/route-loader-runtime.d.ts +22 -0
- package/dist/route-loader-runtime.d.ts.map +1 -0
- package/dist/route-loader-runtime.js +30 -0
- package/dist/route-loader-runtime.js.map +1 -0
- package/dist/routes.d.ts +2 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +48 -1
- package/dist/routes.js.map +1 -1
- package/dist/serve.d.ts +4 -3
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +84 -582
- package/dist/serve.js.map +1 -1
- package/package.json +11 -11
- package/src/adapters/cloudflare.ts +5 -60
- package/src/build.ts +143 -0
- package/src/built-assets.ts +164 -0
- package/src/built-runtime.ts +312 -0
- package/src/built-server-module-artifacts.ts +340 -0
- package/src/client-manifest-assets.ts +92 -0
- package/src/client.ts +79 -13
- package/src/node-server.ts +129 -0
- package/src/render.ts +38 -60
- package/src/route-dispatch.ts +17 -0
- package/src/route-loader-runtime.ts +54 -0
- package/src/routes.ts +70 -1
- package/src/serve.ts +105 -863
package/dist/serve.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { builtClientAssetPathname, clearBuiltPublicAssetCacheForTest, getBuiltPublicAssetCacheSizeForTest, readBuiltClientAsset, readBuiltPublicAsset, } from "./built-assets.js";
|
|
4
|
+
import { materializeBuiltRuntime, mergeBuiltRuntimeImportPolicy, readBuiltImportPolicyText, } from "./built-runtime.js";
|
|
5
|
+
import { allBuiltServerModuleFiles, loadBuiltServerModuleArtifacts, loadBuiltServerModuleArtifactsForRequest, } from "./built-server-module-artifacts.js";
|
|
6
|
+
import {} from "./routes.js";
|
|
6
7
|
import { preloadBuiltRequestModules, renderAppRequest, resolveAppRouterMiddleware, } from "./render.js";
|
|
7
|
-
import { bytesResponse, htmlResponse,
|
|
8
|
-
import { emitRouterLog, logDurationMs,
|
|
8
|
+
import { bytesResponse, htmlResponse, } from "./http.js";
|
|
9
|
+
import { emitRouterLog, logDurationMs, logNow, } from "./logger.js";
|
|
10
|
+
import { startNodeRequestServer } from "./node-server.js";
|
|
9
11
|
import { builtAppRuntimePreloadPlan } from "./preload-policy.js";
|
|
10
|
-
import { routeShellCandidates } from "./route-shells.js";
|
|
11
12
|
import { normalizeRoutePath } from "./route-path.js";
|
|
12
13
|
const builtRuntimeCache = new Map();
|
|
13
|
-
const
|
|
14
|
+
const builtRuntimeReadInflight = new Map();
|
|
15
|
+
let builtRuntimeMaterializeCountForTest = 0;
|
|
14
16
|
let warnedImplicitHostTrust = false;
|
|
15
17
|
export function resolveRequestHost(options) {
|
|
16
18
|
const raw = options.rawHost;
|
|
@@ -284,196 +286,40 @@ export async function startServer(options) {
|
|
|
284
286
|
importPolicy: options.importPolicy,
|
|
285
287
|
outDir: options.outDir,
|
|
286
288
|
});
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
emitRouterLog(options.logger, "info", {
|
|
306
|
-
...logFields,
|
|
307
|
-
type: "router:request:start",
|
|
308
|
-
});
|
|
309
|
-
const response = await runtime.render(request, {
|
|
310
|
-
instrumentation: options.instrumentation,
|
|
311
|
-
logger: options.logger,
|
|
312
|
-
onResponse: options.onResponse,
|
|
313
|
-
prerenderStore: options.prerenderStore,
|
|
314
|
-
routeCache: options.routeCache,
|
|
315
|
-
serverActions: options.serverActions,
|
|
316
|
-
...(options.sinkStrategy === undefined ? {} : { sinkStrategy: options.sinkStrategy }),
|
|
317
|
-
});
|
|
318
|
-
emitRouterLog(options.logger, "info", {
|
|
319
|
-
...logFields,
|
|
320
|
-
durationMs: logDurationMs(startedAt),
|
|
321
|
-
status: response.status,
|
|
322
|
-
type: "router:request:end",
|
|
323
|
-
});
|
|
324
|
-
await sendResponse(outgoing, response);
|
|
325
|
-
}
|
|
326
|
-
catch (error) {
|
|
327
|
-
// Log the full stack to stderr for operator visibility; never
|
|
328
|
-
// place it in the response body where attackers can scrape it
|
|
329
|
-
// (Issue 071). The errorHandler hook lets embedders customize
|
|
330
|
-
// the public response shape while still benefiting from the
|
|
331
|
-
// server-side log.
|
|
332
|
-
emitRouterLog(options.logger, "error", {
|
|
333
|
-
...fallbackRequestFields,
|
|
334
|
-
durationMs: logDurationMs(startedAt),
|
|
335
|
-
error: logError(error),
|
|
336
|
-
type: "router:request:error",
|
|
337
|
-
});
|
|
338
|
-
if (options.logger === undefined) {
|
|
339
|
-
console.error("[mreact] startServer request failed:", error);
|
|
340
|
-
}
|
|
341
|
-
const payload = options.errorHandler
|
|
342
|
-
? options.errorHandler(error)
|
|
343
|
-
: { body: "Internal Server Error", status: 500 };
|
|
344
|
-
outgoing.statusCode = payload.status;
|
|
345
|
-
outgoing.setHeader("content-type", payload.headers?.["content-type"] ?? "text/plain; charset=utf-8");
|
|
346
|
-
for (const [name, value] of Object.entries(payload.headers ?? {})) {
|
|
347
|
-
if (name.toLowerCase() === "content-type")
|
|
348
|
-
continue;
|
|
349
|
-
outgoing.setHeader(name, value);
|
|
350
|
-
}
|
|
351
|
-
outgoing.end(payload.body);
|
|
352
|
-
}
|
|
289
|
+
return await startNodeRequestServer({
|
|
290
|
+
allowedHosts: options.allowedHosts,
|
|
291
|
+
errorHandler: options.errorHandler,
|
|
292
|
+
hostname: options.hostname,
|
|
293
|
+
hostPolicy: options.hostPolicy,
|
|
294
|
+
logger: options.logger,
|
|
295
|
+
onUpgrade: options.onUpgrade,
|
|
296
|
+
port: options.port,
|
|
297
|
+
resolveHost: resolveRequestHost,
|
|
298
|
+
render: (request) => runtime.render(request, {
|
|
299
|
+
instrumentation: options.instrumentation,
|
|
300
|
+
logger: options.logger,
|
|
301
|
+
onResponse: options.onResponse,
|
|
302
|
+
prerenderStore: options.prerenderStore,
|
|
303
|
+
routeCache: options.routeCache,
|
|
304
|
+
serverActions: options.serverActions,
|
|
305
|
+
...(options.sinkStrategy === undefined ? {} : { sinkStrategy: options.sinkStrategy }),
|
|
306
|
+
}),
|
|
353
307
|
});
|
|
354
|
-
if (options.onUpgrade !== undefined) {
|
|
355
|
-
server.on("upgrade", options.onUpgrade);
|
|
356
|
-
}
|
|
357
|
-
await new Promise((resolve) => server.listen(options.port, options.hostname ?? "127.0.0.1", resolve));
|
|
358
|
-
const address = server.address();
|
|
359
|
-
const port = typeof address === "object" && address !== null ? address.port : options.port;
|
|
360
|
-
return {
|
|
361
|
-
server,
|
|
362
|
-
url: `http://${options.hostname ?? "127.0.0.1"}:${port}`,
|
|
363
|
-
close: () => new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve()))),
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
async function readBuiltClientAsset(outDir, pathname, allowedPaths) {
|
|
367
|
-
const clientPrefix = "/_mreact/client/";
|
|
368
|
-
const normalized = safeBuiltClientAssetPath(pathname.slice(clientPrefix.length));
|
|
369
|
-
if (normalized === undefined || !allowedPaths.has(normalized)) {
|
|
370
|
-
return new Response("Not Found", { status: 404 });
|
|
371
|
-
}
|
|
372
|
-
try {
|
|
373
|
-
const code = await readFile(join(outDir, "client", normalized), "utf8");
|
|
374
|
-
return new Response(code, {
|
|
375
|
-
headers: clientAssetHeaders(normalized),
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
catch {
|
|
379
|
-
return new Response("Not Found", { status: 404 });
|
|
380
|
-
}
|
|
381
308
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
return normalizedPathname.startsWith("/_mreact/client/") ? normalizedPathname : undefined;
|
|
388
|
-
}
|
|
389
|
-
function safeBuiltClientAssetPath(relativePath) {
|
|
390
|
-
let decoded;
|
|
391
|
-
try {
|
|
392
|
-
decoded = decodeURIComponent(relativePath);
|
|
393
|
-
}
|
|
394
|
-
catch {
|
|
395
|
-
return undefined;
|
|
396
|
-
}
|
|
397
|
-
if (decoded.includes("\\") || decoded.includes("\0")) {
|
|
398
|
-
return undefined;
|
|
399
|
-
}
|
|
400
|
-
if (decoded.split("/").some((segment) => segment === "..")) {
|
|
401
|
-
return undefined;
|
|
402
|
-
}
|
|
403
|
-
const normalized = normalize(decoded);
|
|
404
|
-
if (isAbsolute(normalized) || normalized === ".." || normalized.startsWith(`..${sep}`)) {
|
|
405
|
-
return undefined;
|
|
406
|
-
}
|
|
407
|
-
return normalized;
|
|
408
|
-
}
|
|
409
|
-
function builtClientAssetPaths(manifest) {
|
|
410
|
-
const paths = new Set(["manifest.json"]);
|
|
411
|
-
for (const route of manifest.routes) {
|
|
412
|
-
for (const asset of [
|
|
413
|
-
route.script,
|
|
414
|
-
route.sourceMap,
|
|
415
|
-
route.navigationScript,
|
|
416
|
-
...(route.css ?? []),
|
|
417
|
-
...(route.imports ?? []),
|
|
418
|
-
]) {
|
|
419
|
-
const path = safeClientManifestAssetPath(asset);
|
|
420
|
-
if (path !== undefined) {
|
|
421
|
-
paths.add(path);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
for (const asset of manifest.assets ?? []) {
|
|
426
|
-
const path = safeClientManifestAssetPath(asset);
|
|
427
|
-
if (path !== undefined) {
|
|
428
|
-
paths.add(path);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return paths;
|
|
309
|
+
export const __readBuiltPublicAssetForTest = readBuiltPublicAsset;
|
|
310
|
+
export function __clearBuiltRuntimeCacheForTest() {
|
|
311
|
+
builtRuntimeCache.clear();
|
|
312
|
+
builtRuntimeReadInflight.clear();
|
|
313
|
+
builtRuntimeMaterializeCountForTest = 0;
|
|
432
314
|
}
|
|
433
|
-
function
|
|
434
|
-
|
|
435
|
-
return undefined;
|
|
436
|
-
}
|
|
437
|
-
const segments = asset.split("/");
|
|
438
|
-
return segments.some((segment) => segment === "" || segment === "." || segment === "..")
|
|
439
|
-
? undefined
|
|
440
|
-
: segments.join("/");
|
|
315
|
+
export function __getBuiltRuntimeMaterializeCountForTest() {
|
|
316
|
+
return builtRuntimeMaterializeCountForTest;
|
|
441
317
|
}
|
|
442
|
-
async function readBuiltPublicAsset(outDir, pathname) {
|
|
443
|
-
const relativePath = pathname.startsWith("/") ? pathname.slice(1) : pathname;
|
|
444
|
-
if (relativePath === "") {
|
|
445
|
-
return undefined;
|
|
446
|
-
}
|
|
447
|
-
const normalized = normalize(relativePath);
|
|
448
|
-
if (isAbsolute(normalized) || normalized === ".." || normalized.startsWith("../")) {
|
|
449
|
-
return undefined;
|
|
450
|
-
}
|
|
451
|
-
try {
|
|
452
|
-
const cacheKey = `${outDir}\0${normalized}`;
|
|
453
|
-
const cached = builtPublicAssetCache.get(cacheKey);
|
|
454
|
-
if (cached !== undefined) {
|
|
455
|
-
return bytesResponse(cached.bytes, {
|
|
456
|
-
headers: cached.headers,
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
const bytes = await readFile(join(outDir, "client", "public", normalized));
|
|
460
|
-
const headers = publicAssetHeaders(normalized);
|
|
461
|
-
builtPublicAssetCache.set(cacheKey, {
|
|
462
|
-
bytes,
|
|
463
|
-
headers,
|
|
464
|
-
});
|
|
465
|
-
return bytesResponse(bytes, { headers });
|
|
466
|
-
}
|
|
467
|
-
catch {
|
|
468
|
-
return undefined;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
export const __readBuiltPublicAssetForTest = readBuiltPublicAsset;
|
|
472
318
|
export function __clearBuiltPublicAssetCacheForTest() {
|
|
473
|
-
|
|
319
|
+
clearBuiltPublicAssetCacheForTest();
|
|
474
320
|
}
|
|
475
321
|
export function __getBuiltPublicAssetCacheSizeForTest() {
|
|
476
|
-
return
|
|
322
|
+
return getBuiltPublicAssetCacheSizeForTest();
|
|
477
323
|
}
|
|
478
324
|
async function readBuiltRuntime(options) {
|
|
479
325
|
const outDir = options.outDir;
|
|
@@ -483,6 +329,36 @@ async function readBuiltRuntime(options) {
|
|
|
483
329
|
if (options.immutable === true && cached !== undefined) {
|
|
484
330
|
return cached.runtime;
|
|
485
331
|
}
|
|
332
|
+
if (cached === undefined) {
|
|
333
|
+
const inflight = builtRuntimeReadInflight.get(cacheKey);
|
|
334
|
+
if (inflight !== undefined) {
|
|
335
|
+
return inflight;
|
|
336
|
+
}
|
|
337
|
+
const runtime = readBuiltRuntimeUncached({
|
|
338
|
+
cacheKey,
|
|
339
|
+
cached,
|
|
340
|
+
outDir,
|
|
341
|
+
runtimeDir,
|
|
342
|
+
});
|
|
343
|
+
builtRuntimeReadInflight.set(cacheKey, runtime);
|
|
344
|
+
void runtime
|
|
345
|
+
.finally(() => {
|
|
346
|
+
if (builtRuntimeReadInflight.get(cacheKey) === runtime) {
|
|
347
|
+
builtRuntimeReadInflight.delete(cacheKey);
|
|
348
|
+
}
|
|
349
|
+
})
|
|
350
|
+
.catch(() => { });
|
|
351
|
+
return runtime;
|
|
352
|
+
}
|
|
353
|
+
return readBuiltRuntimeUncached({
|
|
354
|
+
cacheKey,
|
|
355
|
+
cached,
|
|
356
|
+
outDir,
|
|
357
|
+
runtimeDir,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
async function readBuiltRuntimeUncached(options) {
|
|
361
|
+
const { cacheKey, cached, outDir, runtimeDir } = options;
|
|
486
362
|
const serverManifestPath = join(outDir, "server", "manifest.json");
|
|
487
363
|
const clientManifestPath = join(outDir, "client", "manifest.json");
|
|
488
364
|
const importPolicyPath = join(outDir, "server", "import-policy.json");
|
|
@@ -502,6 +378,9 @@ async function readBuiltRuntime(options) {
|
|
|
502
378
|
clientManifestPath,
|
|
503
379
|
importPolicyText,
|
|
504
380
|
importPolicyPath,
|
|
381
|
+
onMaterialize() {
|
|
382
|
+
builtRuntimeMaterializeCountForTest += 1;
|
|
383
|
+
},
|
|
505
384
|
outDir,
|
|
506
385
|
runtimeDir,
|
|
507
386
|
serverManifestText,
|
|
@@ -513,137 +392,12 @@ async function readBuiltRuntime(options) {
|
|
|
513
392
|
runtime,
|
|
514
393
|
serverManifestText,
|
|
515
394
|
});
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
const serverManifest = parseBuiltJsonArtifact(options.serverManifestText, options.serverManifestPath, "built app server manifest");
|
|
520
|
-
const clientManifest = parseBuiltJsonArtifact(options.clientManifestText, options.clientManifestPath, "built app client manifest");
|
|
521
|
-
const appDir = await materializeBuiltServerApp(options.runtimeDir, serverManifest);
|
|
522
|
-
const projectRoot = appDir;
|
|
523
|
-
const routesDir = join(projectRoot, serverManifest.routesDir ?? "");
|
|
524
|
-
const routes = serverManifest.routes.map((route) => ({
|
|
525
|
-
...route,
|
|
526
|
-
file: join(projectRoot, route.file),
|
|
527
|
-
}));
|
|
528
|
-
const prerenderedRoutes = new Map(Object.entries(serverManifest.prerenderedRoutes ?? {}));
|
|
529
|
-
const prerenderableRoutes = new Set(prerenderedRoutes.keys());
|
|
530
|
-
const prerenderLocks = new Map();
|
|
531
|
-
const serverModules = new Map(Object.entries(serverManifest.serverModules ?? {}).map(([file, artifact]) => [
|
|
532
|
-
join(appDir, file),
|
|
533
|
-
artifact,
|
|
534
|
-
]));
|
|
535
|
-
const serverModuleFiles = new Map(Object.entries(serverManifest.serverModuleFiles ?? {}).map(([file, artifactFile]) => [
|
|
536
|
-
join(appDir, file),
|
|
537
|
-
join(options.outDir, "server", safeManifestFilePath(artifactFile)),
|
|
538
|
-
]));
|
|
539
|
-
const serverModuleRequestFiles = new Map(Object.entries(serverManifest.serverModuleRequestFiles ?? {}).map(([file, artifactFile]) => [
|
|
540
|
-
join(appDir, file),
|
|
541
|
-
join(options.outDir, "server", safeManifestFilePath(artifactFile)),
|
|
542
|
-
]));
|
|
543
|
-
const serverModuleRenderFiles = new Map(Object.entries(serverManifest.serverModuleRenderFiles ?? {}).map(([file, artifactFile]) => [
|
|
544
|
-
join(appDir, file),
|
|
545
|
-
join(options.outDir, "server", safeManifestFilePath(artifactFile)),
|
|
546
|
-
]));
|
|
547
|
-
const serverSourceFiles = new Map(Object.entries(serverManifest.files).map(([file, source]) => [join(appDir, file), source]));
|
|
548
|
-
const serverActionReferencesByFile = new Map(Object.entries(serverManifest.routeServerActionReferences ?? {}).map(([file, references]) => [
|
|
549
|
-
join(appDir, file),
|
|
550
|
-
references,
|
|
551
|
-
]));
|
|
552
|
-
const routeMatcher = createRouteMatcher(routes, serverManifest.routeMatcher);
|
|
553
|
-
const clientScripts = new Map(clientManifest.routes.flatMap((route) => route.client && route.script !== undefined ? [[route.path, route.script]] : []));
|
|
554
|
-
const clientStyles = new Map(clientManifest.routes.flatMap((route) => route.css !== undefined && route.css.length > 0 ? [[route.path, route.css]] : []));
|
|
555
|
-
const clientStylesByFile = new Map((clientManifest.styles ?? []).flatMap((style) => style.css !== undefined && style.css.length > 0
|
|
556
|
-
? [[join(routesDir, style.file), style.css]]
|
|
557
|
-
: []));
|
|
558
|
-
const navigationScripts = new Map(clientManifest.routes.flatMap((route) => route.navigation === true && route.navigationScript !== undefined
|
|
559
|
-
? [[route.path, route.navigationScript]]
|
|
560
|
-
: []));
|
|
561
|
-
const hasMiddleware = serverSourceFiles.has(join(routesDir, "middleware.ts")) ||
|
|
562
|
-
serverSourceFiles.has(join(routesDir, "middleware.mreact.ts"));
|
|
563
|
-
const serverModuleCacheVersion = createHash("sha256")
|
|
564
|
-
.update(options.serverManifestText)
|
|
565
|
-
.update("\0")
|
|
566
|
-
.update(options.clientManifestText)
|
|
567
|
-
.digest("hex")
|
|
568
|
-
.slice(0, 16);
|
|
569
|
-
const allowedSourceDirs = (serverManifest.allowedSourceDirs ?? [""]).map((directory) => join(projectRoot, directory));
|
|
570
|
-
const generatedImportPolicy = builtGeneratedImportPolicy(options.importPolicyText, options.importPolicyPath);
|
|
571
|
-
return {
|
|
572
|
-
appDir: routesDir,
|
|
573
|
-
allowedSourceDirs,
|
|
574
|
-
...(serverManifest.assetBaseUrl === undefined
|
|
575
|
-
? {}
|
|
576
|
-
: { assetBaseUrl: serverManifest.assetBaseUrl }),
|
|
577
|
-
clientAssetPaths: builtClientAssetPaths(clientManifest),
|
|
578
|
-
clientScripts,
|
|
579
|
-
clientStylesByFile,
|
|
580
|
-
clientStyles,
|
|
581
|
-
...(generatedImportPolicy === undefined ? {} : { generatedImportPolicy }),
|
|
582
|
-
hasMiddleware,
|
|
583
|
-
navigationScripts,
|
|
584
|
-
projectRoot,
|
|
585
|
-
...(serverManifest.publicAssetBaseUrl === undefined
|
|
586
|
-
? {}
|
|
587
|
-
: { publicAssetBaseUrl: serverManifest.publicAssetBaseUrl }),
|
|
588
|
-
prerenderableRoutes,
|
|
589
|
-
prerenderLocks,
|
|
590
|
-
prerenderedRoutes,
|
|
591
|
-
routeMatcher,
|
|
592
|
-
routes,
|
|
593
|
-
serverActionReferencesByFile,
|
|
594
|
-
...(serverManifest.serverActionManifest === undefined
|
|
595
|
-
? {}
|
|
596
|
-
: { serverActionManifest: serverManifest.serverActionManifest }),
|
|
597
|
-
serverModuleArtifactLoads: new Map(),
|
|
598
|
-
serverModuleClosureFiles: new Map(),
|
|
599
|
-
serverModuleFiles,
|
|
600
|
-
serverModuleRenderFiles,
|
|
601
|
-
serverModuleRequestFiles,
|
|
602
|
-
serverModules,
|
|
603
|
-
serverModuleCacheVersion,
|
|
604
|
-
serverSourceFiles,
|
|
605
|
-
};
|
|
606
|
-
}
|
|
607
|
-
async function readBuiltImportPolicyText(outDir) {
|
|
608
|
-
const policyPath = join(outDir, "server", "import-policy.json");
|
|
609
|
-
try {
|
|
610
|
-
return await readFile(policyPath, "utf8");
|
|
611
|
-
}
|
|
612
|
-
catch (error) {
|
|
613
|
-
if (isMissingFileError(error)) {
|
|
614
|
-
return undefined;
|
|
395
|
+
runtime.catch(() => {
|
|
396
|
+
if (builtRuntimeCache.get(cacheKey)?.runtime === runtime) {
|
|
397
|
+
builtRuntimeCache.delete(cacheKey);
|
|
615
398
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
}
|
|
619
|
-
function builtGeneratedImportPolicy(importPolicyText, importPolicyPath) {
|
|
620
|
-
if (importPolicyText === undefined) {
|
|
621
|
-
return undefined;
|
|
622
|
-
}
|
|
623
|
-
const artifact = parseBuiltJsonArtifact(importPolicyText, importPolicyPath, "built app import policy");
|
|
624
|
-
const runtimePackages = Array.isArray(artifact.runtimePackages)
|
|
625
|
-
? artifact.runtimePackages.filter((name) => typeof name === "string")
|
|
626
|
-
: [];
|
|
627
|
-
return runtimePackages.length === 0 ? undefined : { allowedPackages: runtimePackages };
|
|
628
|
-
}
|
|
629
|
-
function mergeBuiltRuntimeImportPolicy(runtime, importPolicy) {
|
|
630
|
-
const generatedImportPolicy = runtime.generatedImportPolicy;
|
|
631
|
-
if (generatedImportPolicy === undefined) {
|
|
632
|
-
return importPolicy;
|
|
633
|
-
}
|
|
634
|
-
const allowedPackages = [
|
|
635
|
-
...new Set([
|
|
636
|
-
...(generatedImportPolicy.allowedPackages ?? []),
|
|
637
|
-
...(importPolicy?.allowedPackages ?? []),
|
|
638
|
-
]),
|
|
639
|
-
];
|
|
640
|
-
return {
|
|
641
|
-
...(allowedPackages.length === 0 ? {} : { allowedPackages }),
|
|
642
|
-
...(importPolicy?.allowedSourceDirs === undefined
|
|
643
|
-
? {}
|
|
644
|
-
: { allowedSourceDirs: importPolicy.allowedSourceDirs }),
|
|
645
|
-
...(importPolicy?.projectRoot === undefined ? {} : { projectRoot: importPolicy.projectRoot }),
|
|
646
|
-
};
|
|
399
|
+
});
|
|
400
|
+
return runtime;
|
|
647
401
|
}
|
|
648
402
|
function isMissingFileError(error) {
|
|
649
403
|
return (typeof error === "object" &&
|
|
@@ -664,201 +418,6 @@ function builtArtifactReadError(label, artifactPath, error) {
|
|
|
664
418
|
const detail = error instanceof Error && error.message !== "" ? `: ${error.message}` : "";
|
|
665
419
|
return new Error(`${prefix} ${label}: ${artifactPath}${detail}`, { cause: error });
|
|
666
420
|
}
|
|
667
|
-
function parseBuiltJsonArtifact(text, artifactPath, label) {
|
|
668
|
-
try {
|
|
669
|
-
return JSON.parse(text);
|
|
670
|
-
}
|
|
671
|
-
catch (error) {
|
|
672
|
-
const detail = error instanceof Error && error.message !== "" ? `: ${error.message}` : "";
|
|
673
|
-
throw new Error(`Invalid ${label}: ${artifactPath}${detail}`, { cause: error });
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
async function loadBuiltServerModuleArtifacts(runtime, files, kind = "all") {
|
|
677
|
-
for (const file of files) {
|
|
678
|
-
await loadBuiltServerModuleArtifact(runtime, file, kind);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
async function loadBuiltServerModuleArtifact(runtime, file, kind = "all") {
|
|
682
|
-
if (kind === "all") {
|
|
683
|
-
await loadBuiltServerModuleArtifact(runtime, file, "request");
|
|
684
|
-
await loadBuiltServerModuleArtifact(runtime, file, "render");
|
|
685
|
-
return;
|
|
686
|
-
}
|
|
687
|
-
const artifactPath = kind === "request"
|
|
688
|
-
? runtime.serverModuleRequestFiles.get(file) ?? runtime.serverModuleFiles.get(file)
|
|
689
|
-
: runtime.serverModuleRenderFiles.get(file) ?? runtime.serverModuleFiles.get(file);
|
|
690
|
-
if (artifactPath === undefined) {
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
const cached = runtime.serverModuleArtifactLoads.get(`${kind}\0${file}`);
|
|
694
|
-
if (cached !== undefined) {
|
|
695
|
-
await cached;
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
const loaded = readFile(artifactPath, "utf8")
|
|
699
|
-
.then((text) => {
|
|
700
|
-
const existing = runtime.serverModules.get(file) ?? {};
|
|
701
|
-
runtime.serverModules.set(file, mergeBuiltServerModuleArtifacts(existing, hydrateBuiltServerModuleArtifact(parseBuiltJsonArtifact(text, artifactPath, `built server module artifact for ${file}`), builtServerDirForArtifactPath(artifactPath))));
|
|
702
|
-
})
|
|
703
|
-
.catch((error) => {
|
|
704
|
-
runtime.serverModuleArtifactLoads.delete(`${kind}\0${file}`);
|
|
705
|
-
if (isMissingFileError(error)) {
|
|
706
|
-
throw builtArtifactReadError(`built server module artifact for ${file}`, artifactPath, error);
|
|
707
|
-
}
|
|
708
|
-
throw error;
|
|
709
|
-
});
|
|
710
|
-
runtime.serverModuleArtifactLoads.set(`${kind}\0${file}`, loaded);
|
|
711
|
-
await loaded;
|
|
712
|
-
}
|
|
713
|
-
function allBuiltServerModuleFiles(runtime) {
|
|
714
|
-
return new Set([
|
|
715
|
-
...runtime.serverModuleFiles.keys(),
|
|
716
|
-
...runtime.serverModuleRequestFiles.keys(),
|
|
717
|
-
...runtime.serverModuleRenderFiles.keys(),
|
|
718
|
-
]);
|
|
719
|
-
}
|
|
720
|
-
function builtServerDirForArtifactPath(artifactPath) {
|
|
721
|
-
const marker = `${sep}server-modules${sep}`;
|
|
722
|
-
const index = artifactPath.lastIndexOf(marker);
|
|
723
|
-
return index === -1 ? dirname(dirname(artifactPath)) : artifactPath.slice(0, index);
|
|
724
|
-
}
|
|
725
|
-
function hydrateBuiltServerModuleArtifact(artifact, serverDir) {
|
|
726
|
-
return {
|
|
727
|
-
...(artifact.analysis === undefined ? {} : { analysis: artifact.analysis }),
|
|
728
|
-
...(artifact.loader === undefined
|
|
729
|
-
? {}
|
|
730
|
-
: { loader: hydrateBuiltServerModuleOutput(artifact.loader, serverDir) }),
|
|
731
|
-
...(artifact.routeMetadata === undefined
|
|
732
|
-
? {}
|
|
733
|
-
: { routeMetadata: hydrateBuiltServerModuleOutput(artifact.routeMetadata, serverDir) }),
|
|
734
|
-
...(artifact.request === undefined
|
|
735
|
-
? {}
|
|
736
|
-
: { request: hydrateBuiltServerModuleOutput(artifact.request, serverDir) }),
|
|
737
|
-
...(artifact.stream === undefined
|
|
738
|
-
? {}
|
|
739
|
-
: { stream: hydrateBuiltServerModuleOutput(artifact.stream, serverDir) }),
|
|
740
|
-
...(artifact.string === undefined
|
|
741
|
-
? {}
|
|
742
|
-
: { string: hydrateBuiltServerModuleOutput(artifact.string, serverDir) }),
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
function hydrateBuiltServerModuleOutput(output, serverDir) {
|
|
746
|
-
if (output.moduleFile === undefined || isAbsolute(output.moduleFile)) {
|
|
747
|
-
return output;
|
|
748
|
-
}
|
|
749
|
-
return {
|
|
750
|
-
...output,
|
|
751
|
-
moduleFile: join(serverDir, safeManifestFilePath(output.moduleFile)),
|
|
752
|
-
};
|
|
753
|
-
}
|
|
754
|
-
function mergeBuiltServerModuleArtifacts(existing, loaded) {
|
|
755
|
-
return {
|
|
756
|
-
...existing,
|
|
757
|
-
...loaded,
|
|
758
|
-
};
|
|
759
|
-
}
|
|
760
|
-
async function loadBuiltServerModuleArtifactsForRequest(runtime, routeFile, options = {}) {
|
|
761
|
-
const roots = [
|
|
762
|
-
join(runtime.appDir, "middleware.ts"),
|
|
763
|
-
join(runtime.appDir, "middleware.mreact.ts"),
|
|
764
|
-
...(routeFile === undefined
|
|
765
|
-
? []
|
|
766
|
-
: [
|
|
767
|
-
routeFile,
|
|
768
|
-
...(options.includeShells === false ? [] : shellFilesForRoute(runtime, routeFile)),
|
|
769
|
-
]),
|
|
770
|
-
];
|
|
771
|
-
const seen = new Set();
|
|
772
|
-
for (const file of roots) {
|
|
773
|
-
await loadBuiltServerModuleArtifactClosure(runtime, file, seen, "request");
|
|
774
|
-
}
|
|
775
|
-
if (options.includeRender === true) {
|
|
776
|
-
seen.clear();
|
|
777
|
-
for (const file of roots) {
|
|
778
|
-
await loadBuiltServerModuleArtifactClosure(runtime, file, seen, "render");
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
async function loadBuiltServerModuleArtifactClosure(runtime, file, seen, kind) {
|
|
783
|
-
for (const closureFile of builtServerModuleClosureFiles(runtime, file)) {
|
|
784
|
-
if (seen.has(closureFile)) {
|
|
785
|
-
continue;
|
|
786
|
-
}
|
|
787
|
-
seen.add(closureFile);
|
|
788
|
-
await loadBuiltServerModuleArtifact(runtime, closureFile, kind);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
function builtServerModuleClosureFiles(runtime, file) {
|
|
792
|
-
const cached = runtime.serverModuleClosureFiles.get(file);
|
|
793
|
-
if (cached !== undefined) {
|
|
794
|
-
return cached;
|
|
795
|
-
}
|
|
796
|
-
const closure = [];
|
|
797
|
-
collectBuiltServerModuleClosureFiles(runtime, file, new Set(), closure);
|
|
798
|
-
runtime.serverModuleClosureFiles.set(file, closure);
|
|
799
|
-
return closure;
|
|
800
|
-
}
|
|
801
|
-
function collectBuiltServerModuleClosureFiles(runtime, file, seen, closure) {
|
|
802
|
-
if (seen.has(file)) {
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
seen.add(file);
|
|
806
|
-
closure.push(file);
|
|
807
|
-
const source = runtime.serverSourceFiles.get(file);
|
|
808
|
-
if (source === undefined) {
|
|
809
|
-
return;
|
|
810
|
-
}
|
|
811
|
-
for (const specifier of localServerModuleSpecifiers(source)) {
|
|
812
|
-
const resolved = resolveBuiltLocalServerSourceImport(runtime, file, specifier);
|
|
813
|
-
if (resolved !== undefined) {
|
|
814
|
-
collectBuiltServerModuleClosureFiles(runtime, resolved, seen, closure);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
const localServerModuleImportPattern = /\b(?:import|export)\s+(?:type\s+)?(?:[^"']*?\s+from\s*)?["'](?<source>\.{1,2}\/[^"']+)["']/g;
|
|
819
|
-
function localServerModuleSpecifiers(code) {
|
|
820
|
-
const specifiers = new Set();
|
|
821
|
-
localServerModuleImportPattern.lastIndex = 0;
|
|
822
|
-
for (const match of code.matchAll(localServerModuleImportPattern)) {
|
|
823
|
-
const source = match.groups?.source;
|
|
824
|
-
if (source !== undefined) {
|
|
825
|
-
specifiers.add(source);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
return Array.from(specifiers);
|
|
829
|
-
}
|
|
830
|
-
function resolveBuiltLocalServerSourceImport(runtime, fromFile, specifier) {
|
|
831
|
-
const base = join(dirname(fromFile), specifier);
|
|
832
|
-
for (const candidate of localServerSourceImportCandidates(base)) {
|
|
833
|
-
if (runtime.serverSourceFiles.has(candidate)) {
|
|
834
|
-
return candidate;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
return undefined;
|
|
838
|
-
}
|
|
839
|
-
function localServerSourceImportCandidates(base) {
|
|
840
|
-
const candidates = [base];
|
|
841
|
-
if (base.endsWith(".js")) {
|
|
842
|
-
const withoutJs = base.slice(0, -".js".length);
|
|
843
|
-
candidates.push(`${withoutJs}.ts`, `${withoutJs}.tsx`, `${withoutJs}.mreact.tsx`);
|
|
844
|
-
}
|
|
845
|
-
else if (base.endsWith(".jsx")) {
|
|
846
|
-
const withoutJsx = base.slice(0, -".jsx".length);
|
|
847
|
-
candidates.push(`${withoutJsx}.tsx`, `${withoutJsx}.mreact.tsx`);
|
|
848
|
-
}
|
|
849
|
-
else if (base.endsWith(".mreact")) {
|
|
850
|
-
candidates.push(`${base}.tsx`);
|
|
851
|
-
}
|
|
852
|
-
else {
|
|
853
|
-
candidates.push(`${base}.ts`, `${base}.tsx`, `${base}.mreact.tsx`, join(base, "index.ts"), join(base, "index.tsx"), join(base, "index.mreact.tsx"));
|
|
854
|
-
}
|
|
855
|
-
return candidates;
|
|
856
|
-
}
|
|
857
|
-
function shellFilesForRoute(runtime, routeFile) {
|
|
858
|
-
return routeShellCandidates(runtime.appDir, routeFile)
|
|
859
|
-
.map((candidate) => candidate.file)
|
|
860
|
-
.filter((file) => runtime.serverSourceFiles.has(file));
|
|
861
|
-
}
|
|
862
421
|
async function readPrerenderedRoute(runtime, path, store) {
|
|
863
422
|
const stored = await store?.get(path);
|
|
864
423
|
if (stored !== undefined) {
|
|
@@ -875,6 +434,13 @@ function renderBuiltDynamicResponse(options) {
|
|
|
875
434
|
return renderAppRequest(builtRenderAppRequestOptions(options));
|
|
876
435
|
}
|
|
877
436
|
function builtRenderAppRequestOptions(options) {
|
|
437
|
+
const serverRenderArtifactLoader = {
|
|
438
|
+
async load(routeFile) {
|
|
439
|
+
await loadBuiltServerModuleArtifactsForRequest(options.runtime, routeFile, {
|
|
440
|
+
includeRender: true,
|
|
441
|
+
});
|
|
442
|
+
},
|
|
443
|
+
};
|
|
878
444
|
const renderOptions = {
|
|
879
445
|
appDir: options.runtime.appDir,
|
|
880
446
|
assetBaseUrl: options.runtime.assetBaseUrl,
|
|
@@ -895,11 +461,7 @@ function builtRenderAppRequestOptions(options) {
|
|
|
895
461
|
routeMatcher: options.runtime.routeMatcher,
|
|
896
462
|
requestUrl: options.requestUrl,
|
|
897
463
|
routes: options.runtime.routes,
|
|
898
|
-
|
|
899
|
-
await loadBuiltServerModuleArtifactsForRequest(options.runtime, routeFile, {
|
|
900
|
-
includeRender: true,
|
|
901
|
-
});
|
|
902
|
-
},
|
|
464
|
+
serverRenderArtifactLoader,
|
|
903
465
|
serverModules: options.runtime.serverModules,
|
|
904
466
|
serverModuleCacheVersion: options.runtime.serverModuleCacheVersion,
|
|
905
467
|
serverSourceFiles: options.runtime.serverSourceFiles,
|
|
@@ -986,64 +548,4 @@ async function cloneResponse(response) {
|
|
|
986
548
|
status: response.status,
|
|
987
549
|
});
|
|
988
550
|
}
|
|
989
|
-
async function materializeBuiltServerApp(runtimeDir, manifest) {
|
|
990
|
-
const appDir = join(runtimeDir, "app");
|
|
991
|
-
await rm(appDir, { force: true, recursive: true });
|
|
992
|
-
await Promise.all(Object.entries(manifest.files).map(async ([file, code]) => {
|
|
993
|
-
const outputFile = join(appDir, safeManifestFilePath(file));
|
|
994
|
-
await mkdir(dirname(outputFile), { recursive: true });
|
|
995
|
-
await writeFile(outputFile, code);
|
|
996
|
-
}));
|
|
997
|
-
return appDir;
|
|
998
|
-
}
|
|
999
|
-
function safeManifestFilePath(pathname) {
|
|
1000
|
-
const normalized = normalize(pathname);
|
|
1001
|
-
if (isAbsolute(normalized) || normalized === ".." || normalized.startsWith("../")) {
|
|
1002
|
-
throw new Error(`Invalid built app manifest file path: ${pathname}`);
|
|
1003
|
-
}
|
|
1004
|
-
return normalized;
|
|
1005
|
-
}
|
|
1006
|
-
function clientAssetHeaders(pathname) {
|
|
1007
|
-
if (pathname === "manifest.json") {
|
|
1008
|
-
return {
|
|
1009
|
-
"cache-control": "no-cache",
|
|
1010
|
-
"content-type": "application/json; charset=utf-8",
|
|
1011
|
-
};
|
|
1012
|
-
}
|
|
1013
|
-
return {
|
|
1014
|
-
"cache-control": "public, max-age=31536000, immutable",
|
|
1015
|
-
"content-type": pathname.endsWith(".css")
|
|
1016
|
-
? "text/css; charset=utf-8"
|
|
1017
|
-
: "text/javascript; charset=utf-8",
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
function publicAssetHeaders(pathname) {
|
|
1021
|
-
return {
|
|
1022
|
-
"cache-control": "public, max-age=3600",
|
|
1023
|
-
"content-type": publicAssetContentType(pathname),
|
|
1024
|
-
};
|
|
1025
|
-
}
|
|
1026
|
-
function publicAssetContentType(pathname) {
|
|
1027
|
-
if (pathname.endsWith(".css"))
|
|
1028
|
-
return "text/css; charset=utf-8";
|
|
1029
|
-
if (pathname.endsWith(".html"))
|
|
1030
|
-
return "text/html; charset=utf-8";
|
|
1031
|
-
if (pathname.endsWith(".js"))
|
|
1032
|
-
return "text/javascript; charset=utf-8";
|
|
1033
|
-
if (pathname.endsWith(".json"))
|
|
1034
|
-
return "application/json; charset=utf-8";
|
|
1035
|
-
if (pathname.endsWith(".svg"))
|
|
1036
|
-
return "image/svg+xml";
|
|
1037
|
-
if (pathname.endsWith(".png"))
|
|
1038
|
-
return "image/png";
|
|
1039
|
-
if (pathname.endsWith(".jpg") || pathname.endsWith(".jpeg"))
|
|
1040
|
-
return "image/jpeg";
|
|
1041
|
-
if (pathname.endsWith(".webp"))
|
|
1042
|
-
return "image/webp";
|
|
1043
|
-
if (pathname.endsWith(".ico"))
|
|
1044
|
-
return "image/x-icon";
|
|
1045
|
-
if (pathname.endsWith(".txt"))
|
|
1046
|
-
return "text/plain; charset=utf-8";
|
|
1047
|
-
return "application/octet-stream";
|
|
1048
|
-
}
|
|
1049
551
|
//# sourceMappingURL=serve.js.map
|