@reckona/mreact-router 0.0.81 → 0.0.83
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 +2 -0
- package/dist/adapters/aws-lambda.d.ts.map +1 -1
- package/dist/adapters/aws-lambda.js +17 -22
- package/dist/adapters/aws-lambda.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +3 -1
- package/dist/build.js.map +1 -1
- package/dist/client-route-inference.d.ts +2 -0
- package/dist/client-route-inference.d.ts.map +1 -0
- package/dist/client-route-inference.js +2 -0
- package/dist/client-route-inference.js.map +1 -0
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +89 -24
- package/dist/client.js.map +1 -1
- package/dist/layout-composer.d.ts +24 -0
- package/dist/layout-composer.d.ts.map +1 -0
- package/dist/layout-composer.js +83 -0
- package/dist/layout-composer.js.map +1 -0
- package/dist/metadata.d.ts +9 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +419 -0
- package/dist/metadata.js.map +1 -0
- package/dist/middleware.d.ts +22 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +94 -0
- package/dist/middleware.js.map +1 -0
- package/dist/module-runner.d.ts +2 -2
- package/dist/module-runner.d.ts.map +1 -1
- package/dist/module-runner.js +1 -1
- package/dist/module-runner.js.map +1 -1
- package/dist/navigation-runtime.d.ts +2 -0
- package/dist/navigation-runtime.d.ts.map +1 -0
- package/dist/navigation-runtime.js +2 -0
- package/dist/navigation-runtime.js.map +1 -0
- package/dist/preload-policy.d.ts +24 -0
- package/dist/preload-policy.d.ts.map +1 -0
- package/dist/preload-policy.js +45 -0
- package/dist/preload-policy.js.map +1 -0
- package/dist/render.d.ts +1 -3
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +32 -676
- package/dist/render.js.map +1 -1
- package/dist/route-hydration-contract.d.ts +11 -0
- package/dist/route-hydration-contract.d.ts.map +1 -0
- package/dist/route-hydration-contract.js +21 -0
- package/dist/route-hydration-contract.js.map +1 -0
- package/dist/route-module-loader.d.ts +10 -0
- package/dist/route-module-loader.d.ts.map +1 -0
- package/dist/route-module-loader.js +61 -0
- package/dist/route-module-loader.js.map +1 -0
- package/dist/routes.js +6 -0
- package/dist/routes.js.map +1 -1
- package/dist/serve.d.ts +13 -0
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +63 -28
- package/dist/serve.js.map +1 -1
- package/dist/server-action-inference.d.ts.map +1 -1
- package/dist/server-action-inference.js +37 -1
- package/dist/server-action-inference.js.map +1 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +2 -1
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/adapters/aws-lambda.ts +21 -28
- package/src/build.ts +9 -6
- package/src/client-route-inference.ts +18 -0
- package/src/client.ts +124 -24
- package/src/layout-composer.ts +142 -0
- package/src/metadata.ts +578 -0
- package/src/middleware.ts +153 -0
- package/src/module-runner.ts +3 -2
- package/src/navigation-runtime.ts +16 -0
- package/src/preload-policy.ts +89 -0
- package/src/render.ts +75 -986
- package/src/route-hydration-contract.ts +22 -0
- package/src/route-module-loader.ts +95 -0
- package/src/routes.ts +8 -0
- package/src/serve.ts +110 -29
- package/src/server-action-inference.ts +49 -0
- package/src/vite.ts +6 -4
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const routeHydrationContract: {
|
|
2
|
+
readonly clientReferencesScriptPrefix: "mreact-client-references-";
|
|
3
|
+
readonly hydratedAttribute: "data-mreact-hydrated";
|
|
4
|
+
readonly hotRouteHydrateExport: "__mreactHotHydrateRoute";
|
|
5
|
+
readonly propsScriptPrefix: "mreact-props-";
|
|
6
|
+
readonly routeHydrateExport: "__mreactHydrateRoute";
|
|
7
|
+
readonly routeMarkerAttribute: "data-mreact-route-id";
|
|
8
|
+
};
|
|
9
|
+
export declare function routeDataScriptIds(routeId: string): [string, string];
|
|
10
|
+
export declare function routeDataScriptSelector(): string;
|
|
11
|
+
//# sourceMappingURL=route-hydration-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-hydration-contract.d.ts","sourceRoot":"","sources":["../src/route-hydration-contract.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB;;;;;;;CAOzB,CAAC;AAEX,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAKpE;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAKhD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const routeHydrationContract = {
|
|
2
|
+
clientReferencesScriptPrefix: "mreact-client-references-",
|
|
3
|
+
hydratedAttribute: "data-mreact-hydrated",
|
|
4
|
+
hotRouteHydrateExport: "__mreactHotHydrateRoute",
|
|
5
|
+
propsScriptPrefix: "mreact-props-",
|
|
6
|
+
routeHydrateExport: "__mreactHydrateRoute",
|
|
7
|
+
routeMarkerAttribute: "data-mreact-route-id",
|
|
8
|
+
};
|
|
9
|
+
export function routeDataScriptIds(routeId) {
|
|
10
|
+
return [
|
|
11
|
+
`${routeHydrationContract.propsScriptPrefix}${routeId}`,
|
|
12
|
+
`${routeHydrationContract.clientReferencesScriptPrefix}${routeId}`,
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
export function routeDataScriptSelector() {
|
|
16
|
+
return [
|
|
17
|
+
`script[type="application/json"][id^="${routeHydrationContract.propsScriptPrefix}"]`,
|
|
18
|
+
`script[type="application/json"][id^="${routeHydrationContract.clientReferencesScriptPrefix}"]`,
|
|
19
|
+
].join(", ");
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=route-hydration-contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-hydration-contract.js","sourceRoot":"","sources":["../src/route-hydration-contract.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,4BAA4B,EAAE,2BAA2B;IACzD,iBAAiB,EAAE,sBAAsB;IACzC,qBAAqB,EAAE,yBAAyB;IAChD,iBAAiB,EAAE,eAAe;IAClC,kBAAkB,EAAE,sBAAsB;IAC1C,oBAAoB,EAAE,sBAAsB;CACpC,CAAC;AAEX,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO;QACL,GAAG,sBAAsB,CAAC,iBAAiB,GAAG,OAAO,EAAE;QACvD,GAAG,sBAAsB,CAAC,4BAA4B,GAAG,OAAO,EAAE;KACnE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO;QACL,wCAAwC,sBAAsB,CAAC,iBAAiB,IAAI;QACpF,wCAAwC,sBAAsB,CAAC,4BAA4B,IAAI;KAChG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC","sourcesContent":["export const routeHydrationContract = {\n clientReferencesScriptPrefix: \"mreact-client-references-\",\n hydratedAttribute: \"data-mreact-hydrated\",\n hotRouteHydrateExport: \"__mreactHotHydrateRoute\",\n propsScriptPrefix: \"mreact-props-\",\n routeHydrateExport: \"__mreactHydrateRoute\",\n routeMarkerAttribute: \"data-mreact-route-id\",\n} as const;\n\nexport function routeDataScriptIds(routeId: string): [string, string] {\n return [\n `${routeHydrationContract.propsScriptPrefix}${routeId}`,\n `${routeHydrationContract.clientReferencesScriptPrefix}${routeId}`,\n ];\n}\n\nexport function routeDataScriptSelector(): string {\n return [\n `script[type=\"application/json\"][id^=\"${routeHydrationContract.propsScriptPrefix}\"]`,\n `script[type=\"application/json\"][id^=\"${routeHydrationContract.clientReferencesScriptPrefix}\"]`,\n ].join(\", \");\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BuiltServerModuleArtifact } from "./build.js";
|
|
2
|
+
import type { AppRouterImportPolicy } from "./import-policy.js";
|
|
3
|
+
export type BuiltServerModuleOutputLike = NonNullable<BuiltServerModuleArtifact["request"]>;
|
|
4
|
+
export declare function memoizedHashText(code: string): string;
|
|
5
|
+
export declare function prebuiltRequestModuleArtifact(serverModules: ReadonlyMap<string, BuiltServerModuleArtifact> | undefined, file: string, source: string, kind?: "request" | "routeMetadata"): BuiltServerModuleOutputLike | undefined;
|
|
6
|
+
export declare function prebuiltRouteLoaderModuleArtifact(serverModules: ReadonlyMap<string, BuiltServerModuleArtifact> | undefined, file: string, source: string): BuiltServerModuleOutputLike | undefined;
|
|
7
|
+
export declare function prebuiltServerComponentModuleCode(artifact: BuiltServerModuleArtifact["string"] | BuiltServerModuleArtifact["stream"] | undefined, code: string, codeHash: string): string | undefined;
|
|
8
|
+
export declare function prebuiltServerModuleOutputMatches(artifact: BuiltServerModuleOutputLike, code: string, codeHash: string): boolean;
|
|
9
|
+
export declare function importPolicyCacheKey(policy: AppRouterImportPolicy | undefined): string;
|
|
10
|
+
//# sourceMappingURL=route-module-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-module-loader.d.ts","sourceRoot":"","sources":["../src/route-module-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,MAAM,2BAA2B,GAAG,WAAW,CAAC,yBAAyB,CAAC,SAAS,CAAC,CAAC,CAAC;AAS5F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBrD;AAED,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,SAAS,EACzE,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,SAAS,GAAG,eAA2B,GAC5C,2BAA2B,GAAG,SAAS,CAMzC;AAED,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,yBAAyB,CAAC,GAAG,SAAS,EACzE,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,2BAA2B,GAAG,SAAS,CAMzC;AAED,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,yBAAyB,CAAC,QAAQ,CAAC,GAAG,yBAAyB,CAAC,QAAQ,CAAC,GAAG,SAAS,EAC/F,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,2BAA2B,EACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAET;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,SAAS,GAAG,MAAM,CAUtF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
// Per-request hashText (SHA-256) is one of the hot path's dominant
|
|
3
|
+
// costs. Cache hashes for `code` strings we have already seen this
|
|
4
|
+
// process (common case: the prepared code is identical across requests
|
|
5
|
+
// when the source file is unchanged).
|
|
6
|
+
const codeHashCache = new Map();
|
|
7
|
+
const MAX_CODE_HASH_ENTRIES = 256;
|
|
8
|
+
export function memoizedHashText(code) {
|
|
9
|
+
const cached = codeHashCache.get(code);
|
|
10
|
+
if (cached !== undefined) {
|
|
11
|
+
return cached;
|
|
12
|
+
}
|
|
13
|
+
const hash = hashText(code);
|
|
14
|
+
if (codeHashCache.size >= MAX_CODE_HASH_ENTRIES) {
|
|
15
|
+
// Simple LRU eviction: drop the oldest entry (Map keeps insertion order).
|
|
16
|
+
const oldestKey = codeHashCache.keys().next().value;
|
|
17
|
+
if (oldestKey !== undefined) {
|
|
18
|
+
codeHashCache.delete(oldestKey);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
codeHashCache.set(code, hash);
|
|
22
|
+
return hash;
|
|
23
|
+
}
|
|
24
|
+
export function prebuiltRequestModuleArtifact(serverModules, file, source, kind = "request") {
|
|
25
|
+
const artifact = serverModules?.get(file)?.[kind];
|
|
26
|
+
return artifact !== undefined && artifact.sourceHash === memoizedHashText(source)
|
|
27
|
+
? artifact
|
|
28
|
+
: undefined;
|
|
29
|
+
}
|
|
30
|
+
export function prebuiltRouteLoaderModuleArtifact(serverModules, file, source) {
|
|
31
|
+
const artifact = serverModules?.get(file)?.loader;
|
|
32
|
+
return artifact !== undefined && artifact.sourceHash === memoizedHashText(source)
|
|
33
|
+
? artifact
|
|
34
|
+
: prebuiltRequestModuleArtifact(serverModules, file, source);
|
|
35
|
+
}
|
|
36
|
+
export function prebuiltServerComponentModuleCode(artifact, code, codeHash) {
|
|
37
|
+
if (artifact === undefined) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
if (!prebuiltServerModuleOutputMatches(artifact, code, codeHash)) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return artifact.bundleCode;
|
|
44
|
+
}
|
|
45
|
+
export function prebuiltServerModuleOutputMatches(artifact, code, codeHash) {
|
|
46
|
+
return artifact.sourceHash === codeHash || artifact.code === code;
|
|
47
|
+
}
|
|
48
|
+
export function importPolicyCacheKey(policy) {
|
|
49
|
+
if (policy === undefined) {
|
|
50
|
+
return "";
|
|
51
|
+
}
|
|
52
|
+
return JSON.stringify({
|
|
53
|
+
allowedPackages: [...(policy.allowedPackages ?? [])].sort(),
|
|
54
|
+
allowedSourceDirs: [...(policy.allowedSourceDirs ?? [])].sort(),
|
|
55
|
+
projectRoot: policy.projectRoot ?? "",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function hashText(text) {
|
|
59
|
+
return createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=route-module-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-module-loader.js","sourceRoot":"","sources":["../src/route-module-loader.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { BuiltServerModuleArtifact } from \"./build.js\";\nimport type { AppRouterImportPolicy } from \"./import-policy.js\";\n\nexport type BuiltServerModuleOutputLike = NonNullable<BuiltServerModuleArtifact[\"request\"]>;\n\n// Per-request hashText (SHA-256) is one of the hot path's dominant\n// costs. Cache hashes for `code` strings we have already seen this\n// process (common case: the prepared code is identical across requests\n// when the source file is unchanged).\nconst codeHashCache = new Map<string, string>();\nconst MAX_CODE_HASH_ENTRIES = 256;\n\nexport function memoizedHashText(code: string): string {\n const cached = codeHashCache.get(code);\n if (cached !== undefined) {\n return cached;\n }\n\n const hash = hashText(code);\n if (codeHashCache.size >= MAX_CODE_HASH_ENTRIES) {\n // Simple LRU eviction: drop the oldest entry (Map keeps insertion order).\n const oldestKey = codeHashCache.keys().next().value;\n if (oldestKey !== undefined) {\n codeHashCache.delete(oldestKey);\n }\n }\n codeHashCache.set(code, hash);\n return hash;\n}\n\nexport function prebuiltRequestModuleArtifact(\n serverModules: ReadonlyMap<string, BuiltServerModuleArtifact> | undefined,\n file: string,\n source: string,\n kind: \"request\" | \"routeMetadata\" = \"request\",\n): BuiltServerModuleOutputLike | undefined {\n const artifact = serverModules?.get(file)?.[kind];\n\n return artifact !== undefined && artifact.sourceHash === memoizedHashText(source)\n ? artifact\n : undefined;\n}\n\nexport function prebuiltRouteLoaderModuleArtifact(\n serverModules: ReadonlyMap<string, BuiltServerModuleArtifact> | undefined,\n file: string,\n source: string,\n): BuiltServerModuleOutputLike | undefined {\n const artifact = serverModules?.get(file)?.loader;\n\n return artifact !== undefined && artifact.sourceHash === memoizedHashText(source)\n ? artifact\n : prebuiltRequestModuleArtifact(serverModules, file, source);\n}\n\nexport function prebuiltServerComponentModuleCode(\n artifact: BuiltServerModuleArtifact[\"string\"] | BuiltServerModuleArtifact[\"stream\"] | undefined,\n code: string,\n codeHash: string,\n): string | undefined {\n if (artifact === undefined) {\n return undefined;\n }\n\n if (!prebuiltServerModuleOutputMatches(artifact, code, codeHash)) {\n return undefined;\n }\n\n return artifact.bundleCode;\n}\n\nexport function prebuiltServerModuleOutputMatches(\n artifact: BuiltServerModuleOutputLike,\n code: string,\n codeHash: string,\n): boolean {\n return artifact.sourceHash === codeHash || artifact.code === code;\n}\n\nexport function importPolicyCacheKey(policy: AppRouterImportPolicy | undefined): string {\n if (policy === undefined) {\n return \"\";\n }\n\n return JSON.stringify({\n allowedPackages: [...(policy.allowedPackages ?? [])].sort(),\n allowedSourceDirs: [...(policy.allowedSourceDirs ?? [])].sort(),\n projectRoot: policy.projectRoot ?? \"\",\n });\n}\n\nfunction hashText(text: string): string {\n return createHash(\"sha256\").update(text).digest(\"hex\").slice(0, 16);\n}\n"]}
|
package/dist/routes.js
CHANGED
|
@@ -145,6 +145,9 @@ async function collectRouteFiles(directory, rootDirectory = directory) {
|
|
|
145
145
|
for (const entry of entries) {
|
|
146
146
|
const path = join(directory, entry.name);
|
|
147
147
|
if (entry.isDirectory()) {
|
|
148
|
+
if (shouldSkipRouteScanDirectory(entry.name)) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
148
151
|
files.push(...(await collectRouteFiles(path, rootDirectory)));
|
|
149
152
|
continue;
|
|
150
153
|
}
|
|
@@ -158,6 +161,9 @@ async function collectRouteFiles(directory, rootDirectory = directory) {
|
|
|
158
161
|
}
|
|
159
162
|
return files;
|
|
160
163
|
}
|
|
164
|
+
function shouldSkipRouteScanDirectory(name) {
|
|
165
|
+
return name === ".vite" || name === "node_modules";
|
|
166
|
+
}
|
|
161
167
|
function appFileConventionForRelativeFile(relativeFile) {
|
|
162
168
|
const parts = relativeFile.split(sep);
|
|
163
169
|
const filename = parts.at(-1);
|
package/dist/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\nimport { createNativeRouteMatcher } from \"./native-route-matcher.js\";\nimport {\n appFileConventionForRootFilename,\n type AppFileConvention,\n} from \"./file-conventions.js\";\n\nexport interface ScanAppRoutesOptions {\n appDir: string;\n}\n\nexport type AppRoute = AppAssetRoute | AppMetadataRoute | PageRoute | ServerRoute;\n\nexport interface PageRoute {\n kind: \"page\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport interface ServerRoute {\n kind: \"server\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport interface AppMetadataRoute {\n convention: AppFileConvention;\n kind: \"metadata\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport interface AppAssetRoute {\n convention: AppFileConvention;\n kind: \"asset\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport type RouteSegment =\n | { kind: \"static\"; value: string }\n | { kind: \"dynamic\"; name: string }\n | { kind: \"catch-all\"; name: string };\n\nexport interface MatchedRoute {\n route: AppRoute;\n params: Record<string, readonly string[] | string>;\n}\n\nexport interface RouteMatcher {\n match(pathname: string): MatchedRoute | undefined;\n}\n\nexport async function scanAppRoutes(\n options: ScanAppRoutesOptions,\n): Promise<AppRoute[]> {\n const files = await collectRouteFiles(options.appDir);\n\n return files\n .map((file): AppRoute => {\n const relativeFile = relative(options.appDir, file);\n const convention = appFileConventionForRelativeFile(relativeFile);\n if (convention !== undefined) {\n return {\n convention: convention.convention,\n file,\n kind: convention.kind,\n path: convention.path,\n segments: segmentsFromPath(convention.path),\n };\n }\n\n const kind = relativeFile.endsWith(\"route.ts\") ? \"server\" : \"page\";\n const routePath = routePathFromRelativeFile(relativeFile);\n const segments = segmentsFromPath(routePath);\n\n return { kind, path: routePath, file, segments };\n })\n .sort(compareRouteListEntries);\n}\n\nexport function matchRoute(\n routes: readonly AppRoute[],\n pathname: string,\n): MatchedRoute | undefined {\n return createRouteMatcher(routes).match(pathname);\n}\n\nexport function createRouteMatcher(routes: readonly AppRoute[]): RouteMatcher {\n const sortedRoutes = [...routes].sort(compareRoutes);\n const nativeMatcher = createNativeRouteMatcher(sortedRoutes);\n\n if (nativeMatcher !== undefined) {\n return nativeMatcher;\n }\n\n return {\n match(pathname) {\n return matchSortedRoutes(sortedRoutes, pathname);\n },\n };\n}\n\nfunction matchSortedRoutes(\n routes: readonly AppRoute[],\n pathname: string,\n): MatchedRoute | undefined {\n const normalized = normalizePath(pathname);\n const pathnameSegments = normalized === \"/\" ? [] : normalized.slice(1).split(\"/\");\n\n for (const route of routes) {\n const catchAllIndex = route.segments.findIndex(\n (segment) => segment.kind === \"catch-all\",\n );\n\n if (catchAllIndex === -1 && route.segments.length !== pathnameSegments.length) {\n continue;\n }\n\n if (catchAllIndex !== -1 && pathnameSegments.length < catchAllIndex + 1) {\n continue;\n }\n\n const params: Record<string, readonly string[] | string> = {};\n let matched = true;\n\n for (const [index, segment] of route.segments.entries()) {\n const value = pathnameSegments[index];\n\n if (value === undefined) {\n matched = false;\n break;\n }\n\n if (segment.kind === \"static\" && segment.value !== value) {\n matched = false;\n break;\n }\n\n if (segment.kind === \"dynamic\") {\n const decoded = safeDecodeURIComponent(value);\n if (decoded === undefined) {\n // Malformed percent-encoding -- treat as non-match rather than\n // letting URIError escape and produce a 500 (Issue 072).\n matched = false;\n break;\n }\n params[segment.name] = decoded;\n }\n\n if (segment.kind === \"catch-all\") {\n const suffixSegments = route.segments.slice(index + 1);\n const catchAllEnd = pathnameSegments.length - suffixSegments.length;\n\n if (catchAllEnd <= index) {\n matched = false;\n break;\n }\n\n const decodedParts: string[] = [];\n let decodeOk = true;\n for (const part of pathnameSegments.slice(index, catchAllEnd)) {\n const decoded = safeDecodeURIComponent(part);\n if (decoded === undefined) {\n decodeOk = false;\n break;\n }\n decodedParts.push(decoded);\n }\n if (!decodeOk) {\n matched = false;\n break;\n }\n params[segment.name] = decodedParts;\n\n for (let suffixIndex = 0; suffixIndex < suffixSegments.length; suffixIndex += 1) {\n const suffixSegment = suffixSegments[suffixIndex];\n const suffixValue = pathnameSegments[catchAllEnd + suffixIndex];\n\n if (suffixSegment === undefined || suffixValue === undefined) {\n matched = false;\n break;\n }\n\n if (suffixSegment.kind === \"static\" && suffixSegment.value !== suffixValue) {\n matched = false;\n break;\n }\n\n if (suffixSegment.kind === \"dynamic\") {\n const decoded = safeDecodeURIComponent(suffixValue);\n if (decoded === undefined) {\n matched = false;\n break;\n }\n params[suffixSegment.name] = decoded;\n }\n\n if (suffixSegment.kind === \"catch-all\") {\n matched = false;\n break;\n }\n }\n\n break;\n }\n }\n\n if (matched) {\n return { route, params };\n }\n }\n\n return undefined;\n}\n\n// Issue 072: attacker-supplied path segments / cookie values can include\n// malformed percent escapes (e.g. `%ZZ`, `%E0`). Catch the URIError so a\n// single bad byte cannot turn every request into a 500 + stack-leaking\n// response.\nexport function safeDecodeURIComponent(value: string): string | undefined {\n try {\n return decodeURIComponent(value);\n } catch {\n return undefined;\n }\n}\n\nasync function collectRouteFiles(directory: string, rootDirectory = directory): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const path = join(directory, entry.name);\n\n if (entry.isDirectory()) {\n files.push(...(await collectRouteFiles(path, rootDirectory)));\n continue;\n }\n\n if (\n entry.isFile() &&\n (entry.name === \"page.tsx\" ||\n entry.name === \"page.mreact.tsx\" ||\n entry.name === \"route.ts\" ||\n appFileConventionForRelativeFile(relative(rootDirectory, path)) !== undefined)\n ) {\n files.push(path);\n }\n }\n\n return files;\n}\n\nfunction appFileConventionForRelativeFile(\n relativeFile: string,\n): ReturnType<typeof appFileConventionForRootFilename> {\n const parts = relativeFile.split(sep);\n const filename = parts.at(-1);\n\n if (filename === undefined) {\n return undefined;\n }\n\n const convention = appFileConventionForRootFilename(filename);\n\n if (convention === undefined) {\n return undefined;\n }\n\n if (parts.length === 1) {\n return convention;\n }\n\n if (convention.kind !== \"metadata\" || convention.convention !== \"opengraph-image\") {\n return undefined;\n }\n\n const routeParts = parts\n .slice(0, -1)\n .filter((part) => !isRouteGroup(part))\n .map((part) => (part.startsWith(\"$\") ? `:${part.slice(1)}` : part));\n const conventionPath = convention.path.startsWith(\"/\")\n ? convention.path.slice(1)\n : convention.path;\n\n return {\n ...convention,\n path: normalizePath(`/${[...routeParts, conventionPath].join(\"/\")}`),\n };\n}\n\nfunction routePathFromRelativeFile(relativeFile: string): string {\n const parts = relativeFile.split(sep);\n const routeParts = parts\n .slice(0, -1)\n .filter((part) => !isRouteGroup(part))\n .map((part) => (part.startsWith(\"$\") ? `:${part.slice(1)}` : part));\n\n return normalizePath(`/${routeParts.join(\"/\")}`);\n}\n\nfunction segmentsFromPath(path: string): RouteSegment[] {\n return path === \"/\"\n ? []\n : path\n .slice(1)\n .split(\"/\")\n .map((part) =>\n part.startsWith(\":...\")\n ? { kind: \"catch-all\", name: part.slice(4) }\n : part.startsWith(\":\")\n ? { kind: \"dynamic\", name: part.slice(1) }\n : { kind: \"static\", value: part },\n );\n}\n\nfunction normalizePath(path: string): string {\n const withoutTrailing = path.length > 1 ? path.replace(/\\/+$/, \"\") : path;\n\n return withoutTrailing === \"\" ? \"/\" : withoutTrailing;\n}\n\nfunction isRouteGroup(part: string): boolean {\n return part.startsWith(\"(\") && part.endsWith(\")\");\n}\n\nfunction compareRoutes(a: AppRoute, b: AppRoute): number {\n const scoreDelta = routeScore(b) - routeScore(a);\n\n return scoreDelta === 0 ? a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind) : scoreDelta;\n}\n\nfunction compareRouteListEntries(a: AppRoute, b: AppRoute): number {\n return routeListKey(a.path).localeCompare(routeListKey(b.path)) ||\n a.kind.localeCompare(b.kind);\n}\n\nfunction routeListKey(path: string): string {\n return path === \"/\"\n ? \"\"\n : path.replaceAll(\"/:...\", \"/zzzz-catch-all-\").replaceAll(\"/:\", \"/zzzz-dynamic-\");\n}\n\nfunction routeScore(route: AppRoute): number {\n return route.segments.reduce((score, segment) => {\n if (segment.kind === \"static\") {\n return score + 100;\n }\n\n if (segment.kind === \"dynamic\") {\n return score + 10;\n }\n\n return score;\n }, route.segments.length);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\nimport { createNativeRouteMatcher } from \"./native-route-matcher.js\";\nimport {\n appFileConventionForRootFilename,\n type AppFileConvention,\n} from \"./file-conventions.js\";\n\nexport interface ScanAppRoutesOptions {\n appDir: string;\n}\n\nexport type AppRoute = AppAssetRoute | AppMetadataRoute | PageRoute | ServerRoute;\n\nexport interface PageRoute {\n kind: \"page\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport interface ServerRoute {\n kind: \"server\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport interface AppMetadataRoute {\n convention: AppFileConvention;\n kind: \"metadata\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport interface AppAssetRoute {\n convention: AppFileConvention;\n kind: \"asset\";\n path: string;\n file: string;\n segments: RouteSegment[];\n}\n\nexport type RouteSegment =\n | { kind: \"static\"; value: string }\n | { kind: \"dynamic\"; name: string }\n | { kind: \"catch-all\"; name: string };\n\nexport interface MatchedRoute {\n route: AppRoute;\n params: Record<string, readonly string[] | string>;\n}\n\nexport interface RouteMatcher {\n match(pathname: string): MatchedRoute | undefined;\n}\n\nexport async function scanAppRoutes(\n options: ScanAppRoutesOptions,\n): Promise<AppRoute[]> {\n const files = await collectRouteFiles(options.appDir);\n\n return files\n .map((file): AppRoute => {\n const relativeFile = relative(options.appDir, file);\n const convention = appFileConventionForRelativeFile(relativeFile);\n if (convention !== undefined) {\n return {\n convention: convention.convention,\n file,\n kind: convention.kind,\n path: convention.path,\n segments: segmentsFromPath(convention.path),\n };\n }\n\n const kind = relativeFile.endsWith(\"route.ts\") ? \"server\" : \"page\";\n const routePath = routePathFromRelativeFile(relativeFile);\n const segments = segmentsFromPath(routePath);\n\n return { kind, path: routePath, file, segments };\n })\n .sort(compareRouteListEntries);\n}\n\nexport function matchRoute(\n routes: readonly AppRoute[],\n pathname: string,\n): MatchedRoute | undefined {\n return createRouteMatcher(routes).match(pathname);\n}\n\nexport function createRouteMatcher(routes: readonly AppRoute[]): RouteMatcher {\n const sortedRoutes = [...routes].sort(compareRoutes);\n const nativeMatcher = createNativeRouteMatcher(sortedRoutes);\n\n if (nativeMatcher !== undefined) {\n return nativeMatcher;\n }\n\n return {\n match(pathname) {\n return matchSortedRoutes(sortedRoutes, pathname);\n },\n };\n}\n\nfunction matchSortedRoutes(\n routes: readonly AppRoute[],\n pathname: string,\n): MatchedRoute | undefined {\n const normalized = normalizePath(pathname);\n const pathnameSegments = normalized === \"/\" ? [] : normalized.slice(1).split(\"/\");\n\n for (const route of routes) {\n const catchAllIndex = route.segments.findIndex(\n (segment) => segment.kind === \"catch-all\",\n );\n\n if (catchAllIndex === -1 && route.segments.length !== pathnameSegments.length) {\n continue;\n }\n\n if (catchAllIndex !== -1 && pathnameSegments.length < catchAllIndex + 1) {\n continue;\n }\n\n const params: Record<string, readonly string[] | string> = {};\n let matched = true;\n\n for (const [index, segment] of route.segments.entries()) {\n const value = pathnameSegments[index];\n\n if (value === undefined) {\n matched = false;\n break;\n }\n\n if (segment.kind === \"static\" && segment.value !== value) {\n matched = false;\n break;\n }\n\n if (segment.kind === \"dynamic\") {\n const decoded = safeDecodeURIComponent(value);\n if (decoded === undefined) {\n // Malformed percent-encoding -- treat as non-match rather than\n // letting URIError escape and produce a 500 (Issue 072).\n matched = false;\n break;\n }\n params[segment.name] = decoded;\n }\n\n if (segment.kind === \"catch-all\") {\n const suffixSegments = route.segments.slice(index + 1);\n const catchAllEnd = pathnameSegments.length - suffixSegments.length;\n\n if (catchAllEnd <= index) {\n matched = false;\n break;\n }\n\n const decodedParts: string[] = [];\n let decodeOk = true;\n for (const part of pathnameSegments.slice(index, catchAllEnd)) {\n const decoded = safeDecodeURIComponent(part);\n if (decoded === undefined) {\n decodeOk = false;\n break;\n }\n decodedParts.push(decoded);\n }\n if (!decodeOk) {\n matched = false;\n break;\n }\n params[segment.name] = decodedParts;\n\n for (let suffixIndex = 0; suffixIndex < suffixSegments.length; suffixIndex += 1) {\n const suffixSegment = suffixSegments[suffixIndex];\n const suffixValue = pathnameSegments[catchAllEnd + suffixIndex];\n\n if (suffixSegment === undefined || suffixValue === undefined) {\n matched = false;\n break;\n }\n\n if (suffixSegment.kind === \"static\" && suffixSegment.value !== suffixValue) {\n matched = false;\n break;\n }\n\n if (suffixSegment.kind === \"dynamic\") {\n const decoded = safeDecodeURIComponent(suffixValue);\n if (decoded === undefined) {\n matched = false;\n break;\n }\n params[suffixSegment.name] = decoded;\n }\n\n if (suffixSegment.kind === \"catch-all\") {\n matched = false;\n break;\n }\n }\n\n break;\n }\n }\n\n if (matched) {\n return { route, params };\n }\n }\n\n return undefined;\n}\n\n// Issue 072: attacker-supplied path segments / cookie values can include\n// malformed percent escapes (e.g. `%ZZ`, `%E0`). Catch the URIError so a\n// single bad byte cannot turn every request into a 500 + stack-leaking\n// response.\nexport function safeDecodeURIComponent(value: string): string | undefined {\n try {\n return decodeURIComponent(value);\n } catch {\n return undefined;\n }\n}\n\nasync function collectRouteFiles(directory: string, rootDirectory = directory): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const files: string[] = [];\n\n for (const entry of entries) {\n const path = join(directory, entry.name);\n\n if (entry.isDirectory()) {\n if (shouldSkipRouteScanDirectory(entry.name)) {\n continue;\n }\n\n files.push(...(await collectRouteFiles(path, rootDirectory)));\n continue;\n }\n\n if (\n entry.isFile() &&\n (entry.name === \"page.tsx\" ||\n entry.name === \"page.mreact.tsx\" ||\n entry.name === \"route.ts\" ||\n appFileConventionForRelativeFile(relative(rootDirectory, path)) !== undefined)\n ) {\n files.push(path);\n }\n }\n\n return files;\n}\n\nfunction shouldSkipRouteScanDirectory(name: string): boolean {\n return name === \".vite\" || name === \"node_modules\";\n}\n\nfunction appFileConventionForRelativeFile(\n relativeFile: string,\n): ReturnType<typeof appFileConventionForRootFilename> {\n const parts = relativeFile.split(sep);\n const filename = parts.at(-1);\n\n if (filename === undefined) {\n return undefined;\n }\n\n const convention = appFileConventionForRootFilename(filename);\n\n if (convention === undefined) {\n return undefined;\n }\n\n if (parts.length === 1) {\n return convention;\n }\n\n if (convention.kind !== \"metadata\" || convention.convention !== \"opengraph-image\") {\n return undefined;\n }\n\n const routeParts = parts\n .slice(0, -1)\n .filter((part) => !isRouteGroup(part))\n .map((part) => (part.startsWith(\"$\") ? `:${part.slice(1)}` : part));\n const conventionPath = convention.path.startsWith(\"/\")\n ? convention.path.slice(1)\n : convention.path;\n\n return {\n ...convention,\n path: normalizePath(`/${[...routeParts, conventionPath].join(\"/\")}`),\n };\n}\n\nfunction routePathFromRelativeFile(relativeFile: string): string {\n const parts = relativeFile.split(sep);\n const routeParts = parts\n .slice(0, -1)\n .filter((part) => !isRouteGroup(part))\n .map((part) => (part.startsWith(\"$\") ? `:${part.slice(1)}` : part));\n\n return normalizePath(`/${routeParts.join(\"/\")}`);\n}\n\nfunction segmentsFromPath(path: string): RouteSegment[] {\n return path === \"/\"\n ? []\n : path\n .slice(1)\n .split(\"/\")\n .map((part) =>\n part.startsWith(\":...\")\n ? { kind: \"catch-all\", name: part.slice(4) }\n : part.startsWith(\":\")\n ? { kind: \"dynamic\", name: part.slice(1) }\n : { kind: \"static\", value: part },\n );\n}\n\nfunction normalizePath(path: string): string {\n const withoutTrailing = path.length > 1 ? path.replace(/\\/+$/, \"\") : path;\n\n return withoutTrailing === \"\" ? \"/\" : withoutTrailing;\n}\n\nfunction isRouteGroup(part: string): boolean {\n return part.startsWith(\"(\") && part.endsWith(\")\");\n}\n\nfunction compareRoutes(a: AppRoute, b: AppRoute): number {\n const scoreDelta = routeScore(b) - routeScore(a);\n\n return scoreDelta === 0 ? a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind) : scoreDelta;\n}\n\nfunction compareRouteListEntries(a: AppRoute, b: AppRoute): number {\n return routeListKey(a.path).localeCompare(routeListKey(b.path)) ||\n a.kind.localeCompare(b.kind);\n}\n\nfunction routeListKey(path: string): string {\n return path === \"/\"\n ? \"\"\n : path.replaceAll(\"/:...\", \"/zzzz-catch-all-\").replaceAll(\"/:\", \"/zzzz-dynamic-\");\n}\n\nfunction routeScore(route: AppRoute): number {\n return route.segments.reduce((score, segment) => {\n if (segment.kind === \"static\") {\n return score + 100;\n }\n\n if (segment.kind === \"dynamic\") {\n return score + 10;\n }\n\n return score;\n }, route.segments.length);\n}\n"]}
|
package/dist/serve.d.ts
CHANGED
|
@@ -32,10 +32,22 @@ export interface RenderBuiltAppRequestOptions {
|
|
|
32
32
|
request: Request;
|
|
33
33
|
routeCache?: AppRouterCache | undefined;
|
|
34
34
|
runtimeDir?: string | undefined;
|
|
35
|
+
immutableRuntime?: boolean | undefined;
|
|
35
36
|
serverActions?: AppRouterServerActionOptions | undefined;
|
|
36
37
|
sinkStrategy?: ResponseSinkStrategy;
|
|
37
38
|
preload?: AppRouterRenderPreload | undefined;
|
|
38
39
|
}
|
|
40
|
+
export interface BuiltRequestRuntimeOptions {
|
|
41
|
+
immutableRuntime?: boolean | undefined;
|
|
42
|
+
importPolicy?: AppRouterImportPolicy | undefined;
|
|
43
|
+
outDir: string;
|
|
44
|
+
runtimeDir?: string | undefined;
|
|
45
|
+
}
|
|
46
|
+
export type BuiltRequestRuntimeRenderOptions = Omit<RenderBuiltAppRequestOptions, "immutableRuntime" | "outDir" | "request" | "runtimeDir">;
|
|
47
|
+
export interface BuiltRequestRuntime {
|
|
48
|
+
preload(preload?: BuiltAppRuntimePreloadStrategy | undefined): Promise<void>;
|
|
49
|
+
render(request: Request, options?: BuiltRequestRuntimeRenderOptions | undefined): Promise<Response>;
|
|
50
|
+
}
|
|
39
51
|
export type BuiltAppRuntimePreloadMode = "all" | "hot-route-requests" | "hot-routes" | "middleware" | "none";
|
|
40
52
|
export interface BuiltAppRuntimePreloadStrategy {
|
|
41
53
|
mode: BuiltAppRuntimePreloadMode;
|
|
@@ -78,6 +90,7 @@ export interface AppRouterPrerenderStore {
|
|
|
78
90
|
set(path: string, entry: BuiltPrerenderedRoute): void | Promise<void>;
|
|
79
91
|
withLock?<T>(path: string, task: () => Promise<T>): Promise<T>;
|
|
80
92
|
}
|
|
93
|
+
export declare function createBuiltRequestRuntime(options: BuiltRequestRuntimeOptions): Promise<BuiltRequestRuntime>;
|
|
81
94
|
export declare function preloadBuiltAppRuntime(options: {
|
|
82
95
|
importPolicy?: AppRouterImportPolicy | undefined;
|
|
83
96
|
outDir: string;
|
package/dist/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAItD,OAAO,KAAK,EACV,qBAAqB,EAGtB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAE3B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAOL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
package/dist/serve.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createRouteMatcher } from "./routes.js";
|
|
|
6
6
|
import { preloadBuiltRequestModules, renderAppRequest, resolveAppRouterMiddleware, } from "./render.js";
|
|
7
7
|
import { bytesResponse, htmlResponse, nodeRequestToWebRequest, sendResponse } from "./http.js";
|
|
8
8
|
import { emitRouterLog, logDurationMs, logError, logNow, nodeRequestPath, requestLogFields, } from "./logger.js";
|
|
9
|
+
import { builtAppRuntimePreloadPlan } from "./preload-policy.js";
|
|
9
10
|
import { routeShellCandidates } from "./route-shells.js";
|
|
10
11
|
import { normalizeRoutePath } from "./route-path.js";
|
|
11
12
|
const builtRuntimeCache = new Map();
|
|
@@ -30,42 +31,73 @@ export function warnIfImplicitHostTrust(options) {
|
|
|
30
31
|
warnedImplicitHostTrust = true;
|
|
31
32
|
console.error("[mreact] Host header trust is implicit because neither allowedHosts nor hostPolicy is configured. Set allowedHosts for public deployments, hostPolicy: \"strict\" to reject unlisted Host headers, or hostPolicy: \"trusted-proxy\" when a trusted reverse proxy normalizes Host.");
|
|
32
33
|
}
|
|
34
|
+
export async function createBuiltRequestRuntime(options) {
|
|
35
|
+
const runtime = await readBuiltRuntime({
|
|
36
|
+
immutable: options.immutableRuntime,
|
|
37
|
+
outDir: options.outDir,
|
|
38
|
+
runtimeDir: options.runtimeDir,
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
preload(preload) {
|
|
42
|
+
return preloadBuiltAppRuntimeWithRuntime({
|
|
43
|
+
importPolicy: options.importPolicy,
|
|
44
|
+
preload,
|
|
45
|
+
runtime,
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
async render(request, renderOptions = {}) {
|
|
49
|
+
const response = await renderBuiltAppRequestWithRuntime({
|
|
50
|
+
...renderOptions,
|
|
51
|
+
importPolicy: renderOptions.importPolicy ?? options.importPolicy,
|
|
52
|
+
outDir: options.outDir,
|
|
53
|
+
request,
|
|
54
|
+
runtime,
|
|
55
|
+
});
|
|
56
|
+
return applyBuiltAppResponseHook(response, {
|
|
57
|
+
onResponse: renderOptions.onResponse,
|
|
58
|
+
request,
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
33
63
|
export async function preloadBuiltAppRuntime(options) {
|
|
34
64
|
const runtime = await readBuiltRuntime({
|
|
35
65
|
outDir: options.outDir,
|
|
36
66
|
runtimeDir: options.runtimeDir,
|
|
37
67
|
});
|
|
38
|
-
|
|
39
|
-
|
|
68
|
+
await preloadBuiltAppRuntimeWithRuntime({
|
|
69
|
+
importPolicy: options.importPolicy,
|
|
70
|
+
preload: options.preload,
|
|
71
|
+
runtime,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function preloadBuiltAppRuntimeWithRuntime(options) {
|
|
75
|
+
const plan = builtAppRuntimePreloadPlan(options.preload);
|
|
76
|
+
if (!plan.shouldPreload) {
|
|
40
77
|
return;
|
|
41
78
|
}
|
|
42
|
-
const routes = builtRuntimePreloadRoutes(runtime,
|
|
43
|
-
if (
|
|
44
|
-
await loadBuiltServerModuleArtifacts(runtime, allBuiltServerModuleFiles(runtime), "all");
|
|
79
|
+
const routes = builtRuntimePreloadRoutes(options.runtime, plan);
|
|
80
|
+
if (plan.loadAllArtifacts) {
|
|
81
|
+
await loadBuiltServerModuleArtifacts(options.runtime, allBuiltServerModuleFiles(options.runtime), "all");
|
|
45
82
|
}
|
|
46
83
|
else {
|
|
47
|
-
await loadBuiltServerModuleArtifactsForRequest(runtime, undefined,
|
|
48
|
-
includeRender: strategy.mode !== "hot-route-requests",
|
|
49
|
-
});
|
|
84
|
+
await loadBuiltServerModuleArtifactsForRequest(options.runtime, undefined, plan.middlewareArtifacts);
|
|
50
85
|
for (const route of routes) {
|
|
51
|
-
await loadBuiltServerModuleArtifactsForRequest(runtime, route.file,
|
|
52
|
-
includeShells: strategy.mode !== "hot-route-requests",
|
|
53
|
-
includeRender: strategy.mode !== "hot-route-requests",
|
|
54
|
-
});
|
|
86
|
+
await loadBuiltServerModuleArtifactsForRequest(options.runtime, route.file, plan.routeArtifacts);
|
|
55
87
|
}
|
|
56
88
|
}
|
|
57
89
|
await preloadBuiltRequestModules({
|
|
58
|
-
appDir: runtime.appDir,
|
|
90
|
+
appDir: options.runtime.appDir,
|
|
59
91
|
importPolicy: {
|
|
60
92
|
...options.importPolicy,
|
|
61
|
-
allowedSourceDirs: runtime.allowedSourceDirs,
|
|
62
|
-
projectRoot: runtime.projectRoot,
|
|
93
|
+
allowedSourceDirs: options.runtime.allowedSourceDirs,
|
|
94
|
+
projectRoot: options.runtime.projectRoot,
|
|
63
95
|
},
|
|
64
96
|
routes,
|
|
65
|
-
serverModules: runtime.serverModules,
|
|
66
|
-
serverModuleCacheVersion: runtime.serverModuleCacheVersion,
|
|
67
|
-
serverSourceFiles: runtime.serverSourceFiles,
|
|
68
|
-
includeRenderModules:
|
|
97
|
+
serverModules: options.runtime.serverModules,
|
|
98
|
+
serverModuleCacheVersion: options.runtime.serverModuleCacheVersion,
|
|
99
|
+
serverSourceFiles: options.runtime.serverSourceFiles,
|
|
100
|
+
includeRenderModules: plan.includeRenderModules,
|
|
69
101
|
});
|
|
70
102
|
}
|
|
71
103
|
function builtRuntimePreloadRoutes(runtime, strategy) {
|
|
@@ -89,6 +121,7 @@ export async function renderBuiltAppRequest(options) {
|
|
|
89
121
|
...options,
|
|
90
122
|
runtime: await readBuiltRuntime({
|
|
91
123
|
outDir: options.outDir,
|
|
124
|
+
immutable: options.immutableRuntime,
|
|
92
125
|
runtimeDir: options.runtimeDir,
|
|
93
126
|
}),
|
|
94
127
|
});
|
|
@@ -222,7 +255,10 @@ async function materializeResponseAsBuffer(response) {
|
|
|
222
255
|
}
|
|
223
256
|
export async function startServer(options) {
|
|
224
257
|
warnIfImplicitHostTrust(options);
|
|
225
|
-
const runtime = await
|
|
258
|
+
const runtime = await createBuiltRequestRuntime({
|
|
259
|
+
importPolicy: options.importPolicy,
|
|
260
|
+
outDir: options.outDir,
|
|
261
|
+
});
|
|
226
262
|
const server = createServer(async (incoming, outgoing) => {
|
|
227
263
|
const startedAt = logNow();
|
|
228
264
|
const fallbackRequestFields = {
|
|
@@ -245,19 +281,15 @@ export async function startServer(options) {
|
|
|
245
281
|
...logFields,
|
|
246
282
|
type: "router:request:start",
|
|
247
283
|
});
|
|
248
|
-
const response = await
|
|
249
|
-
outDir: options.outDir,
|
|
250
|
-
importPolicy: options.importPolicy,
|
|
284
|
+
const response = await runtime.render(request, {
|
|
251
285
|
instrumentation: options.instrumentation,
|
|
252
286
|
logger: options.logger,
|
|
253
287
|
onResponse: options.onResponse,
|
|
254
288
|
prerenderStore: options.prerenderStore,
|
|
255
|
-
request,
|
|
256
289
|
routeCache: options.routeCache,
|
|
257
|
-
runtime,
|
|
258
290
|
serverActions: options.serverActions,
|
|
259
291
|
...(options.sinkStrategy === undefined ? {} : { sinkStrategy: options.sinkStrategy }),
|
|
260
|
-
})
|
|
292
|
+
});
|
|
261
293
|
emitRouterLog(options.logger, "info", {
|
|
262
294
|
...logFields,
|
|
263
295
|
durationMs: logDurationMs(startedAt),
|
|
@@ -359,12 +391,15 @@ async function readBuiltPublicAsset(outDir, pathname) {
|
|
|
359
391
|
async function readBuiltRuntime(options) {
|
|
360
392
|
const outDir = options.outDir;
|
|
361
393
|
const runtimeDir = options.runtimeDir ?? join(outDir, "server", "runtime");
|
|
394
|
+
const cacheKey = `${outDir}\0${runtimeDir}`;
|
|
395
|
+
const cached = builtRuntimeCache.get(cacheKey);
|
|
396
|
+
if (options.immutable === true && cached !== undefined) {
|
|
397
|
+
return cached.runtime;
|
|
398
|
+
}
|
|
362
399
|
const [serverManifestText, clientManifestText] = await Promise.all([
|
|
363
400
|
readFile(join(outDir, "server", "manifest.json"), "utf8"),
|
|
364
401
|
readFile(join(outDir, "client", "manifest.json"), "utf8"),
|
|
365
402
|
]);
|
|
366
|
-
const cacheKey = `${outDir}\0${runtimeDir}`;
|
|
367
|
-
const cached = builtRuntimeCache.get(cacheKey);
|
|
368
403
|
if (cached !== undefined &&
|
|
369
404
|
cached.serverManifestText === serverManifestText &&
|
|
370
405
|
cached.clientManifestText === clientManifestText) {
|