@reckona/mreact-router 0.0.201 → 0.0.203
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 +6 -3
- package/dist/actions.d.ts +2 -3
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +61 -41
- package/dist/actions.js.map +1 -1
- package/dist/adapters/cloudflare.d.ts +3 -1
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +74 -11
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/node.d.ts +7 -0
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +7 -1
- package/dist/adapters/node.js.map +1 -1
- package/dist/adapters/static.d.ts.map +1 -1
- package/dist/adapters/static.js +14 -3
- package/dist/adapters/static.js.map +1 -1
- package/dist/build.d.ts +5 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +137 -14
- package/dist/build.js.map +1 -1
- package/dist/built-runtime.d.ts +4 -1
- package/dist/built-runtime.d.ts.map +1 -1
- package/dist/built-runtime.js.map +1 -1
- package/dist/cache.d.ts +27 -1
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +83 -16
- package/dist/cache.js.map +1 -1
- package/dist/cli-options.d.ts +7 -0
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +27 -2
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +5 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -2
- package/dist/client.js.map +1 -1
- package/dist/navigation-marker.d.ts +2 -0
- package/dist/navigation-marker.d.ts.map +1 -0
- package/dist/navigation-marker.js +294 -0
- package/dist/navigation-marker.js.map +1 -0
- package/dist/navigation-runtime.d.ts +1 -1
- package/dist/navigation-runtime.d.ts.map +1 -1
- package/dist/navigation-runtime.js +1 -1
- package/dist/navigation-runtime.js.map +1 -1
- package/dist/node-server.d.ts +6 -0
- package/dist/node-server.d.ts.map +1 -1
- package/dist/node-server.js +19 -1
- package/dist/node-server.js.map +1 -1
- package/dist/prerender-entry.d.ts +7 -0
- package/dist/prerender-entry.d.ts.map +1 -0
- package/dist/prerender-entry.js +99 -0
- package/dist/prerender-entry.js.map +1 -0
- package/dist/render.d.ts +20 -1
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +190 -110
- package/dist/render.js.map +1 -1
- package/dist/request-header-tracking.d.ts +44 -0
- package/dist/request-header-tracking.d.ts.map +1 -0
- package/dist/request-header-tracking.js +116 -0
- package/dist/request-header-tracking.js.map +1 -0
- package/dist/route-source.d.ts +16 -0
- package/dist/route-source.d.ts.map +1 -1
- package/dist/route-source.js +55 -1
- package/dist/route-source.js.map +1 -1
- package/dist/security-headers.d.ts +16 -0
- package/dist/security-headers.d.ts.map +1 -1
- package/dist/security-headers.js +37 -0
- package/dist/security-headers.js.map +1 -1
- package/dist/serve.d.ts +10 -0
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +132 -42
- package/dist/serve.js.map +1 -1
- package/package.json +11 -11
- package/src/actions.ts +72 -56
- package/src/adapters/cloudflare.ts +118 -16
- package/src/adapters/node.ts +14 -1
- package/src/adapters/static.ts +18 -5
- package/src/build.ts +176 -12
- package/src/built-runtime.ts +2 -2
- package/src/cache.ts +127 -15
- package/src/cli-options.ts +39 -2
- package/src/cli.ts +7 -1
- package/src/client.ts +15 -2
- package/src/navigation-marker.ts +353 -0
- package/src/navigation-runtime.ts +1 -0
- package/src/node-server.ts +27 -1
- package/src/prerender-entry.ts +129 -0
- package/src/render.ts +267 -121
- package/src/request-header-tracking.ts +161 -0
- package/src/route-source.ts +71 -0
- package/src/security-headers.ts +41 -0
- package/src/serve.ts +188 -48
package/dist/adapters/static.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join, resolve, sep } from "node:path";
|
|
3
|
+
import { isCurrentPrerenderedRoute } from "../prerender-entry.js";
|
|
3
4
|
/**
|
|
4
5
|
* Exports prerendered app-router routes and client assets to a static filesystem directory.
|
|
5
6
|
*
|
|
@@ -10,13 +11,23 @@ export async function exportStaticApp(options) {
|
|
|
10
11
|
const clientManifest = JSON.parse(await readFile(join(options.outDir, "client", "manifest.json"), "utf8"));
|
|
11
12
|
const prerenderedRoutes = manifest.prerenderedRoutes ?? {};
|
|
12
13
|
const routes = [...(options.paths ?? Object.keys(prerenderedRoutes))].sort();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
for (const route of routes) {
|
|
14
|
+
const entries = routes.map((route) => {
|
|
15
|
+
routeToHtmlFile(options.exportDir, route);
|
|
16
16
|
const entry = prerenderedRoutes[route];
|
|
17
17
|
if (entry === undefined) {
|
|
18
18
|
throw new Error(`Cannot export non-prerendered route: ${route}`);
|
|
19
19
|
}
|
|
20
|
+
if (!isCurrentPrerenderedRoute(entry)) {
|
|
21
|
+
throw new Error(`Cannot export invalid prerendered route: ${route}`);
|
|
22
|
+
}
|
|
23
|
+
if (entry.status < 200 || entry.status >= 300) {
|
|
24
|
+
throw new Error(`Cannot export route ${route} with status ${entry.status}.`);
|
|
25
|
+
}
|
|
26
|
+
return [route, entry];
|
|
27
|
+
});
|
|
28
|
+
await rm(options.exportDir, { force: true, recursive: true });
|
|
29
|
+
await mkdir(options.exportDir, { recursive: true });
|
|
30
|
+
for (const [route, entry] of entries) {
|
|
20
31
|
await writePrerenderedRoute(options.exportDir, route, entry);
|
|
21
32
|
}
|
|
22
33
|
await cp(join(options.outDir, "client"), join(options.exportDir, "_mreact", "client"), {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/adapters/static.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"static.js","sourceRoot":"","sources":["../../src/adapters/static.ts"],"names":[],"mappings":"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","sourcesContent":["import { cp, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport type { BuiltPrerenderedRoute, BuiltServerManifest } from \"../build.js\";\nimport { isCurrentPrerenderedRoute } from \"../prerender-entry.js\";\n\n/**\n * Configures static export from a built app-router output directory.\n */\nexport interface StaticExportOptions {\n exportDir: string;\n outDir: string;\n paths?: readonly string[] | undefined;\n}\n\n/**\n * Lists the routes written by a static app-router export.\n */\nexport interface StaticExportResult {\n routes: string[];\n}\n\n/**\n * Exports prerendered app-router routes and client assets to a static filesystem directory.\n *\n * Only routes present in the built prerender manifest can be exported; the export directory is removed and recreated, and route paths are checked to prevent traversal outside it.\n */\nexport async function exportStaticApp(options: StaticExportOptions): Promise<StaticExportResult> {\n const manifest = JSON.parse(\n await readFile(join(options.outDir, \"server\", \"manifest.json\"), \"utf8\"),\n ) as BuiltServerManifest;\n const clientManifest = JSON.parse(\n await readFile(join(options.outDir, \"client\", \"manifest.json\"), \"utf8\"),\n ) as { publicAssets?: readonly string[] };\n const prerenderedRoutes = manifest.prerenderedRoutes ?? {};\n const routes = [...(options.paths ?? Object.keys(prerenderedRoutes))].sort();\n const entries = routes.map((route): readonly [string, BuiltPrerenderedRoute] => {\n routeToHtmlFile(options.exportDir, route);\n const entry = prerenderedRoutes[route];\n\n if (entry === undefined) {\n throw new Error(`Cannot export non-prerendered route: ${route}`);\n }\n\n if (!isCurrentPrerenderedRoute(entry)) {\n throw new Error(`Cannot export invalid prerendered route: ${route}`);\n }\n\n if (entry.status < 200 || entry.status >= 300) {\n throw new Error(`Cannot export route ${route} with status ${entry.status}.`);\n }\n\n return [route, entry];\n });\n\n await rm(options.exportDir, { force: true, recursive: true });\n await mkdir(options.exportDir, { recursive: true });\n\n for (const [route, entry] of entries) {\n await writePrerenderedRoute(options.exportDir, route, entry);\n }\n\n await cp(join(options.outDir, \"client\"), join(options.exportDir, \"_mreact\", \"client\"), {\n recursive: true,\n });\n await copyPublicAssetsToExportRoot(\n join(options.outDir, \"client\"),\n options.exportDir,\n clientManifest.publicAssets ?? [],\n );\n\n return { routes };\n}\n\nasync function copyPublicAssetsToExportRoot(\n clientDir: string,\n exportDir: string,\n publicAssets: readonly string[],\n): Promise<void> {\n for (const asset of publicAssets) {\n if (\n !asset.startsWith(\"/\") ||\n asset.startsWith(\"//\") ||\n asset.includes(\"..\") ||\n asset === \"/_mreact\" ||\n asset.startsWith(\"/_mreact/\")\n ) {\n continue;\n }\n\n const relativeAsset = asset.slice(1);\n const destination = join(exportDir, relativeAsset);\n await mkdir(dirname(destination), { recursive: true });\n await cp(join(clientDir, relativeAsset), destination, { recursive: true });\n }\n}\n\nasync function writePrerenderedRoute(\n exportDir: string,\n route: string,\n entry: BuiltPrerenderedRoute,\n): Promise<void> {\n if (entry.status < 200 || entry.status >= 300) {\n throw new Error(`Cannot export route ${route} with status ${entry.status}.`);\n }\n\n const file = routeToHtmlFile(exportDir, route);\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, entry.html);\n}\n\nfunction routeToHtmlFile(exportDir: string, route: string): string {\n const pathname = route.split(\"?\")[0] ?? \"/\";\n const normalized = pathname.startsWith(\"/\") ? pathname.slice(1) : pathname;\n const relativeFile = normalized === \"\" ? \"index.html\" : join(normalized, \"index.html\");\n const root = resolve(exportDir);\n const file = resolve(root, relativeFile);\n\n if (file !== root && !file.startsWith(`${root}${sep}`)) {\n throw new Error(`unsafe static export route: ${route}`);\n }\n\n return file;\n}\n"]}
|
package/dist/build.d.ts
CHANGED
|
@@ -159,6 +159,7 @@ export interface BuiltRouteSourceAnalysisSummary {
|
|
|
159
159
|
routePath: string;
|
|
160
160
|
sourceHash: string;
|
|
161
161
|
streamRoute: boolean;
|
|
162
|
+
usesRequestInput?: boolean | undefined;
|
|
162
163
|
usesRuntimeCacheControl: boolean;
|
|
163
164
|
}
|
|
164
165
|
export interface BuiltServerModuleOutput {
|
|
@@ -171,7 +172,11 @@ export interface BuiltServerModuleOutput {
|
|
|
171
172
|
export interface BuiltPrerenderedRoute {
|
|
172
173
|
headers: Record<string, string>;
|
|
173
174
|
html: string;
|
|
175
|
+
navigationHtml?: string | undefined;
|
|
176
|
+
/** Identifies entries that satisfy the complete current prerender contract. */
|
|
177
|
+
schemaVersion?: 4 | undefined;
|
|
174
178
|
status: number;
|
|
179
|
+
strictTransportSecurity?: string | undefined;
|
|
175
180
|
}
|
|
176
181
|
/**
|
|
177
182
|
* Builds an app-router project into server, client, and optional deployment-target artifacts.
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAgBjE,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/build.js
CHANGED
|
@@ -9,20 +9,21 @@ import { collectStaticImportReferences, collectTopLevelValueExportNames, formatD
|
|
|
9
9
|
import { transformCompilerModuleContext } from "@reckona/mreact-compiler/internal";
|
|
10
10
|
import { compilerModuleContextForSource, collectClientRouteReferences, createClientRouteInferenceCache, detectAnchorElementUsage, detectClientNavigationOverride, formatClientRouteInferenceDiagnostic, inferClientRouteModule, navigationRuntimeLinkDisabledDiagnostic, resolveNavigationRuntime, } from "./client-route-inference.js";
|
|
11
11
|
import { createBoundaryReport } from "./boundaries.js";
|
|
12
|
-
import { buildClientRouteBatchOutput, buildNavigationRuntimeBundle, clientScriptForPath, routeIdForPath, } from "./navigation-runtime.js";
|
|
12
|
+
import { buildClientRouteBatchOutput, buildNavigationRuntimeBundle, clientScriptForPath, routeIdForPath, routeMarkerParts, } from "./navigation-runtime.js";
|
|
13
13
|
import { COMPAT_VENDOR_PLACEHOLDER_PREFIX, bundleAppRouterSourceModule, fileImportMetaUrlPlugin, importAppRouterSourceModule, resolveCompatVendorEntryFiles, sourceReferencesCompatVendorSpecifier, } from "./module-runner.js";
|
|
14
14
|
import { compileRouteMatcherArtifact, scanAppRoutes } from "./routes.js";
|
|
15
15
|
import { appFileConventionForRootFilename } from "./file-conventions.js";
|
|
16
16
|
import { resolveAppRouterProjectOptions, resolveBuildTargets, } from "./config.js";
|
|
17
17
|
import { routeCachePolicyFromSource } from "./cache.js";
|
|
18
|
-
import { bundleMiddlewareModuleCode, renderAppRequest } from "./render.js";
|
|
18
|
+
import { bundleMiddlewareModuleCode, prerenderVariantMarkerParts, renderAppRequest, } from "./render.js";
|
|
19
19
|
import { createAppRouterImportPolicyPlugin } from "./import-policy.js";
|
|
20
|
-
import { hasGenerateStaticParamsExport, hasLoaderExport, hasPrerenderExport, isStreamRouteSource, routeClosureMayUseAwaitBoundary, stripRouteBuildExports, stripRouteClientOnlyExports, stripRouteClientSource, stripRouteLoaderOnlyExports, stripRouteMetadataOnlyExports, stripRouteRequestOnlyExports, } from "./route-source.js";
|
|
20
|
+
import { hasGenerateStaticParamsExport, hasLoaderExport, hasPrerenderExport, isStreamRouteSource, routeClosureMayUseAwaitBoundary, routeClosureMayUseRequestInput, stripRouteBuildExports, stripRouteClientOnlyExports, stripRouteClientSource, stripRouteLoaderOnlyExports, stripRouteMetadataOnlyExports, stripRouteRequestOnlyExports, } from "./route-source.js";
|
|
21
21
|
import { bundleRouterModule, bundleRouterModules, } from "./bundle-pipeline.js";
|
|
22
22
|
import { collectRouteCssFilesFromSources, collectSpecialBoundaryFiles } from "./route-styles.js";
|
|
23
23
|
import { existingRouteShellCandidates } from "./route-shells.js";
|
|
24
24
|
import { sourceModuleCandidates } from "./source-modules.js";
|
|
25
25
|
import { collectBuildInferredServerActions } from "./server-action-inference.js";
|
|
26
|
+
import { isVisitorDependentResponse, PRERENDERED_ROUTE_SCHEMA_VERSION, storedPrerenderedRouteHeaders, } from "./prerender-entry.js";
|
|
26
27
|
import { prepareRouteServerActionPlaceholders } from "./actions.js";
|
|
27
28
|
import { viteDefineCacheKey, vitePluginsCacheKey } from "./vite-plugin-cache-key.js";
|
|
28
29
|
import { workspacePackageFile } from "./workspace-packages.js";
|
|
@@ -799,6 +800,14 @@ async function analyzeBuildRouteSources(options) {
|
|
|
799
800
|
projectRoot: options.projectRoot,
|
|
800
801
|
source,
|
|
801
802
|
}),
|
|
803
|
+
usesRequestInput: await buildRouteUsesRequestInput({
|
|
804
|
+
file,
|
|
805
|
+
files: options.files,
|
|
806
|
+
project: options.project,
|
|
807
|
+
projectRoot: options.projectRoot,
|
|
808
|
+
routeFile: route.file,
|
|
809
|
+
source,
|
|
810
|
+
}),
|
|
802
811
|
},
|
|
803
812
|
];
|
|
804
813
|
});
|
|
@@ -822,6 +831,23 @@ async function analyzeBuildRouteSources(options) {
|
|
|
822
831
|
byRouteFile,
|
|
823
832
|
};
|
|
824
833
|
}
|
|
834
|
+
async function buildRouteUsesRequestInput(options) {
|
|
835
|
+
const shells = await existingRouteShellCandidates(options.project.routesDir, options.routeFile, async (shellFile) => options.files[relative(options.projectRoot, shellFile).split(sep).join("/")] !== undefined);
|
|
836
|
+
const sources = [
|
|
837
|
+
{ file: options.file, source: options.source },
|
|
838
|
+
...shells.flatMap((shell) => {
|
|
839
|
+
const file = relative(options.projectRoot, shell.file).split(sep).join("/");
|
|
840
|
+
const source = options.files[file];
|
|
841
|
+
return source === undefined ? [] : [{ file, source }];
|
|
842
|
+
}),
|
|
843
|
+
];
|
|
844
|
+
return sources.some((entry) => routeClosureMayUseRequestInput({
|
|
845
|
+
filename: entry.file,
|
|
846
|
+
files: options.files,
|
|
847
|
+
projectRoot: options.projectRoot,
|
|
848
|
+
source: entry.source,
|
|
849
|
+
}));
|
|
850
|
+
}
|
|
825
851
|
function analyzeBuildSource(source, filename) {
|
|
826
852
|
const cachePolicy = routeCachePolicyFromSource(source);
|
|
827
853
|
const sourceHash = hashText(source);
|
|
@@ -1577,7 +1603,11 @@ async function prerenderStaticRoutes(options) {
|
|
|
1577
1603
|
}
|
|
1578
1604
|
const entries = [];
|
|
1579
1605
|
for (const pathname of await prerenderPathsForRoute(route, analysis, options.vitePlugins)) {
|
|
1580
|
-
const
|
|
1606
|
+
const renderSignals = {
|
|
1607
|
+
headerDependent: () => true,
|
|
1608
|
+
strictTransportSecurity: () => undefined,
|
|
1609
|
+
};
|
|
1610
|
+
const renderOptions = {
|
|
1581
1611
|
appDir: options.appDir,
|
|
1582
1612
|
assetBaseUrl: options.assetBaseUrl,
|
|
1583
1613
|
clientScripts,
|
|
@@ -1585,21 +1615,46 @@ async function prerenderStaticRoutes(options) {
|
|
|
1585
1615
|
define: options.define,
|
|
1586
1616
|
importPolicy,
|
|
1587
1617
|
navigationScripts,
|
|
1588
|
-
request: new Request(`http://mreact.local${pathname}
|
|
1618
|
+
request: new Request(`http://mreact.local${pathname}`, analysis.clientRoute
|
|
1619
|
+
? undefined
|
|
1620
|
+
: { headers: { "x-mreact-prerender-variant-capture": "1" } }),
|
|
1621
|
+
renderSignals,
|
|
1589
1622
|
serverModuleCacheVersion,
|
|
1590
1623
|
serverModules: serverModuleMap,
|
|
1591
1624
|
vitePlugins: options.vitePlugins,
|
|
1592
|
-
}
|
|
1593
|
-
const
|
|
1594
|
-
response.
|
|
1595
|
-
|
|
1596
|
-
|
|
1625
|
+
};
|
|
1626
|
+
const response = await renderAppRequest(renderOptions);
|
|
1627
|
+
const renderedHtml = await response.text();
|
|
1628
|
+
if (renderSignals.headerDependent() || isVisitorDependentResponse(response)) {
|
|
1629
|
+
continue;
|
|
1630
|
+
}
|
|
1631
|
+
let html = renderedHtml;
|
|
1632
|
+
let navigationHtml = renderedHtml;
|
|
1633
|
+
if (!analysis.clientRoute) {
|
|
1634
|
+
const capture = prerenderVariantMarkerParts(route.path);
|
|
1635
|
+
const start = renderedHtml.indexOf(capture.prefix);
|
|
1636
|
+
const end = renderedHtml.lastIndexOf(capture.suffix);
|
|
1637
|
+
if (start === -1 || end < start + capture.prefix.length) {
|
|
1638
|
+
throw new Error(`Failed to capture prerender response variants for ${pathname}.`);
|
|
1639
|
+
}
|
|
1640
|
+
const before = renderedHtml.slice(0, start);
|
|
1641
|
+
const content = renderedHtml.slice(start + capture.prefix.length, end);
|
|
1642
|
+
const after = renderedHtml.slice(end + capture.suffix.length);
|
|
1643
|
+
const navigationMarker = routeMarkerParts(route.path);
|
|
1644
|
+
html = `${before}${content}${after}`;
|
|
1645
|
+
navigationHtml = `${before}${navigationMarker.prefix}${content}${navigationMarker.suffix}${after}`;
|
|
1646
|
+
}
|
|
1647
|
+
const headers = storedPrerenderedRouteHeaders(response.headers);
|
|
1648
|
+
const strictTransportSecurity = renderSignals.strictTransportSecurity();
|
|
1597
1649
|
entries.push([
|
|
1598
1650
|
pathname,
|
|
1599
1651
|
{
|
|
1600
1652
|
headers,
|
|
1601
|
-
html
|
|
1653
|
+
html,
|
|
1654
|
+
navigationHtml,
|
|
1655
|
+
schemaVersion: PRERENDERED_ROUTE_SCHEMA_VERSION,
|
|
1602
1656
|
status: response.status,
|
|
1657
|
+
...(strictTransportSecurity === undefined ? {} : { strictTransportSecurity }),
|
|
1603
1658
|
},
|
|
1604
1659
|
]);
|
|
1605
1660
|
}
|
|
@@ -2008,6 +2063,7 @@ function builtRouteSourceAnalysisSummary(options) {
|
|
|
2008
2063
|
routePath: options.analysis.route.path,
|
|
2009
2064
|
sourceHash: options.analysis.sourceHash,
|
|
2010
2065
|
streamRoute: options.analysis.streamRoute,
|
|
2066
|
+
usesRequestInput: options.analysis.usesRequestInput,
|
|
2011
2067
|
usesRuntimeCacheControl: options.analysis.usesRuntimeCacheControl,
|
|
2012
2068
|
};
|
|
2013
2069
|
}
|
|
@@ -2495,6 +2551,7 @@ function cloudflarePageRouteFacadeModuleSource(componentImport) {
|
|
|
2495
2551
|
const componentSlots = readComponentModuleExport(componentModule, "slots");
|
|
2496
2552
|
const componentGenerateMetadata = readComponentModuleExport(componentModule, "generateMetadata");
|
|
2497
2553
|
const componentMetadata = readComponentModuleExport(componentModule, "metadata");
|
|
2554
|
+
const componentSecurityHeadersApplied = readComponentModuleExport(componentModule, "__mreactSecurityHeadersApplied");
|
|
2498
2555
|
|
|
2499
2556
|
export function App(props) {
|
|
2500
2557
|
return renderCloudflareRouteComponent(props);
|
|
@@ -2509,6 +2566,7 @@ export const slots = componentSlots === undefined ? undefined : { ...componentSl
|
|
|
2509
2566
|
export const generateMetadata =
|
|
2510
2567
|
typeof componentGenerateMetadata === "function" ? componentGenerateMetadata : undefined;
|
|
2511
2568
|
export const metadata = componentMetadata;
|
|
2569
|
+
export const __mreactSecurityHeadersApplied = componentSecurityHeadersApplied === true;
|
|
2512
2570
|
|
|
2513
2571
|
function renderCloudflareRouteComponent(props) {
|
|
2514
2572
|
const routeComponent = resolveCloudflareRouteComponent();
|
|
@@ -3078,7 +3136,9 @@ ${cloudflareShellRuntimeSource()}`;
|
|
|
3078
3136
|
});
|
|
3079
3137
|
}
|
|
3080
3138
|
function cloudflareShellRuntimeSource() {
|
|
3081
|
-
return `
|
|
3139
|
+
return `export const __mreactSecurityHeadersApplied = true;
|
|
3140
|
+
|
|
3141
|
+
async function renderLayoutShells(shells, props, namedSlots) {
|
|
3082
3142
|
const slotContext = { consumedSlots: new Set(), namedSlots };
|
|
3083
3143
|
const rendered = [];
|
|
3084
3144
|
for (const shell of shells) {
|
|
@@ -3157,7 +3217,7 @@ function cloudflareHydrationMarkerParts(props) {
|
|
|
3157
3217
|
const escapedRouteId = escapeHtmlAttribute(routeId);
|
|
3158
3218
|
const propsJson = escapeScriptJson(JSON.stringify({
|
|
3159
3219
|
params: props.params,
|
|
3160
|
-
request: { url: props.request.url },
|
|
3220
|
+
request: { url: new URL(props.request.url).pathname },
|
|
3161
3221
|
data: props.data,
|
|
3162
3222
|
}));
|
|
3163
3223
|
const clientReferencesJson = route.clientReferenceManifest === undefined || route.clientReferenceManifest.length === 0
|
|
@@ -3580,17 +3640,63 @@ function routeSecurityHeaders(security, request) {
|
|
|
3580
3640
|
} else {
|
|
3581
3641
|
headers["referrer-policy"] = validateHeaderValue(security?.referrerPolicy ?? "strict-origin-when-cross-origin");
|
|
3582
3642
|
}
|
|
3643
|
+
if (security?.permissionsPolicy === null) {
|
|
3644
|
+
delete headers["permissions-policy"];
|
|
3645
|
+
} else {
|
|
3646
|
+
const permissionsPolicy = serializePermissionsPolicy(security?.permissionsPolicy);
|
|
3647
|
+
if (permissionsPolicy === undefined) {
|
|
3648
|
+
delete headers["permissions-policy"];
|
|
3649
|
+
} else {
|
|
3650
|
+
headers["permissions-policy"] = permissionsPolicy;
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3583
3653
|
if (security?.frameOptions === null) {
|
|
3584
3654
|
delete headers["x-frame-options"];
|
|
3585
3655
|
} else if (security?.frameOptions !== undefined) {
|
|
3586
3656
|
headers["x-frame-options"] = validateHeaderValue(security.frameOptions);
|
|
3587
3657
|
}
|
|
3588
3658
|
if (request.url.startsWith("https://") && security?.hsts !== undefined && security.hsts !== false && security.hsts !== null) {
|
|
3589
|
-
headers["strict-transport-security"] =
|
|
3659
|
+
headers["strict-transport-security"] = serializeHsts(security.hsts);
|
|
3590
3660
|
}
|
|
3591
3661
|
return headers;
|
|
3592
3662
|
}
|
|
3593
3663
|
|
|
3664
|
+
function serializeHsts(hsts) {
|
|
3665
|
+
if (hsts === false) {
|
|
3666
|
+
throw new TypeError("Invalid security header value for hsts.");
|
|
3667
|
+
}
|
|
3668
|
+
const maxAge = Math.trunc(hsts.maxAge);
|
|
3669
|
+
if (!Number.isFinite(maxAge) || maxAge < 0) {
|
|
3670
|
+
throw new TypeError("Invalid security header value for hsts.maxAge.");
|
|
3671
|
+
}
|
|
3672
|
+
const parts = [\`max-age=\${maxAge}\`];
|
|
3673
|
+
if (hsts.includeSubDomains === true) {
|
|
3674
|
+
parts.push("includeSubDomains");
|
|
3675
|
+
}
|
|
3676
|
+
if (hsts.preload === true) {
|
|
3677
|
+
parts.push("preload");
|
|
3678
|
+
}
|
|
3679
|
+
return parts.join("; ");
|
|
3680
|
+
}
|
|
3681
|
+
|
|
3682
|
+
function serializePermissionsPolicy(policy) {
|
|
3683
|
+
if (policy === undefined) {
|
|
3684
|
+
return "camera=(), microphone=(), geolocation=()";
|
|
3685
|
+
}
|
|
3686
|
+
const directives = [];
|
|
3687
|
+
for (const [directive, allowlist] of Object.entries(policy)) {
|
|
3688
|
+
if (allowlist === null || allowlist === undefined) {
|
|
3689
|
+
continue;
|
|
3690
|
+
}
|
|
3691
|
+
validateToken(directive, "permissionsPolicy directive");
|
|
3692
|
+
for (const value of allowlist) {
|
|
3693
|
+
validatePermissionAllowlistValue(value);
|
|
3694
|
+
}
|
|
3695
|
+
directives.push(\`\${directive}=(\${allowlist.join(" ")})\`);
|
|
3696
|
+
}
|
|
3697
|
+
return directives.length === 0 ? undefined : directives.join(", ");
|
|
3698
|
+
}
|
|
3699
|
+
|
|
3594
3700
|
function validateHeaderValue(value) {
|
|
3595
3701
|
for (let index = 0; index < value.length; index += 1) {
|
|
3596
3702
|
const code = value.charCodeAt(index);
|
|
@@ -3601,6 +3707,22 @@ function validateHeaderValue(value) {
|
|
|
3601
3707
|
return value;
|
|
3602
3708
|
}
|
|
3603
3709
|
|
|
3710
|
+
function validateToken(value, label) {
|
|
3711
|
+
if (!/^[A-Za-z][A-Za-z0-9-]*$/.test(value)) {
|
|
3712
|
+
throw new TypeError(\`Invalid security header value for \${label}: \${JSON.stringify(value)}\`);
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
3715
|
+
|
|
3716
|
+
function validatePermissionAllowlistValue(value) {
|
|
3717
|
+
if (value === "self" || value === "*" || /^[A-Za-z][A-Za-z0-9+.-]*:$/.test(value)) {
|
|
3718
|
+
return;
|
|
3719
|
+
}
|
|
3720
|
+
if (/^https:\\/\\/[A-Za-z0-9.-]+(?::[0-9]+)?$/.test(value)) {
|
|
3721
|
+
return;
|
|
3722
|
+
}
|
|
3723
|
+
throw new TypeError(\`Invalid security header value for permissionsPolicy allowlist: \${JSON.stringify(value)}\`);
|
|
3724
|
+
}
|
|
3725
|
+
|
|
3604
3726
|
function mergeRouteMetadata(metadata) {
|
|
3605
3727
|
if (metadata.length === 0) {
|
|
3606
3728
|
return undefined;
|
|
@@ -4322,6 +4444,7 @@ async function writeClientRouteBundles(options) {
|
|
|
4322
4444
|
clientNavigation: detectClientNavigationOverride(source) ??
|
|
4323
4445
|
(navigation || detectAnchorElementUsage(clientSource, route.file)),
|
|
4324
4446
|
routeMayUseOutOfOrderFragments: options.sourceAnalysis.byRouteFile.get(relative(options.projectRoot, route.file).split(sep).join("/"))?.streamRoute === true,
|
|
4447
|
+
restoreRequestUrl: options.sourceAnalysis.byRouteFile.get(relative(options.projectRoot, route.file).split(sep).join("/"))?.usesRequestInput === true,
|
|
4325
4448
|
cacheDir: options.cacheDir,
|
|
4326
4449
|
dropConsoleFunctions: options.clientConsolePureFunctions,
|
|
4327
4450
|
filename: route.file,
|