@reckona/mreact-router 0.0.202 → 0.0.204
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 +58 -11
- package/dist/actions.d.ts +8 -3
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +125 -45
- package/dist/actions.js.map +1 -1
- package/dist/adapters/aws-lambda.d.ts +15 -4
- package/dist/adapters/aws-lambda.d.ts.map +1 -1
- package/dist/adapters/aws-lambda.js +301 -63
- package/dist/adapters/aws-lambda.js.map +1 -1
- package/dist/adapters/cloudflare.d.ts +5 -2
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +35 -11
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/edge.d.ts +1 -1
- package/dist/adapters/edge.d.ts.map +1 -1
- package/dist/adapters/edge.js.map +1 -1
- package/dist/adapters/node.d.ts +5 -3
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +2 -1
- package/dist/adapters/node.js.map +1 -1
- package/dist/adapters/static.d.ts.map +1 -1
- package/dist/adapters/static.js +24 -2
- package/dist/adapters/static.js.map +1 -1
- package/dist/build.d.ts +4 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +185 -13
- package/dist/build.js.map +1 -1
- package/dist/built-runtime.d.ts +2 -0
- package/dist/built-runtime.d.ts.map +1 -1
- package/dist/built-runtime.js +16 -0
- package/dist/built-runtime.js.map +1 -1
- package/dist/cache.d.ts +4 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +216 -17
- package/dist/cache.js.map +1 -1
- package/dist/cli-options.d.ts +3 -0
- package/dist/cli-options.d.ts.map +1 -1
- package/dist/cli-options.js +10 -2
- package/dist/cli-options.js.map +1 -1
- package/dist/cli.js +14 -3
- 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 +43 -3
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -2
- package/dist/config.js.map +1 -1
- package/dist/csp.d.ts +1 -0
- package/dist/csp.d.ts.map +1 -1
- package/dist/csp.js +9 -0
- package/dist/csp.js.map +1 -1
- package/dist/dehydrate-policy.d.ts +3 -0
- package/dist/dehydrate-policy.d.ts.map +1 -0
- package/dist/dehydrate-policy.js +16 -0
- package/dist/dehydrate-policy.js.map +1 -0
- package/dist/dev-server.d.ts +7 -2
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +120 -11
- package/dist/dev-server.js.map +1 -1
- package/dist/http.d.ts +1 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +147 -7
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +22 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +22 -8
- package/dist/logger.js.map +1 -1
- package/dist/metadata.d.ts +8 -0
- package/dist/metadata.d.ts.map +1 -1
- package/dist/metadata.js +60 -22
- package/dist/metadata.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 +357 -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/navigation.d.ts +1 -0
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +1 -1
- package/dist/navigation.js.map +1 -1
- package/dist/node-server.d.ts +5 -2
- package/dist/node-server.d.ts.map +1 -1
- package/dist/node-server.js +75 -6
- package/dist/node-server.js.map +1 -1
- package/dist/prerender-entry.d.ts +17 -1
- package/dist/prerender-entry.d.ts.map +1 -1
- package/dist/prerender-entry.js +98 -3
- package/dist/prerender-entry.js.map +1 -1
- package/dist/render.d.ts +16 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +142 -135
- package/dist/render.js.map +1 -1
- package/dist/serve.d.ts +11 -2
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +67 -41
- package/dist/serve.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +52 -19
- package/dist/session.js.map +1 -1
- package/dist/upgrade.d.ts +59 -2
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +282 -1
- package/dist/upgrade.js.map +1 -1
- package/dist/vite-config.d.ts +2 -0
- package/dist/vite-config.d.ts.map +1 -1
- package/dist/vite-config.js +2 -0
- package/dist/vite-config.js.map +1 -1
- package/dist/vite.d.ts +4 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +117 -6
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/actions.ts +146 -60
- package/src/adapters/aws-lambda.ts +426 -115
- package/src/adapters/cloudflare.ts +58 -12
- package/src/adapters/edge.ts +2 -0
- package/src/adapters/node.ts +8 -10
- package/src/adapters/static.ts +31 -2
- package/src/build.ts +217 -13
- package/src/built-runtime.ts +28 -0
- package/src/cache.ts +272 -19
- package/src/cli-options.ts +15 -2
- package/src/cli.ts +16 -2
- package/src/client.ts +47 -3
- package/src/config.ts +43 -6
- package/src/csp.ts +11 -0
- package/src/dehydrate-policy.ts +23 -0
- package/src/dev-server.ts +188 -15
- package/src/http.ts +172 -6
- package/src/index.ts +14 -1
- package/src/logger.ts +47 -10
- package/src/metadata.ts +125 -60
- package/src/navigation-marker.ts +423 -0
- package/src/navigation-runtime.ts +1 -0
- package/src/navigation.ts +1 -1
- package/src/node-server.ts +128 -22
- package/src/prerender-entry.ts +127 -5
- package/src/render.ts +859 -749
- package/src/serve.ts +112 -82
- package/src/session.ts +56 -25
- package/src/upgrade.ts +402 -3
- package/src/vite-config.ts +6 -0
- package/src/vite.ts +157 -5
package/src/prerender-entry.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { BuiltPrerenderedRoute } from "./build.js";
|
|
2
|
+
import { responseHeadersContainCspNonce } from "./csp.js";
|
|
3
|
+
import { hasNavigationRouteMarker } from "./navigation-marker.js";
|
|
2
4
|
|
|
3
|
-
export const PRERENDERED_ROUTE_SCHEMA_VERSION =
|
|
5
|
+
export const PRERENDERED_ROUTE_SCHEMA_VERSION = 4;
|
|
6
|
+
|
|
7
|
+
const validatedNavigationHtmlByEntry = new WeakMap<object, string | null>();
|
|
4
8
|
|
|
5
9
|
export function isCurrentPrerenderedRoute(value: unknown): value is BuiltPrerenderedRoute {
|
|
6
10
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
@@ -12,6 +16,9 @@ export function isCurrentPrerenderedRoute(value: unknown): value is BuiltPrerend
|
|
|
12
16
|
entry.schemaVersion === PRERENDERED_ROUTE_SCHEMA_VERSION &&
|
|
13
17
|
isStringRecord(entry.headers) &&
|
|
14
18
|
isShareableHeaderRecord(entry.headers) &&
|
|
19
|
+
hasRequiredNavigationVary(entry.headers) &&
|
|
20
|
+
!hasStoredHstsHeader(entry.headers) &&
|
|
21
|
+
isCanonicalHstsHeader(entry.strictTransportSecurity) &&
|
|
15
22
|
typeof entry.html === "string" &&
|
|
16
23
|
typeof entry.status === "number" &&
|
|
17
24
|
Number.isInteger(entry.status) &&
|
|
@@ -20,10 +27,120 @@ export function isCurrentPrerenderedRoute(value: unknown): value is BuiltPrerend
|
|
|
20
27
|
);
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Returns a navigation variant only after validating its route marker.
|
|
32
|
+
*
|
|
33
|
+
* Stored entries are stable objects during a runtime's lifetime, so the
|
|
34
|
+
* marker scan is cached by identity. Document requests never call this
|
|
35
|
+
* function and therefore never inspect navigation HTML.
|
|
36
|
+
*/
|
|
37
|
+
export function validatedPrerenderedNavigationHtml(
|
|
38
|
+
entry: BuiltPrerenderedRoute,
|
|
39
|
+
): string | undefined {
|
|
40
|
+
const cached = validatedNavigationHtmlByEntry.get(entry);
|
|
41
|
+
if (cached !== undefined) {
|
|
42
|
+
return cached === null ? undefined : cached;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const candidate = entry.navigationHtml;
|
|
46
|
+
const validated =
|
|
47
|
+
typeof candidate === "string" && hasNavigationRouteMarker(candidate) ? candidate : null;
|
|
48
|
+
validatedNavigationHtmlByEntry.set(entry, validated);
|
|
49
|
+
return validated === null ? undefined : validated;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Adds a regenerated navigation variant only when it satisfies the marker
|
|
54
|
+
* contract. Invalid navigation output must not replace a valid document.
|
|
55
|
+
*/
|
|
56
|
+
export function mergePrerenderedNavigationHtml(
|
|
57
|
+
entry: BuiltPrerenderedRoute,
|
|
58
|
+
navigationHtml: string,
|
|
59
|
+
): BuiltPrerenderedRoute {
|
|
60
|
+
return hasNavigationRouteMarker(navigationHtml) ? { ...entry, navigationHtml } : entry;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function hasStoredHstsHeader(headers: Record<string, string>): boolean {
|
|
64
|
+
try {
|
|
65
|
+
return new Headers(headers).has("strict-transport-security");
|
|
66
|
+
} catch {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isCanonicalHstsHeader(value: unknown): value is string | undefined {
|
|
72
|
+
return (
|
|
73
|
+
value === undefined ||
|
|
74
|
+
(typeof value === "string" &&
|
|
75
|
+
/^max-age=(?:0|[1-9][0-9]*)(?:; includeSubDomains)?(?:; preload)?$/.test(value))
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
23
79
|
export function isVisitorDependentResponse(response: Response): boolean {
|
|
24
80
|
return isVisitorDependentHeaders(response.headers);
|
|
25
81
|
}
|
|
26
82
|
|
|
83
|
+
export function protectNonceBearingResponse(response: Response): Response {
|
|
84
|
+
if (!responseHeadersContainCspNonce(response.headers)) {
|
|
85
|
+
return response;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const headers = new Headers(response.headers);
|
|
89
|
+
headers.set("cache-control", "private, no-store");
|
|
90
|
+
headers.set("x-mreact-cache", "DYNAMIC");
|
|
91
|
+
return new Response(response.body, {
|
|
92
|
+
headers,
|
|
93
|
+
status: response.status,
|
|
94
|
+
statusText: response.statusText,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function storedPrerenderedRouteHeaders(headers: Headers): Record<string, string> {
|
|
99
|
+
const stored: Record<string, string> = {};
|
|
100
|
+
|
|
101
|
+
headers.forEach((value, key) => {
|
|
102
|
+
if (key !== "strict-transport-security") {
|
|
103
|
+
stored[key] = value;
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return stored;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function replayedPrerenderedRouteHeaders(
|
|
111
|
+
entry: BuiltPrerenderedRoute,
|
|
112
|
+
request: Request,
|
|
113
|
+
): Headers {
|
|
114
|
+
const headers = new Headers(entry.headers);
|
|
115
|
+
|
|
116
|
+
if (!hasNavigationVary(headers)) {
|
|
117
|
+
headers.append("vary", "x-mreact-navigation");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (entry.strictTransportSecurity !== undefined && request.url.startsWith("https://")) {
|
|
121
|
+
headers.set("strict-transport-security", entry.strictTransportSecurity);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return headers;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function hasRequiredNavigationVary(headers: Record<string, string>): boolean {
|
|
128
|
+
try {
|
|
129
|
+
return hasNavigationVary(new Headers(headers));
|
|
130
|
+
} catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function hasNavigationVary(headers: Headers): boolean {
|
|
136
|
+
return (
|
|
137
|
+
headers
|
|
138
|
+
.get("vary")
|
|
139
|
+
?.split(",")
|
|
140
|
+
.some((value) => value.trim().toLowerCase() === "x-mreact-navigation") === true
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
27
144
|
function isShareableHeaderRecord(headers: Record<string, string>): boolean {
|
|
28
145
|
try {
|
|
29
146
|
return !isVisitorDependentHeaders(new Headers(headers));
|
|
@@ -34,14 +151,19 @@ function isShareableHeaderRecord(headers: Record<string, string>): boolean {
|
|
|
34
151
|
|
|
35
152
|
function isVisitorDependentHeaders(headers: Headers): boolean {
|
|
36
153
|
const cacheControl = headers.get("cache-control") ?? "";
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
154
|
+
const vary = headers.get("vary");
|
|
155
|
+
const hasVisitorDependentVary =
|
|
156
|
+
vary !== null &&
|
|
157
|
+
vary.split(",").some((value) => value.trim().toLowerCase() !== "x-mreact-navigation");
|
|
158
|
+
const forbidsSharedStorage = cacheControl
|
|
159
|
+
.split(",")
|
|
160
|
+
.some((directive) => /^(?:private|no-cache|no-store)(?:=|$)/i.test(directive.trim()));
|
|
40
161
|
|
|
41
162
|
return (
|
|
42
163
|
headers.get("x-mreact-cache")?.toUpperCase() === "DYNAMIC" ||
|
|
43
164
|
headers.has("set-cookie") ||
|
|
44
|
-
headers
|
|
165
|
+
responseHeadersContainCspNonce(headers) ||
|
|
166
|
+
hasVisitorDependentVary ||
|
|
45
167
|
forbidsSharedStorage
|
|
46
168
|
);
|
|
47
169
|
}
|