vinext 1.0.0-beta.1 → 1.0.0-beta.2
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 +4 -1
- package/dist/build/client-build-config.js +1 -0
- package/dist/build/report.d.ts +8 -1
- package/dist/build/report.js +12 -2
- package/dist/check.js +15 -2
- package/dist/cli.js +3 -2
- package/dist/config/config-matchers.d.ts +13 -37
- package/dist/config/config-matchers.js +31 -121
- package/dist/config/next-config.d.ts +3 -2
- package/dist/config/next-config.js +3 -1
- package/dist/config/request-context.d.ts +14 -0
- package/dist/config/request-context.js +26 -0
- package/dist/entries/app-rsc-entry.js +27 -9
- package/dist/entries/app-rsc-manifest.js +17 -0
- package/dist/entries/pages-server-entry.js +3 -2
- package/dist/index.js +82 -58
- package/dist/init.d.ts +6 -4
- package/dist/init.js +20 -22
- package/dist/plugins/og-assets.js +1 -1
- package/dist/routing/app-route-graph.d.ts +13 -5
- package/dist/routing/app-route-graph.js +59 -13
- package/dist/routing/app-router.js +12 -6
- package/dist/routing/file-matcher.d.ts +11 -22
- package/dist/routing/file-matcher.js +21 -33
- package/dist/routing/pages-router.js +23 -29
- package/dist/routing/route-matching.d.ts +14 -1
- package/dist/routing/route-matching.js +13 -1
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-pattern.js +7 -4
- package/dist/routing/route-trie.d.ts +5 -1
- package/dist/routing/route-trie.js +5 -2
- package/dist/server/app-browser-entry.js +7 -6
- package/dist/server/app-browser-history-controller.d.ts +1 -1
- package/dist/server/app-browser-history-controller.js +3 -3
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +3 -0
- package/dist/server/app-fallback-renderer.js +4 -2
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-page-boundary-render.d.ts +12 -1
- package/dist/server/app-page-boundary-render.js +84 -2
- package/dist/server/app-page-cache-finalizer.d.ts +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-dispatch.d.ts +11 -2
- package/dist/server/app-page-dispatch.js +14 -17
- package/dist/server/app-page-element-builder.d.ts +7 -2
- package/dist/server/app-page-element-builder.js +112 -27
- package/dist/server/app-page-head.d.ts +54 -2
- package/dist/server/app-page-head.js +164 -78
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +106 -0
- package/dist/server/app-page-render.d.ts +2 -2
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.d.ts +12 -0
- package/dist/server/app-page-request.js +133 -13
- package/dist/server/app-page-route-wiring.d.ts +9 -0
- package/dist/server/app-page-route-wiring.js +43 -3
- package/dist/server/app-post-middleware-context.d.ts +1 -1
- package/dist/server/app-post-middleware-context.js +1 -1
- package/dist/server/app-route-handler-dispatch.js +31 -17
- package/dist/server/app-route-handler-execution.d.ts +6 -1
- package/dist/server/app-route-handler-execution.js +42 -16
- package/dist/server/app-route-handler-policy.d.ts +2 -0
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-module-loader.d.ts +3 -1
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-rsc-cache-busting.d.ts +1 -1
- package/dist/server/app-rsc-errors.d.ts +1 -1
- package/dist/server/app-rsc-errors.js +12 -2
- package/dist/server/app-rsc-handler.d.ts +10 -5
- package/dist/server/app-rsc-handler.js +52 -24
- package/dist/server/app-rsc-request-normalization.d.ts +3 -2
- package/dist/server/app-rsc-request-normalization.js +8 -2
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
- package/dist/server/app-rsc-response-finalizer.js +5 -11
- package/dist/server/app-rsc-route-matching.d.ts +20 -0
- package/dist/server/app-rsc-route-matching.js +87 -11
- package/dist/server/app-segment-config.js +13 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +9 -7
- package/dist/server/app-ssr-entry.js +2 -2
- package/dist/server/app-ssr-stream.d.ts +1 -7
- package/dist/server/app-ssr-stream.js +2 -10
- package/dist/server/config-headers.d.ts +24 -0
- package/dist/server/config-headers.js +52 -0
- package/dist/server/dev-initial-server-error.d.ts +1 -1
- package/dist/server/dev-server.js +29 -13
- package/dist/server/isr-cache.d.ts +1 -1
- package/dist/server/middleware-matcher-pattern.d.ts +22 -0
- package/dist/server/middleware-matcher-pattern.js +219 -0
- package/dist/server/middleware-matcher.d.ts +2 -7
- package/dist/server/middleware-matcher.js +13 -60
- package/dist/server/middleware-path-to-regexp.d.ts +14 -0
- package/dist/server/middleware-path-to-regexp.js +228 -0
- package/dist/server/middleware-runtime.js +4 -3
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +2 -1
- package/dist/server/pages-data-route.d.ts +11 -1
- package/dist/server/pages-data-route.js +16 -1
- package/dist/server/pages-get-initial-props.d.ts +15 -2
- package/dist/server/pages-get-initial-props.js +16 -6
- package/dist/server/pages-page-data.d.ts +3 -1
- package/dist/server/pages-page-data.js +16 -7
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +16 -17
- package/dist/server/pages-page-response.js +1 -1
- package/dist/server/pages-readiness.d.ts +3 -3
- package/dist/server/pages-request-pipeline.d.ts +1 -0
- package/dist/server/pages-request-pipeline.js +25 -11
- package/dist/server/pages-router-entry.js +6 -0
- package/dist/server/prerender-route-params.js +2 -2
- package/dist/server/prod-server.d.ts +1 -4
- package/dist/server/prod-server.js +36 -23
- package/dist/server/request-pipeline.d.ts +15 -29
- package/dist/server/request-pipeline.js +24 -59
- package/dist/server/rsc-stream-hints.js +122 -18
- package/dist/shims/app.d.ts +1 -1
- package/dist/shims/cache-request-state.d.ts +27 -1
- package/dist/shims/cache-request-state.js +60 -1
- package/dist/shims/cache-runtime.d.ts +12 -1
- package/dist/shims/cache-runtime.js +22 -7
- package/dist/shims/cache.d.ts +5 -5
- package/dist/shims/cache.js +26 -10
- package/dist/shims/document.d.ts +42 -83
- package/dist/shims/document.js +62 -53
- package/dist/shims/dynamic.d.ts +5 -25
- package/dist/shims/dynamic.js +29 -8
- package/dist/shims/error.d.ts +1 -1
- package/dist/shims/error.js +1 -1
- package/dist/shims/fetch-cache.js +12 -3
- package/dist/shims/font-google-base.d.ts +11 -4
- package/dist/shims/font-local.d.ts +10 -3
- package/dist/shims/head.d.ts +13 -2
- package/dist/shims/head.js +3 -3
- package/dist/shims/headers.d.ts +28 -31
- package/dist/shims/headers.js +109 -49
- package/dist/shims/image.d.ts +27 -37
- package/dist/shims/image.js +21 -14
- package/dist/shims/internal/cookie-serialize.d.ts +3 -1
- package/dist/shims/internal/cookie-serialize.js +3 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
- package/dist/shims/internal/utils.d.ts +3 -3
- package/dist/shims/legacy-image.d.ts +3 -37
- package/dist/shims/legacy-image.js +6 -16
- package/dist/shims/link.d.ts +15 -22
- package/dist/shims/link.js +20 -11
- package/dist/shims/navigation-context-state.d.ts +1 -1
- package/dist/shims/navigation.d.ts +7 -3
- package/dist/shims/navigation.js +24 -13
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/next-shims-augmentations.d.ts +1 -0
- package/dist/shims/next-shims-public.d.ts +1 -0
- package/dist/shims/public-shim-map.json.js +103 -0
- package/dist/shims/readonly-url-search-params.d.ts +3 -3
- package/dist/shims/readonly-url-search-params.js +3 -3
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router.d.ts +55 -21
- package/dist/shims/router.js +162 -37
- package/dist/shims/script.d.ts +6 -10
- package/dist/shims/script.js +6 -3
- package/dist/shims/server.d.ts +45 -22
- package/dist/shims/server.js +44 -5
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -0
- package/dist/shims/url-safety.d.ts +1 -1
- package/dist/shims/url-safety.js +2 -2
- package/dist/typegen.d.ts +8 -2
- package/dist/typegen.js +76 -15
- package/dist/utils/domain-locale.d.ts +2 -2
- package/dist/utils/external-url.d.ts +5 -0
- package/dist/utils/external-url.js +7 -0
- package/dist/utils/regex-safety.d.ts +8 -0
- package/dist/utils/regex-safety.js +737 -0
- package/package.json +13 -2
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
//#region src/server/middleware-path-to-regexp.ts
|
|
2
|
+
function lexer(value) {
|
|
3
|
+
const tokens = [];
|
|
4
|
+
let index = 0;
|
|
5
|
+
while (index < value.length) {
|
|
6
|
+
const character = value[index];
|
|
7
|
+
if (character === "*" || character === "+" || character === "?") {
|
|
8
|
+
tokens.push({
|
|
9
|
+
type: "MODIFIER",
|
|
10
|
+
index,
|
|
11
|
+
value: value[index++]
|
|
12
|
+
});
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (character === "\\") {
|
|
16
|
+
tokens.push({
|
|
17
|
+
type: "ESCAPED_CHAR",
|
|
18
|
+
index: index++,
|
|
19
|
+
value: value[index++]
|
|
20
|
+
});
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (character === "{") {
|
|
24
|
+
tokens.push({
|
|
25
|
+
type: "OPEN",
|
|
26
|
+
index,
|
|
27
|
+
value: value[index++]
|
|
28
|
+
});
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (character === "}") {
|
|
32
|
+
tokens.push({
|
|
33
|
+
type: "CLOSE",
|
|
34
|
+
index,
|
|
35
|
+
value: value[index++]
|
|
36
|
+
});
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (character === ":") {
|
|
40
|
+
let name = "";
|
|
41
|
+
let nameEnd = index + 1;
|
|
42
|
+
while (nameEnd < value.length) {
|
|
43
|
+
const code = value.charCodeAt(nameEnd);
|
|
44
|
+
if (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 95) {
|
|
45
|
+
name += value[nameEnd++];
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (!name) throw new TypeError(`Missing parameter name at ${index}`);
|
|
51
|
+
tokens.push({
|
|
52
|
+
type: "NAME",
|
|
53
|
+
index,
|
|
54
|
+
value: name
|
|
55
|
+
});
|
|
56
|
+
index = nameEnd;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (character === "(") {
|
|
60
|
+
let depth = 1;
|
|
61
|
+
let pattern = "";
|
|
62
|
+
let patternEnd = index + 1;
|
|
63
|
+
if (value[patternEnd] === "?") throw new TypeError(`Pattern cannot start with "?" at ${patternEnd}`);
|
|
64
|
+
while (patternEnd < value.length) {
|
|
65
|
+
if (value[patternEnd] === "\\") {
|
|
66
|
+
pattern += value[patternEnd++] + value[patternEnd++];
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (value[patternEnd] === ")") {
|
|
70
|
+
depth--;
|
|
71
|
+
if (depth === 0) {
|
|
72
|
+
patternEnd++;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
} else if (value[patternEnd] === "(") {
|
|
76
|
+
depth++;
|
|
77
|
+
if (value[patternEnd + 1] !== "?") throw new TypeError(`Capturing groups are not allowed at ${patternEnd}`);
|
|
78
|
+
}
|
|
79
|
+
pattern += value[patternEnd++];
|
|
80
|
+
}
|
|
81
|
+
if (depth) throw new TypeError(`Unbalanced pattern at ${index}`);
|
|
82
|
+
if (!pattern) throw new TypeError(`Missing pattern at ${index}`);
|
|
83
|
+
tokens.push({
|
|
84
|
+
type: "PATTERN",
|
|
85
|
+
index,
|
|
86
|
+
value: pattern
|
|
87
|
+
});
|
|
88
|
+
index = patternEnd;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
tokens.push({
|
|
92
|
+
type: "CHAR",
|
|
93
|
+
index,
|
|
94
|
+
value: value[index++]
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
tokens.push({
|
|
98
|
+
type: "END",
|
|
99
|
+
index,
|
|
100
|
+
value: ""
|
|
101
|
+
});
|
|
102
|
+
return tokens;
|
|
103
|
+
}
|
|
104
|
+
function parseMiddlewarePath(value) {
|
|
105
|
+
const tokens = lexer(value);
|
|
106
|
+
const result = [];
|
|
107
|
+
const prefixes = "./";
|
|
108
|
+
const delimiter = "/#?";
|
|
109
|
+
let key = 0;
|
|
110
|
+
let index = 0;
|
|
111
|
+
let path = "";
|
|
112
|
+
const tryConsume = (type) => {
|
|
113
|
+
if (index < tokens.length && tokens[index].type === type) return tokens[index++].value;
|
|
114
|
+
};
|
|
115
|
+
const mustConsume = (type) => {
|
|
116
|
+
const consumed = tryConsume(type);
|
|
117
|
+
if (consumed !== void 0) return consumed;
|
|
118
|
+
const next = tokens[index];
|
|
119
|
+
throw new TypeError(`Unexpected ${next.type} at ${next.index}, expected ${type}`);
|
|
120
|
+
};
|
|
121
|
+
const consumeText = () => {
|
|
122
|
+
let text = "";
|
|
123
|
+
let consumed;
|
|
124
|
+
while ((consumed = tryConsume("CHAR") ?? tryConsume("ESCAPED_CHAR")) !== void 0) text += consumed;
|
|
125
|
+
return text;
|
|
126
|
+
};
|
|
127
|
+
const containsDelimiter = (text) => {
|
|
128
|
+
for (const character of delimiter) if (text.includes(character)) return true;
|
|
129
|
+
return false;
|
|
130
|
+
};
|
|
131
|
+
const defaultPattern = (prefix) => {
|
|
132
|
+
const previous = result[result.length - 1];
|
|
133
|
+
const previousText = prefix || (typeof previous === "string" ? previous : "");
|
|
134
|
+
if (previous && !previousText) {
|
|
135
|
+
const name = typeof previous === "string" ? previous : previous.name;
|
|
136
|
+
throw new TypeError(`Must have text between two parameters, missing text after "${name}"`);
|
|
137
|
+
}
|
|
138
|
+
if (!previousText || containsDelimiter(previousText)) return "[^\\/#\\?]+?";
|
|
139
|
+
return `(?:(?!${escapeRegex(previousText)})[^\\/#\\?])+?`;
|
|
140
|
+
};
|
|
141
|
+
while (index < tokens.length) {
|
|
142
|
+
const character = tryConsume("CHAR");
|
|
143
|
+
const name = tryConsume("NAME");
|
|
144
|
+
const pattern = tryConsume("PATTERN");
|
|
145
|
+
if (name !== void 0 || pattern !== void 0) {
|
|
146
|
+
let prefix = character ?? "";
|
|
147
|
+
if (!prefixes.includes(prefix)) {
|
|
148
|
+
path += prefix;
|
|
149
|
+
prefix = "";
|
|
150
|
+
}
|
|
151
|
+
if (path) {
|
|
152
|
+
result.push(path);
|
|
153
|
+
path = "";
|
|
154
|
+
}
|
|
155
|
+
result.push({
|
|
156
|
+
name: name ?? key++,
|
|
157
|
+
prefix,
|
|
158
|
+
suffix: "",
|
|
159
|
+
pattern: pattern ?? defaultPattern(prefix),
|
|
160
|
+
modifier: tryConsume("MODIFIER") ?? ""
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const text = character ?? tryConsume("ESCAPED_CHAR");
|
|
165
|
+
if (text !== void 0) {
|
|
166
|
+
path += text;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (path) {
|
|
170
|
+
result.push(path);
|
|
171
|
+
path = "";
|
|
172
|
+
}
|
|
173
|
+
if (tryConsume("OPEN") !== void 0) {
|
|
174
|
+
const prefix = consumeText();
|
|
175
|
+
const groupName = tryConsume("NAME") ?? "";
|
|
176
|
+
const groupPattern = tryConsume("PATTERN") ?? "";
|
|
177
|
+
const suffix = consumeText();
|
|
178
|
+
mustConsume("CLOSE");
|
|
179
|
+
result.push({
|
|
180
|
+
name: groupName || (groupPattern ? key++ : ""),
|
|
181
|
+
pattern: groupName && !groupPattern ? defaultPattern(prefix) : groupPattern,
|
|
182
|
+
prefix,
|
|
183
|
+
suffix,
|
|
184
|
+
modifier: tryConsume("MODIFIER") ?? ""
|
|
185
|
+
});
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
mustConsume("END");
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
function escapeRegex(value) {
|
|
193
|
+
return value.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
|
|
194
|
+
}
|
|
195
|
+
function normalizeMiddlewarePathTokens(tokens) {
|
|
196
|
+
return tokens.map((token) => {
|
|
197
|
+
if (typeof token === "object" && (token.modifier === "*" || token.modifier === "+") && token.prefix === "" && token.suffix === "") return {
|
|
198
|
+
...token,
|
|
199
|
+
prefix: "/"
|
|
200
|
+
};
|
|
201
|
+
return token;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function middlewarePathTokensToRegExp(tokens) {
|
|
205
|
+
const delimiterRegex = `[${escapeRegex("/#?")}]`;
|
|
206
|
+
let route = "^";
|
|
207
|
+
for (const token of tokens) {
|
|
208
|
+
if (typeof token === "string") {
|
|
209
|
+
route += escapeRegex(token);
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
const prefix = escapeRegex(token.prefix);
|
|
213
|
+
const suffix = escapeRegex(token.suffix);
|
|
214
|
+
if (token.pattern) if (prefix || suffix) if (token.modifier === "+" || token.modifier === "*") {
|
|
215
|
+
const optional = token.modifier === "*" ? "?" : "";
|
|
216
|
+
route += `(?:${prefix}((?:${token.pattern})(?:${suffix}${prefix}(?:${token.pattern}))*)${suffix})${optional}`;
|
|
217
|
+
} else route += `(?:${prefix}(${token.pattern})${suffix})${token.modifier}`;
|
|
218
|
+
else {
|
|
219
|
+
if (token.modifier === "+" || token.modifier === "*") throw new TypeError(`Can not repeat "${token.name}" without a prefix and suffix`);
|
|
220
|
+
route += `(${token.pattern})${token.modifier}`;
|
|
221
|
+
}
|
|
222
|
+
else route += `(?:${prefix}${suffix})${token.modifier}`;
|
|
223
|
+
}
|
|
224
|
+
route += `${delimiterRegex}?$`;
|
|
225
|
+
return new RegExp(route, "i");
|
|
226
|
+
}
|
|
227
|
+
//#endregion
|
|
228
|
+
export { middlewarePathTokensToRegExp, normalizeMiddlewarePathTokens, parseMiddlewarePath };
|
|
@@ -112,10 +112,11 @@ function resolveMiddlewarePathname(request) {
|
|
|
112
112
|
return badRequestResponse();
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
-
function createNextRequest(request,
|
|
115
|
+
function createNextRequest(request, i18nConfig, basePath, trailingSlash, hadBasePath) {
|
|
116
116
|
const url = new URL(request.url);
|
|
117
117
|
let mwRequest = request.body && !request.bodyUsed ? request.clone() : request;
|
|
118
|
-
const
|
|
118
|
+
const requestPathname = url.pathname;
|
|
119
|
+
const mwPathname = basePath && hadBasePath && !hasBasePath(requestPathname, basePath) ? addBasePathToPathname(requestPathname, basePath) : requestPathname;
|
|
119
120
|
if (mwPathname !== url.pathname) {
|
|
120
121
|
const mwUrl = new URL(url);
|
|
121
122
|
mwUrl.pathname = mwPathname;
|
|
@@ -141,7 +142,7 @@ async function executeMiddleware(options) {
|
|
|
141
142
|
const hadBasePath = options.hadBasePath ?? (!options.basePath || hasBasePath(new URL(options.request.url).pathname, options.basePath));
|
|
142
143
|
const matchPathname = options.basePath ? stripBasePath(normalizedPathname, options.basePath) : normalizedPathname;
|
|
143
144
|
if (!matchesMiddleware(matchPathname, middlewareMatcher(options.module), options.request, options.i18nConfig)) return { continue: true };
|
|
144
|
-
const nextRequest = createNextRequest(options.request,
|
|
145
|
+
const nextRequest = createNextRequest(options.request, options.i18nConfig, options.basePath, options.trailingSlash, hadBasePath);
|
|
145
146
|
if (options.isDataRequest) Object.defineProperty(nextRequest, "__isData", {
|
|
146
147
|
enumerable: false,
|
|
147
148
|
value: true
|
|
@@ -58,6 +58,6 @@ declare function findMiddlewareFile(root: string, fileMatcher: ValidFileMatcher,
|
|
|
58
58
|
* @param request - The incoming Request object
|
|
59
59
|
* @returns Middleware result describing what action to take
|
|
60
60
|
*/
|
|
61
|
-
declare function runMiddleware(runner: ModuleRunner, middlewarePath: string, request: Request, i18nConfig?: NextI18nConfig | null, basePath?: string, trailingSlash?: boolean, isDataRequest?: boolean): Promise<MiddlewareResult>;
|
|
61
|
+
declare function runMiddleware(runner: ModuleRunner, middlewarePath: string, request: Request, i18nConfig?: NextI18nConfig | null, basePath?: string, trailingSlash?: boolean, isDataRequest?: boolean, normalizedPathname?: string): Promise<MiddlewareResult>;
|
|
62
62
|
//#endregion
|
|
63
63
|
export { findMiddlewareFile, isProxyFile, matchPattern, matchesMiddleware, resolveMiddlewareHandler, runMiddleware };
|
|
@@ -94,7 +94,7 @@ function isMiddlewareModule(value) {
|
|
|
94
94
|
* @param request - The incoming Request object
|
|
95
95
|
* @returns Middleware result describing what action to take
|
|
96
96
|
*/
|
|
97
|
-
async function runMiddleware(runner, middlewarePath, request, i18nConfig, basePath, trailingSlash, isDataRequest) {
|
|
97
|
+
async function runMiddleware(runner, middlewarePath, request, i18nConfig, basePath, trailingSlash, isDataRequest, normalizedPathname) {
|
|
98
98
|
const mod = await runner.import(middlewarePath);
|
|
99
99
|
if (!isMiddlewareModule(mod)) throw new Error(`Middleware module "${middlewarePath}" did not evaluate to an object.`);
|
|
100
100
|
return runGeneratedMiddleware({
|
|
@@ -106,6 +106,7 @@ async function runMiddleware(runner, middlewarePath, request, i18nConfig, basePa
|
|
|
106
106
|
isDataRequest,
|
|
107
107
|
isProxy: isProxyFile(middlewarePath),
|
|
108
108
|
module: mod,
|
|
109
|
+
normalizedPathname,
|
|
109
110
|
request,
|
|
110
111
|
trailingSlash
|
|
111
112
|
});
|
|
@@ -34,6 +34,16 @@ type NextDataMatch = {
|
|
|
34
34
|
* even when the buildId is wrong (so we can still return a 404 JSON response).
|
|
35
35
|
*/
|
|
36
36
|
declare function isNextDataPathname(pathname: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* WHATWG URL parsing removes TAB, LF, and CR characters. Reject paths where
|
|
39
|
+
* that normalization would manufacture the internal Pages data namespace.
|
|
40
|
+
*/
|
|
41
|
+
declare function urlParserCreatesPagesDataPath(pathname: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Keep URL-parser-ignored characters encoded until route matching decodes the
|
|
44
|
+
* captured parameter. Passing them literally to `new URL()` would remove them.
|
|
45
|
+
*/
|
|
46
|
+
declare function encodeUrlParserIgnoredCharacters(pathname: string): string;
|
|
37
47
|
/**
|
|
38
48
|
* Parse `/_next/data/<buildId>/<...page>.json` and return the normalized page
|
|
39
49
|
* pathname. Returns `null` if the pathname does not match the pattern or if
|
|
@@ -120,4 +130,4 @@ type NormalizePagesDataRequestResult = {
|
|
|
120
130
|
*/
|
|
121
131
|
declare function normalizePagesDataRequest(request: Request, buildId: string | null, basePath?: string, trailingSlash?: boolean): NormalizePagesDataRequestResult;
|
|
122
132
|
//#endregion
|
|
123
|
-
export { buildMiddlewarePrefetchSkipResponse, buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizeNextDataPagePathname, normalizePagesDataRequest, parseNextDataPathname };
|
|
133
|
+
export { buildMiddlewarePrefetchSkipResponse, buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, normalizePagesDataRequest, parseNextDataPathname, urlParserCreatesPagesDataPath };
|
|
@@ -32,6 +32,21 @@ function isNextDataPathname(pathname) {
|
|
|
32
32
|
return pathname.startsWith(NEXT_DATA_PREFIX) && pathname.endsWith(NEXT_DATA_SUFFIX);
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
+
* WHATWG URL parsing removes TAB, LF, and CR characters. Reject paths where
|
|
36
|
+
* that normalization would manufacture the internal Pages data namespace.
|
|
37
|
+
*/
|
|
38
|
+
function urlParserCreatesPagesDataPath(pathname) {
|
|
39
|
+
const parsedPathname = pathname.replaceAll(" ", "").replaceAll("\n", "").replaceAll("\r", "");
|
|
40
|
+
return pathname !== parsedPathname && !isNextDataPathname(pathname) && isNextDataPathname(parsedPathname);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Keep URL-parser-ignored characters encoded until route matching decodes the
|
|
44
|
+
* captured parameter. Passing them literally to `new URL()` would remove them.
|
|
45
|
+
*/
|
|
46
|
+
function encodeUrlParserIgnoredCharacters(pathname) {
|
|
47
|
+
return pathname.replaceAll(" ", "%09").replaceAll("\n", "%0A").replaceAll("\r", "%0D");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
35
50
|
* Parse `/_next/data/<buildId>/<...page>.json` and return the normalized page
|
|
36
51
|
* pathname. Returns `null` if the pathname does not match the pattern or if
|
|
37
52
|
* the buildId segment does not match the server's buildId.
|
|
@@ -168,4 +183,4 @@ function normalizePagesDataRequest(request, buildId, basePath = "", trailingSlas
|
|
|
168
183
|
};
|
|
169
184
|
}
|
|
170
185
|
//#endregion
|
|
171
|
-
export { buildMiddlewarePrefetchSkipResponse, buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizeNextDataPagePathname, normalizePagesDataRequest, parseNextDataPathname };
|
|
186
|
+
export { buildMiddlewarePrefetchSkipResponse, buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, normalizePagesDataRequest, parseNextDataPathname, urlParserCreatesPagesDataPath };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { NextRouter } from "../shims/router.js";
|
|
2
|
+
|
|
1
3
|
//#region src/server/pages-get-initial-props.d.ts
|
|
2
4
|
type PagesGetInitialPropsContext = {
|
|
3
5
|
req?: unknown;
|
|
@@ -10,6 +12,16 @@ type PagesGetInitialPropsContext = {
|
|
|
10
12
|
locales?: string[];
|
|
11
13
|
defaultLocale?: string;
|
|
12
14
|
} & Record<string, unknown>;
|
|
15
|
+
type PagesGetInitialPropsRouter = Omit<Pick<NextRouter, "route" | "pathname" | "query" | "asPath">, "query"> & {
|
|
16
|
+
query: Record<string, unknown>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Build the URL-state subset of Next.js's ServerRouter used by isolated
|
|
20
|
+
* initial-props helpers. Real request handlers pass their full `next/router`
|
|
21
|
+
* instance; this fallback keeps direct helper callers and tests aligned with
|
|
22
|
+
* the same required fields.
|
|
23
|
+
*/
|
|
24
|
+
declare function createPagesGetInitialPropsRouter(pathname: string, query: Record<string, unknown>, asPath: string): PagesGetInitialPropsRouter;
|
|
13
25
|
declare function hasPagesGetInitialProps(component: unknown): boolean;
|
|
14
26
|
declare function isResponseSent(res: unknown): boolean;
|
|
15
27
|
declare function loadPagesGetInitialProps(component: unknown, context: PagesGetInitialPropsContext): Promise<Record<string, unknown> | null>;
|
|
@@ -47,7 +59,8 @@ type DevAppInitialPropsContext = {
|
|
|
47
59
|
res: unknown;
|
|
48
60
|
pathname: string;
|
|
49
61
|
query: Record<string, unknown>;
|
|
50
|
-
asPath: string;
|
|
62
|
+
asPath: string; /** The request-scoped `next/router` server instance when available. */
|
|
63
|
+
router?: PagesGetInitialPropsRouter;
|
|
51
64
|
locale?: string;
|
|
52
65
|
locales?: string[];
|
|
53
66
|
defaultLocale?: string;
|
|
@@ -64,4 +77,4 @@ type DevAppInitialPropsContext = {
|
|
|
64
77
|
*/
|
|
65
78
|
declare function loadDevAppInitialProps(ctx: DevAppInitialPropsContext): Promise<DevAppInitialPropsResult>;
|
|
66
79
|
//#endregion
|
|
67
|
-
export { DevAppInitialPropsContext, DevAppInitialPropsResult, hasPagesGetInitialProps, isResponseSent, loadDevAppInitialProps, loadPagesGetInitialProps };
|
|
80
|
+
export { DevAppInitialPropsContext, DevAppInitialPropsResult, PagesGetInitialPropsRouter, createPagesGetInitialPropsRouter, hasPagesGetInitialProps, isResponseSent, loadDevAppInitialProps, loadPagesGetInitialProps };
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
//#region src/server/pages-get-initial-props.ts
|
|
2
|
+
/**
|
|
3
|
+
* Build the URL-state subset of Next.js's ServerRouter used by isolated
|
|
4
|
+
* initial-props helpers. Real request handlers pass their full `next/router`
|
|
5
|
+
* instance; this fallback keeps direct helper callers and tests aligned with
|
|
6
|
+
* the same required fields.
|
|
7
|
+
*/
|
|
8
|
+
function createPagesGetInitialPropsRouter(pathname, query, asPath) {
|
|
9
|
+
return {
|
|
10
|
+
route: pathname.replace(/\/$/, "") || "/",
|
|
11
|
+
pathname,
|
|
12
|
+
query,
|
|
13
|
+
asPath
|
|
14
|
+
};
|
|
15
|
+
}
|
|
2
16
|
function isObjectLike(value) {
|
|
3
17
|
return typeof value === "object" && value !== null || typeof value === "function";
|
|
4
18
|
}
|
|
@@ -61,11 +75,7 @@ async function loadDevAppInitialProps(ctx) {
|
|
|
61
75
|
const initialProps = await loadPagesGetInitialProps(ctx.appComponent, {
|
|
62
76
|
AppTree: ctx.appTree,
|
|
63
77
|
Component: ctx.component,
|
|
64
|
-
router:
|
|
65
|
-
pathname: ctx.pathname,
|
|
66
|
-
query: ctx.query,
|
|
67
|
-
asPath: ctx.asPath
|
|
68
|
-
},
|
|
78
|
+
router: ctx.router ?? createPagesGetInitialPropsRouter(ctx.pathname, ctx.query, ctx.asPath),
|
|
69
79
|
ctx: {
|
|
70
80
|
req: ctx.req,
|
|
71
81
|
res: ctx.res,
|
|
@@ -89,4 +99,4 @@ async function loadDevAppInitialProps(ctx) {
|
|
|
89
99
|
};
|
|
90
100
|
}
|
|
91
101
|
//#endregion
|
|
92
|
-
export { hasPagesGetInitialProps, isResponseSent, loadDevAppInitialProps, loadPagesGetInitialProps };
|
|
102
|
+
export { createPagesGetInitialPropsRouter, hasPagesGetInitialProps, isResponseSent, loadDevAppInitialProps, loadPagesGetInitialProps };
|
|
@@ -3,6 +3,7 @@ import { VinextNextData } from "../client/vinext-next-data.js";
|
|
|
3
3
|
import { CachedPagesValue } from "../shims/cache-handler.js";
|
|
4
4
|
import { ISRCacheEntry } from "./isr-cache.js";
|
|
5
5
|
import { PagesPreviewData } from "./pages-preview.js";
|
|
6
|
+
import { PagesGetInitialPropsRouter } from "./pages-get-initial-props.js";
|
|
6
7
|
import { PagesGsspResponse, PagesI18nRenderContext, PagesNextDataExtras } from "./pages-page-response.js";
|
|
7
8
|
import { ReactNode } from "react";
|
|
8
9
|
|
|
@@ -161,7 +162,8 @@ type ResolvePagesPageDataOptions = {
|
|
|
161
162
|
deploymentId?: string;
|
|
162
163
|
htmlLimitedBots?: string;
|
|
163
164
|
pageModule: PagesPageModule;
|
|
164
|
-
AppComponent?: unknown;
|
|
165
|
+
AppComponent?: unknown; /** The request-scoped `next/router` server instance when available. */
|
|
166
|
+
router?: PagesGetInitialPropsRouter;
|
|
165
167
|
params: Record<string, unknown>;
|
|
166
168
|
query: Record<string, unknown>;
|
|
167
169
|
asPath?: string;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
1
2
|
import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
3
|
+
import { isDangerousScheme } from "../shims/url-safety.js";
|
|
2
4
|
import { buildCacheStateHeaders } from "./cache-headers.js";
|
|
3
5
|
import { isUnknownRecord } from "../utils/record.js";
|
|
4
6
|
import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
@@ -6,7 +8,7 @@ import { decideIsr } from "./isr-decision.js";
|
|
|
6
8
|
import { buildPagesCacheValue } from "./isr-cache.js";
|
|
7
9
|
import { normalizeStaticPathname } from "../routing/route-pattern.js";
|
|
8
10
|
import { buildPagesNextDataScript, etagMatches, generatePagesETag, isPagesStreamingBot, requestsNoCache } from "./pages-page-response.js";
|
|
9
|
-
import { hasPagesGetInitialProps, isResponseSent, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
11
|
+
import { createPagesGetInitialPropsRouter, hasPagesGetInitialProps, isResponseSent, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
10
12
|
import { buildNextDataPropsJsonResponse } from "./pages-data-route.js";
|
|
11
13
|
import { isSerializableProps } from "./pages-serializable-props.js";
|
|
12
14
|
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
@@ -57,11 +59,7 @@ async function loadPagesAppInitialRenderProps(options, getSharedReqRes) {
|
|
|
57
59
|
const initialProps = await loadPagesGetInitialProps(options.AppComponent, {
|
|
58
60
|
AppTree: options.createAppTree ?? options.createPageElement,
|
|
59
61
|
Component: options.pageModule.default,
|
|
60
|
-
router:
|
|
61
|
-
pathname: options.routePattern,
|
|
62
|
-
query: options.query,
|
|
63
|
-
asPath: options.asPath ?? options.routeUrl
|
|
64
|
-
},
|
|
62
|
+
router: options.router ?? createPagesGetInitialPropsRouter(options.routePattern, options.query, options.asPath ?? options.routeUrl),
|
|
65
63
|
ctx: {
|
|
66
64
|
req,
|
|
67
65
|
res,
|
|
@@ -111,6 +109,17 @@ async function loadPagesAppInitialRenderProps(options, getSharedReqRes) {
|
|
|
111
109
|
*/
|
|
112
110
|
function buildPagesRedirectResponse(redirect, options, props = { pageProps: {} }) {
|
|
113
111
|
const destination = options.sanitizeDestination(redirect.destination);
|
|
112
|
+
if (isDangerousScheme(destination)) {
|
|
113
|
+
const headers = new Headers({
|
|
114
|
+
"Cache-Control": "private, no-cache, no-store, max-age=0, must-revalidate",
|
|
115
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
116
|
+
});
|
|
117
|
+
if (options.deploymentId) headers.set(NEXTJS_DEPLOYMENT_ID_HEADER, options.deploymentId);
|
|
118
|
+
return new Response("Invalid redirect destination", {
|
|
119
|
+
status: 500,
|
|
120
|
+
headers
|
|
121
|
+
});
|
|
122
|
+
}
|
|
114
123
|
if (options.isDataReq) {
|
|
115
124
|
const init = { headers: {} };
|
|
116
125
|
if (options.deploymentId) init.headers[NEXTJS_DEPLOYMENT_ID_HEADER] = options.deploymentId;
|
|
@@ -152,7 +161,7 @@ function getPagesRouteParams(routePattern) {
|
|
|
152
161
|
}).filter((param) => param !== null);
|
|
153
162
|
}
|
|
154
163
|
function matchesPagesStaticPath(pathEntry, params, routeParams, routeUrl) {
|
|
155
|
-
if (typeof pathEntry === "string") return normalizeStaticPathname(pathEntry) === normalizeStaticPathname(routeUrl);
|
|
164
|
+
if (typeof pathEntry === "string") return normalizePathnameForRouteMatch(normalizeStaticPathname(pathEntry)) === normalizePathnameForRouteMatch(normalizeStaticPathname(routeUrl));
|
|
156
165
|
const entryParams = pathEntry.params;
|
|
157
166
|
if (entryParams === void 0 || entryParams === null) return false;
|
|
158
167
|
return routeParams.every(({ key, repeat, optional }) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RenderPageEnhancers } from "./pages-document-initial-props.js";
|
|
2
|
+
import { PagesGetInitialPropsRouter } from "./pages-get-initial-props.js";
|
|
2
3
|
import { PagesPageModule } from "./pages-page-data.js";
|
|
3
4
|
import { ComponentType, ReactNode } from "react";
|
|
4
5
|
|
|
@@ -23,7 +24,7 @@ type I18nConfig = {
|
|
|
23
24
|
domain: string;
|
|
24
25
|
defaultLocale: string;
|
|
25
26
|
locales?: string[];
|
|
26
|
-
http?:
|
|
27
|
+
http?: true;
|
|
27
28
|
}>;
|
|
28
29
|
} | null;
|
|
29
30
|
type VinextConfigSubset = {
|
|
@@ -60,7 +61,8 @@ type CreatePagesPageHandlerOptions = {
|
|
|
60
61
|
*/
|
|
61
62
|
getPagesNavigationIsReadyFromSerializedState: ((routePattern: string | undefined, searchString: string, nextData?: Record<string, unknown>) => boolean) | null; /** `setI18nContext` from `vinext/i18n-context`. */
|
|
62
63
|
setI18nContext: ((ctx: Record<string, unknown>) => void) | null; /** `wrapWithRouterContext` from `next/router`. */
|
|
63
|
-
wrapWithRouterContext: ((element: ReactNode) => ReactNode) | null; /**
|
|
64
|
+
wrapWithRouterContext: ((element: ReactNode) => ReactNode) | null; /** Request-scoped `next/router` server instance. */
|
|
65
|
+
router?: PagesGetInitialPropsRouter; /** `resetSSRHead` from `next/head`. */
|
|
64
66
|
resetSSRHead: (() => void) | undefined; /** `getSSRHeadHTML` from `next/head`. */
|
|
65
67
|
getSSRHeadHTML: (() => string) | undefined; /** `setDocumentInitialHead` from `next/head`. */
|
|
66
68
|
setDocumentInitialHead: ((head: ReactNode[]) => void) | undefined; /** `flushPreloads` from `next/dynamic`. */
|
|
@@ -53,7 +53,7 @@ function buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domain
|
|
|
53
53
|
* accepts the same options shape the generated entry always passed inline.
|
|
54
54
|
*/
|
|
55
55
|
function createPagesPageHandler(opts) {
|
|
56
|
-
const { pageRoutes, errorPageRoute, matchRoute, i18nConfig, vinextConfig, buildId, hasMiddleware, appAssetPath, hasRewrites, setSSRContext, getPagesNavigationIsReadyFromSerializedState, setI18nContext, wrapWithRouterContext, resetSSRHead, getSSRHeadHTML, setDocumentInitialHead, flushPreloads, getFontLinks, getFontStyles, getFontPreloads, renderToReadableStream, renderIsrPassToStringAsync, safeJsonStringify, sanitizeDestination, createPageElement, enhancePageElement, AppComponent, DocumentComponent } = opts;
|
|
56
|
+
const { pageRoutes, errorPageRoute, matchRoute, i18nConfig, vinextConfig, buildId, hasMiddleware, appAssetPath, hasRewrites, setSSRContext, getPagesNavigationIsReadyFromSerializedState, setI18nContext, wrapWithRouterContext, router, resetSSRHead, getSSRHeadHTML, setDocumentInitialHead, flushPreloads, getFontLinks, getFontStyles, getFontPreloads, renderToReadableStream, renderIsrPassToStringAsync, safeJsonStringify, sanitizeDestination, createPageElement, enhancePageElement, AppComponent, DocumentComponent } = opts;
|
|
57
57
|
function renderToStringAsync(element) {
|
|
58
58
|
return renderToReadableStream(element).then((stream) => new Response(stream).text());
|
|
59
59
|
}
|
|
@@ -138,15 +138,18 @@ function createPagesPageHandler(opts) {
|
|
|
138
138
|
} else return buildDefaultPagesNotFoundResponse();
|
|
139
139
|
}
|
|
140
140
|
const { route, params } = match;
|
|
141
|
-
const
|
|
141
|
+
const pageModule = route.module;
|
|
142
|
+
const isStaticPropsRoute = typeof pageModule.getStaticProps === "function";
|
|
143
|
+
const isStaticPropsRender = isStaticPropsRoute && typeof pageModule.getServerSideProps !== "function";
|
|
144
|
+
const renderRouteUrl = isStaticPropsRender ? routeUrl.split("?")[0] : routeUrl;
|
|
145
|
+
const routerAsPathSource = isStaticPropsRender ? renderRouteUrl : renderAsPath ?? renderRouteUrl;
|
|
146
|
+
const routerAsPath = i18nConfig ? extractLocaleFromUrl(routerAsPathSource, i18nConfig, locale).url : routerAsPathSource;
|
|
142
147
|
return runWithRequestContext(createRequestContext({ executionContext: getRequestExecutionContext() }), async () => {
|
|
143
148
|
ensureFetchPatch();
|
|
144
149
|
try {
|
|
145
150
|
const routePattern = patternToNextFormat(route.pattern);
|
|
146
151
|
const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : void 0);
|
|
147
|
-
const query = mergeRouteParamsIntoQuery(parseQueryString(
|
|
148
|
-
const pageModule = route.module;
|
|
149
|
-
const isStaticPropsRoute = typeof pageModule.getStaticProps === "function";
|
|
152
|
+
const query = mergeRouteParamsIntoQuery(parseQueryString(renderRouteUrl), params);
|
|
150
153
|
const isOnDemandRevalidate = isOnDemandRevalidateRequest(request.headers.get(PRERENDER_REVALIDATE_HEADER));
|
|
151
154
|
const preview = isStaticPropsRoute || typeof pageModule.getServerSideProps === "function" ? getPagesPreviewState(request.headers.get("cookie"), { isOnDemandRevalidate }) : {
|
|
152
155
|
data: false,
|
|
@@ -161,7 +164,7 @@ function createPagesPageHandler(opts) {
|
|
|
161
164
|
}),
|
|
162
165
|
...previewData === false ? {} : { isPreview: true }
|
|
163
166
|
};
|
|
164
|
-
const navigationIsReady = typeof getPagesNavigationIsReadyFromSerializedState === "function" ? getPagesNavigationIsReadyFromSerializedState(routePattern,
|
|
167
|
+
const navigationIsReady = isStaticPropsRender ? false : typeof getPagesNavigationIsReadyFromSerializedState === "function" ? getPagesNavigationIsReadyFromSerializedState(routePattern, originalRequestUrl.search, pagesNextData) : true;
|
|
165
168
|
function applySSRContext(extra) {
|
|
166
169
|
if (typeof setSSRContext === "function") setSSRContext({
|
|
167
170
|
pathname: routePattern,
|
|
@@ -204,7 +207,7 @@ function createPagesPageHandler(opts) {
|
|
|
204
207
|
pageModuleUrl,
|
|
205
208
|
appModuleUrl,
|
|
206
209
|
hasMiddleware,
|
|
207
|
-
routeUrl
|
|
210
|
+
routeUrl: renderRouteUrl
|
|
208
211
|
}
|
|
209
212
|
};
|
|
210
213
|
const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareHeaders);
|
|
@@ -253,6 +256,7 @@ function createPagesPageHandler(opts) {
|
|
|
253
256
|
previewData,
|
|
254
257
|
pageModule,
|
|
255
258
|
AppComponent,
|
|
259
|
+
router,
|
|
256
260
|
params,
|
|
257
261
|
query,
|
|
258
262
|
asPath: routerAsPath,
|
|
@@ -260,7 +264,7 @@ function createPagesPageHandler(opts) {
|
|
|
260
264
|
renderIsrPassToStringAsync,
|
|
261
265
|
route: { isDynamic: route.isDynamic },
|
|
262
266
|
routePattern,
|
|
263
|
-
routeUrl,
|
|
267
|
+
routeUrl: renderRouteUrl,
|
|
264
268
|
runInFreshUnifiedContext(callback) {
|
|
265
269
|
return runWithRequestContext(createRequestContext({ executionContext: null }), async () => {
|
|
266
270
|
ensureFetchPatch();
|
|
@@ -309,15 +313,10 @@ function createPagesPageHandler(opts) {
|
|
|
309
313
|
const documentReqRes = serializedPagesNextData.autoExport === true ? null : pageDataResult.documentReqRes ?? createPageReqRes();
|
|
310
314
|
const isrRevalidateSeconds = pageDataResult.isrRevalidateSeconds;
|
|
311
315
|
const isFallbackRender = pageDataResult.isFallback === true;
|
|
312
|
-
if (isFallbackRender
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
asPath: routerAsPath,
|
|
316
|
+
if (isFallbackRender) applySSRContext({
|
|
317
|
+
query: {},
|
|
318
|
+
asPath: routePattern,
|
|
316
319
|
navigationIsReady: false,
|
|
317
|
-
locale,
|
|
318
|
-
locales: i18nConfig ? i18nConfig.locales : void 0,
|
|
319
|
-
defaultLocale: currentDefaultLocale,
|
|
320
|
-
domainLocales,
|
|
321
320
|
isFallback: true
|
|
322
321
|
});
|
|
323
322
|
if (isDataReq) {
|
|
@@ -404,7 +403,7 @@ function createPagesPageHandler(opts) {
|
|
|
404
403
|
resetSSRHead: typeof resetSSRHead === "function" ? resetSSRHead : void 0,
|
|
405
404
|
setDocumentInitialHead: typeof setDocumentInitialHead === "function" ? setDocumentInitialHead : void 0,
|
|
406
405
|
routePattern,
|
|
407
|
-
routeUrl,
|
|
406
|
+
routeUrl: renderRouteUrl,
|
|
408
407
|
safeJsonStringify,
|
|
409
408
|
scriptNonce,
|
|
410
409
|
statusCode: renderStatusCode,
|
|
@@ -72,7 +72,7 @@ function buildPagesNextDataScript(options) {
|
|
|
72
72
|
const nextDataPayload = {
|
|
73
73
|
props: options.props ?? { pageProps: options.pageProps },
|
|
74
74
|
page: options.routePattern,
|
|
75
|
-
query: options.params,
|
|
75
|
+
query: options.isFallback === true ? {} : options.params,
|
|
76
76
|
buildId: options.buildId,
|
|
77
77
|
isFallback: options.isFallback === true
|
|
78
78
|
};
|
|
@@ -7,9 +7,9 @@ import { PagesPageModule } from "./pages-page-data.js";
|
|
|
7
7
|
*
|
|
8
8
|
* The initial `router.isReady` value for the `next/navigation` compat hooks is
|
|
9
9
|
* derived from the page/_app data-fetching exports plus the configured-rewrites
|
|
10
|
-
* flag
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* flag. The client recomputes readiness from those flags and its live URL,
|
|
11
|
+
* matching the Pages Router constructor; server-only readiness remains in the
|
|
12
|
+
* request context. See `getPagesNavigationIsReadyFromSerializedState` in
|
|
13
13
|
* `shims/router.ts`.
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
@@ -44,6 +44,7 @@ type PagesPipelineDeps = {
|
|
|
44
44
|
hasMiddleware: boolean;
|
|
45
45
|
ctx?: unknown;
|
|
46
46
|
rawSearch?: string;
|
|
47
|
+
configMatchPathname?: string;
|
|
47
48
|
matchPageRoute?: ((pathname: string, request: Request) => PageRouteMatch | null) | null;
|
|
48
49
|
runMiddleware?: ((request: Request, ctx: unknown, opts: {
|
|
49
50
|
isDataRequest: boolean;
|