vinext 1.0.0-beta.1 → 1.0.0-beta.3

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.
Files changed (234) hide show
  1. package/README.md +10 -10
  2. package/dist/build/client-build-config.js +8 -1
  3. package/dist/build/report.d.ts +8 -1
  4. package/dist/build/report.js +12 -2
  5. package/dist/check.js +19 -2
  6. package/dist/cli.js +3 -2
  7. package/dist/config/config-matchers.d.ts +13 -37
  8. package/dist/config/config-matchers.js +35 -122
  9. package/dist/config/next-config.d.ts +15 -5
  10. package/dist/config/next-config.js +7 -1
  11. package/dist/config/request-context.d.ts +14 -0
  12. package/dist/config/request-context.js +26 -0
  13. package/dist/entries/app-browser-entry.d.ts +4 -10
  14. package/dist/entries/app-browser-entry.js +20 -4
  15. package/dist/entries/app-rsc-entry.js +30 -9
  16. package/dist/entries/app-rsc-manifest.js +36 -0
  17. package/dist/entries/pages-client-entry.js +0 -1
  18. package/dist/entries/pages-server-entry.js +13 -5
  19. package/dist/index.js +194 -101
  20. package/dist/init-cloudflare.d.ts +3 -1
  21. package/dist/init-cloudflare.js +59 -5
  22. package/dist/init.d.ts +6 -4
  23. package/dist/init.js +20 -22
  24. package/dist/plugins/extensionless-dynamic-import.js +23 -18
  25. package/dist/plugins/ignore-dynamic-requests.js +3 -1
  26. package/dist/plugins/import-meta-url.js +17 -6
  27. package/dist/plugins/og-assets.js +1 -1
  28. package/dist/plugins/require-context.js +20 -15
  29. package/dist/plugins/transform-cache.d.ts +19 -0
  30. package/dist/plugins/transform-cache.js +36 -0
  31. package/dist/routing/app-route-graph.d.ts +27 -11
  32. package/dist/routing/app-route-graph.js +158 -22
  33. package/dist/routing/app-router.js +12 -6
  34. package/dist/routing/file-matcher.d.ts +11 -22
  35. package/dist/routing/file-matcher.js +21 -33
  36. package/dist/routing/pages-router.js +23 -29
  37. package/dist/routing/route-matching.d.ts +14 -1
  38. package/dist/routing/route-matching.js +13 -1
  39. package/dist/routing/route-pattern.d.ts +2 -1
  40. package/dist/routing/route-pattern.js +7 -4
  41. package/dist/routing/route-trie.d.ts +5 -1
  42. package/dist/routing/route-trie.js +5 -2
  43. package/dist/server/api-handler.d.ts +2 -0
  44. package/dist/server/api-handler.js +3 -3
  45. package/dist/server/app-browser-entry.js +110 -37
  46. package/dist/server/app-browser-history-controller.d.ts +1 -1
  47. package/dist/server/app-browser-history-controller.js +3 -3
  48. package/dist/server/app-browser-navigation-controller.d.ts +23 -21
  49. package/dist/server/app-browser-navigation-controller.js +2 -2
  50. package/dist/server/app-browser-state.js +1 -1
  51. package/dist/server/app-browser-visible-commit.js +1 -1
  52. package/dist/server/app-fallback-renderer.d.ts +3 -0
  53. package/dist/server/app-fallback-renderer.js +4 -2
  54. package/dist/server/app-middleware.js +2 -1
  55. package/dist/server/app-page-boundary-render.d.ts +12 -1
  56. package/dist/server/app-page-boundary-render.js +84 -2
  57. package/dist/server/app-page-cache-finalizer.d.ts +1 -1
  58. package/dist/server/app-page-cache-finalizer.js +1 -1
  59. package/dist/server/app-page-cache.d.ts +2 -2
  60. package/dist/server/app-page-cache.js +16 -2
  61. package/dist/server/app-page-dispatch.d.ts +19 -2
  62. package/dist/server/app-page-dispatch.js +45 -23
  63. package/dist/server/app-page-element-builder.d.ts +9 -2
  64. package/dist/server/app-page-element-builder.js +144 -33
  65. package/dist/server/app-page-head.d.ts +56 -4
  66. package/dist/server/app-page-head.js +216 -85
  67. package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
  68. package/dist/server/app-page-http-access-fallback-metadata.js +114 -0
  69. package/dist/server/app-page-probe.d.ts +4 -0
  70. package/dist/server/app-page-probe.js +6 -2
  71. package/dist/server/app-page-render.d.ts +2 -2
  72. package/dist/server/app-page-render.js +1 -1
  73. package/dist/server/app-page-request.d.ts +15 -0
  74. package/dist/server/app-page-request.js +134 -14
  75. package/dist/server/app-page-response.js +1 -1
  76. package/dist/server/app-page-route-wiring.d.ts +16 -0
  77. package/dist/server/app-page-route-wiring.js +254 -52
  78. package/dist/server/app-pages-bridge.d.ts +1 -1
  79. package/dist/server/app-pages-bridge.js +2 -1
  80. package/dist/server/app-post-middleware-context.d.ts +1 -1
  81. package/dist/server/app-post-middleware-context.js +1 -1
  82. package/dist/server/app-route-handler-cache.js +4 -0
  83. package/dist/server/app-route-handler-dispatch.js +40 -20
  84. package/dist/server/app-route-handler-execution.d.ts +6 -1
  85. package/dist/server/app-route-handler-execution.js +42 -16
  86. package/dist/server/app-route-handler-policy.d.ts +2 -0
  87. package/dist/server/app-route-handler-policy.js +3 -3
  88. package/dist/server/app-route-handler-response.js +1 -1
  89. package/dist/server/app-route-module-loader.d.ts +9 -1
  90. package/dist/server/app-route-module-loader.js +4 -0
  91. package/dist/server/app-router-entry.js +6 -3
  92. package/dist/server/app-rsc-cache-busting.d.ts +1 -1
  93. package/dist/server/app-rsc-errors.d.ts +1 -1
  94. package/dist/server/app-rsc-errors.js +22 -2
  95. package/dist/server/app-rsc-handler.d.ts +10 -5
  96. package/dist/server/app-rsc-handler.js +73 -33
  97. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  98. package/dist/server/app-rsc-request-normalization.js +8 -2
  99. package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
  100. package/dist/server/app-rsc-response-finalizer.js +5 -11
  101. package/dist/server/app-rsc-route-matching.d.ts +29 -0
  102. package/dist/server/app-rsc-route-matching.js +93 -11
  103. package/dist/server/app-segment-config.js +13 -3
  104. package/dist/server/app-server-action-execution.d.ts +3 -1
  105. package/dist/server/app-server-action-execution.js +9 -7
  106. package/dist/server/app-ssr-entry.js +6 -6
  107. package/dist/server/app-ssr-stream.d.ts +1 -7
  108. package/dist/server/app-ssr-stream.js +2 -10
  109. package/dist/server/cache-control.d.ts +2 -2
  110. package/dist/server/cache-control.js +2 -1
  111. package/dist/server/config-headers.d.ts +24 -0
  112. package/dist/server/config-headers.js +52 -0
  113. package/dist/server/dev-initial-server-error.d.ts +1 -1
  114. package/dist/server/dev-server.d.ts +3 -1
  115. package/dist/server/dev-server.js +170 -321
  116. package/dist/server/headers.d.ts +2 -2
  117. package/dist/server/headers.js +4 -3
  118. package/dist/server/isr-cache.d.ts +11 -34
  119. package/dist/server/isr-cache.js +33 -43
  120. package/dist/server/isr-decision.d.ts +2 -2
  121. package/dist/server/middleware-matcher-pattern.d.ts +22 -0
  122. package/dist/server/middleware-matcher-pattern.js +219 -0
  123. package/dist/server/middleware-matcher.d.ts +2 -7
  124. package/dist/server/middleware-matcher.js +13 -60
  125. package/dist/server/middleware-path-to-regexp.d.ts +14 -0
  126. package/dist/server/middleware-path-to-regexp.js +228 -0
  127. package/dist/server/middleware-runtime.js +4 -3
  128. package/dist/server/middleware.d.ts +1 -1
  129. package/dist/server/middleware.js +2 -1
  130. package/dist/server/pages-api-route.d.ts +2 -0
  131. package/dist/server/pages-api-route.js +4 -1
  132. package/dist/server/pages-data-route.d.ts +11 -1
  133. package/dist/server/pages-data-route.js +16 -1
  134. package/dist/server/pages-dev-hydration.js +0 -1
  135. package/dist/server/pages-get-initial-props.d.ts +16 -3
  136. package/dist/server/pages-get-initial-props.js +17 -10
  137. package/dist/server/pages-i18n.js +64 -16
  138. package/dist/server/pages-node-compat.d.ts +2 -0
  139. package/dist/server/pages-node-compat.js +7 -3
  140. package/dist/server/pages-page-data.d.ts +64 -10
  141. package/dist/server/pages-page-data.js +349 -80
  142. package/dist/server/pages-page-handler.d.ts +9 -3
  143. package/dist/server/pages-page-handler.js +131 -36
  144. package/dist/server/pages-page-response.d.ts +5 -3
  145. package/dist/server/pages-page-response.js +24 -27
  146. package/dist/server/pages-readiness.d.ts +3 -3
  147. package/dist/server/pages-request-pipeline.d.ts +8 -0
  148. package/dist/server/pages-request-pipeline.js +30 -12
  149. package/dist/server/pages-revalidate.d.ts +1 -1
  150. package/dist/server/pages-revalidate.js +54 -8
  151. package/dist/server/pages-router-entry.d.ts +1 -0
  152. package/dist/server/pages-router-entry.js +16 -4
  153. package/dist/server/prerender-route-params.js +2 -2
  154. package/dist/server/prod-server.d.ts +3 -5
  155. package/dist/server/prod-server.js +72 -35
  156. package/dist/server/request-pipeline.d.ts +15 -29
  157. package/dist/server/request-pipeline.js +24 -59
  158. package/dist/server/revalidation-host.d.ts +11 -0
  159. package/dist/server/revalidation-host.js +19 -0
  160. package/dist/server/rsc-stream-hints.js +122 -18
  161. package/dist/server/worker-revalidation-context.d.ts +13 -0
  162. package/dist/server/worker-revalidation-context.js +29 -0
  163. package/dist/shims/app.d.ts +1 -1
  164. package/dist/shims/cache-handler.d.ts +1 -1
  165. package/dist/shims/cache-handler.js +10 -7
  166. package/dist/shims/cache-request-state.d.ts +27 -1
  167. package/dist/shims/cache-request-state.js +60 -1
  168. package/dist/shims/cache-runtime.d.ts +18 -1
  169. package/dist/shims/cache-runtime.js +26 -8
  170. package/dist/shims/cache.d.ts +5 -5
  171. package/dist/shims/cache.js +27 -11
  172. package/dist/shims/document.d.ts +42 -83
  173. package/dist/shims/document.js +62 -53
  174. package/dist/shims/dynamic.d.ts +5 -25
  175. package/dist/shims/dynamic.js +29 -8
  176. package/dist/shims/error.d.ts +1 -1
  177. package/dist/shims/error.js +2 -2
  178. package/dist/shims/fetch-cache.js +13 -4
  179. package/dist/shims/font-google-base.d.ts +11 -4
  180. package/dist/shims/font-google-base.js +17 -8
  181. package/dist/shims/font-local.d.ts +10 -3
  182. package/dist/shims/font-local.js +41 -10
  183. package/dist/shims/head.d.ts +13 -2
  184. package/dist/shims/head.js +3 -3
  185. package/dist/shims/headers.d.ts +37 -43
  186. package/dist/shims/headers.js +183 -74
  187. package/dist/shims/image.d.ts +27 -37
  188. package/dist/shims/image.js +21 -14
  189. package/dist/shims/internal/cookie-serialize.d.ts +12 -9
  190. package/dist/shims/internal/cookie-serialize.js +10 -7
  191. package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
  192. package/dist/shims/internal/interpolate-as.d.ts +15 -1
  193. package/dist/shims/internal/interpolate-as.js +27 -2
  194. package/dist/shims/internal/utils.d.ts +3 -3
  195. package/dist/shims/legacy-image.d.ts +3 -37
  196. package/dist/shims/legacy-image.js +6 -16
  197. package/dist/shims/link.d.ts +15 -22
  198. package/dist/shims/link.js +34 -13
  199. package/dist/shims/metadata.d.ts +7 -17
  200. package/dist/shims/metadata.js +74 -24
  201. package/dist/shims/navigation-context-state.d.ts +1 -1
  202. package/dist/shims/navigation.d.ts +7 -3
  203. package/dist/shims/navigation.js +25 -14
  204. package/dist/shims/navigation.react-server.js +1 -1
  205. package/dist/shims/next-shims-augmentations.d.ts +1 -0
  206. package/dist/shims/next-shims-public.d.ts +1 -0
  207. package/dist/shims/public-shim-map.json.js +103 -0
  208. package/dist/shims/readonly-url-search-params.d.ts +3 -3
  209. package/dist/shims/readonly-url-search-params.js +3 -3
  210. package/dist/shims/request-context.d.ts +4 -1
  211. package/dist/shims/request-state-types.d.ts +1 -1
  212. package/dist/shims/router.d.ts +55 -21
  213. package/dist/shims/router.js +180 -44
  214. package/dist/shims/script.d.ts +6 -10
  215. package/dist/shims/script.js +7 -4
  216. package/dist/shims/server.d.ts +50 -26
  217. package/dist/shims/server.js +193 -55
  218. package/dist/shims/unified-request-context.d.ts +22 -3
  219. package/dist/shims/unified-request-context.js +84 -1
  220. package/dist/shims/url-safety.d.ts +1 -1
  221. package/dist/shims/url-safety.js +2 -2
  222. package/dist/typegen.d.ts +8 -2
  223. package/dist/typegen.js +76 -15
  224. package/dist/utils/cache-control-metadata.d.ts +2 -1
  225. package/dist/utils/cache-control-metadata.js +5 -1
  226. package/dist/utils/domain-locale.d.ts +2 -2
  227. package/dist/utils/external-url.d.ts +5 -0
  228. package/dist/utils/external-url.js +7 -0
  229. package/dist/utils/html-limited-bots.js +1 -1
  230. package/dist/utils/protocol-headers.d.ts +7 -1
  231. package/dist/utils/protocol-headers.js +7 -1
  232. package/dist/utils/regex-safety.d.ts +8 -0
  233. package/dist/utils/regex-safety.js +737 -0
  234. package/package.json +13 -2
@@ -1,19 +1,21 @@
1
- import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
1
+ import { closeAfterResponse, closeAfterResponseWithBody, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import { patternToNextFormat } from "../routing/route-validation.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
- import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
4
+ import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
5
+ import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER } from "./headers.js";
5
6
  import { reportRequestError } from "./instrumentation.js";
6
7
  import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, applyCdnResponseHeaders, shouldUseNextDeployCacheControl } from "./cache-control.js";
7
8
  import { buildMissIsrCacheControl } from "./isr-decision.js";
8
- import { PRERENDER_REVALIDATE_HEADER, isOnDemandRevalidateRequest, isrCacheKey, isrGet, isrSet, triggerBackgroundRegeneration } from "./isr-cache.js";
9
+ import { coalesceOnDemandRevalidation, isOnDemandRevalidateRequest, isrCacheKey, isrGet, isrSet, triggerBackgroundRegeneration } from "./isr-cache.js";
10
+ import { encodeCacheTag } from "../utils/encode-cache-tag.js";
9
11
  import { ensureFetchPatch } from "../shims/fetch-cache.js";
10
- import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
11
12
  import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
12
13
  import { getScriptNonceFromHeaderSources } from "./csp.js";
13
14
  import { extractLocaleFromUrl, resolvePagesI18nRequest } from "./pages-i18n.js";
14
15
  import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
15
16
  import { buildPagesReadinessNextData } from "./pages-readiness.js";
16
17
  import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
18
+ import { setCacheStateHeaders } from "./cache-headers.js";
17
19
  import { renderPagesPageResponse } from "./pages-page-response.js";
18
20
  import { hasPagesGetInitialProps } from "./pages-get-initial-props.js";
19
21
  import { buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, normalizePagesDataRequest, parseNextDataPathname } from "./pages-data-route.js";
@@ -25,7 +27,12 @@ import { createPagesReqRes } from "./pages-node-compat.js";
25
27
  function finalizePagesPreviewResponse(response, preview) {
26
28
  if (preview.data === false && !preview.shouldClear) return response;
27
29
  const headers = new Headers(response.headers);
28
- if (preview.data !== false) headers.set("Cache-Control", PAGES_PREVIEW_CACHE_CONTROL);
30
+ if (preview.data !== false) {
31
+ headers.set("Cache-Control", PAGES_PREVIEW_CACHE_CONTROL);
32
+ headers.delete("CDN-Cache-Control");
33
+ headers.delete("Cloudflare-CDN-Cache-Control");
34
+ headers.delete("Cache-Tag");
35
+ }
29
36
  if (preview.shouldClear) appendPagesPreviewClearCookies(headers);
30
37
  return new Response(response.body, {
31
38
  headers,
@@ -33,6 +40,41 @@ function finalizePagesPreviewResponse(response, preview) {
33
40
  statusText: response.statusText
34
41
  });
35
42
  }
43
+ function withPagesCacheState(response, state) {
44
+ const headers = new Headers(response.headers);
45
+ if (state === "REVALIDATED") {
46
+ headers.set(NEXTJS_CACHE_HEADER, state);
47
+ headers.delete(VINEXT_CACHE_HEADER);
48
+ } else setCacheStateHeaders(headers, state);
49
+ return new Response(response.body, {
50
+ headers,
51
+ status: response.status,
52
+ statusText: response.statusText
53
+ });
54
+ }
55
+ function applyPagesErrorCachePolicy(response, revalidateSeconds, expireSeconds, cacheTagPathname) {
56
+ const headers = new Headers(response.headers);
57
+ const browserPolicy = headers.get("Cache-Control");
58
+ const sharedPolicies = [headers.get("CDN-Cache-Control"), headers.get("Cloudflare-CDN-Cache-Control")];
59
+ const hasCacheableSharedPolicy = sharedPolicies.some((value) => value && /(?:^|,)\s*s-maxage\s*=/i.test(value));
60
+ if (sharedPolicies.some((value) => value && /(?:private|no-store|no-cache)/i.test(value)) || !hasCacheableSharedPolicy && browserPolicy && /(?:private|no-store|no-cache)/i.test(browserPolicy)) return response;
61
+ headers.delete("CDN-Cache-Control");
62
+ headers.delete("Cloudflare-CDN-Cache-Control");
63
+ headers.delete("Cache-Tag");
64
+ if (revalidateSeconds === void 0) applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
65
+ else {
66
+ const stem = cacheTagPathname.endsWith("/") ? cacheTagPathname.slice(0, -1) : cacheTagPathname;
67
+ applyCdnResponseHeaders(headers, {
68
+ cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds),
69
+ tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
70
+ });
71
+ }
72
+ return new Response(response.body, {
73
+ headers,
74
+ status: response.status,
75
+ statusText: response.statusText
76
+ });
77
+ }
36
78
  function shouldEmitPagesClientTraceMetadata(pageModule, appComponent) {
37
79
  if (typeof pageModule.getServerSideProps === "function") return true;
38
80
  if (typeof pageModule.getStaticProps === "function") return false;
@@ -53,7 +95,7 @@ function buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domain
53
95
  * accepts the same options shape the generated entry always passed inline.
54
96
  */
55
97
  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;
98
+ 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
99
  function renderToStringAsync(element) {
58
100
  return renderToReadableStream(element).then((stream) => new Response(stream).text());
59
101
  }
@@ -122,6 +164,7 @@ function createPagesPageHandler(opts) {
122
164
  route: options.__forcedRoute,
123
165
  params: {}
124
166
  } : matchRoute(routeUrl, pageRoutes);
167
+ let isRouteMissErrorRender = false;
125
168
  let renderStatusCodeOverride = statusCode;
126
169
  let renderAsPath = asPath;
127
170
  if (!match) {
@@ -133,21 +176,52 @@ function createPagesPageHandler(opts) {
133
176
  route: notFoundRoute,
134
177
  params: {}
135
178
  };
179
+ isRouteMissErrorRender = true;
136
180
  renderStatusCodeOverride = 404;
137
181
  renderAsPath = routeUrl;
138
182
  } else return buildDefaultPagesNotFoundResponse();
139
183
  }
140
184
  const { route, params } = match;
141
- const routerAsPath = i18nConfig ? extractLocaleFromUrl(renderAsPath ?? routeUrl, i18nConfig, locale).url : renderAsPath ?? routeUrl;
142
- return runWithRequestContext(createRequestContext({ executionContext: getRequestExecutionContext() }), async () => {
185
+ const pageModule = route.module;
186
+ const isStaticPropsRoute = typeof pageModule.getStaticProps === "function";
187
+ const isStaticPropsRender = isStaticPropsRoute && typeof pageModule.getServerSideProps !== "function";
188
+ if (!options?.__skipOnDemandCoalesce && !options?.__forcedRoute && isStaticPropsRoute && isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate"))) {
189
+ const snapshot = await coalesceOnDemandRevalidation(pageIsrCacheKey("pages", routeUrl.split("?")[0]), async () => {
190
+ const response = await renderPage(request, url, manifest, middlewareHeaders, {
191
+ ...options,
192
+ __skipOnDemandCoalesce: true
193
+ });
194
+ return {
195
+ body: request.method === "HEAD" || response.status === 204 || response.status === 304 ? null : new Uint8Array(await response.arrayBuffer()),
196
+ headers: [...response.headers.entries()],
197
+ status: response.status,
198
+ statusText: response.statusText
199
+ };
200
+ });
201
+ return new Response(snapshot.body?.slice() ?? null, {
202
+ headers: snapshot.headers,
203
+ status: snapshot.status,
204
+ statusText: snapshot.statusText
205
+ });
206
+ }
207
+ const renderRouteUrl = isStaticPropsRender ? routeUrl.split("?")[0] : routeUrl;
208
+ const routerAsPathSource = isStaticPropsRender ? renderRouteUrl : renderAsPath ?? renderRouteUrl;
209
+ const routerAsPath = i18nConfig ? extractLocaleFromUrl(routerAsPathSource, i18nConfig, locale).url : routerAsPathSource;
210
+ const uCtx = createRequestContext({ executionContext: getRequestExecutionContext() });
211
+ return closeAfterResponseWithBody(await runWithRequestContext(uCtx, async () => {
143
212
  ensureFetchPatch();
144
213
  try {
145
214
  const routePattern = patternToNextFormat(route.pattern);
146
215
  const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : void 0);
147
- const query = mergeRouteParamsIntoQuery(parseQueryString(routeUrl), params);
148
- const pageModule = route.module;
149
- const isStaticPropsRoute = typeof pageModule.getStaticProps === "function";
216
+ const isrCachePathname = isStaticPropsRender && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error") ? routePattern : renderRouteUrl.split("?")[0];
217
+ const isNotFoundErrorRender = routePattern === "/404" || routePattern === "/_error" && renderStatusCode === 404;
218
+ const isStatusErrorRender = isNotFoundErrorRender || routePattern === "/500" || routePattern === "/_error" && renderStatusCode === 500;
219
+ const errorPageRevalidateSeconds = isNotFoundErrorRender ? options?.__notFoundRevalidateSeconds : void 0;
220
+ const errorPageExpireSeconds = isNotFoundErrorRender ? options?.__notFoundExpireSeconds : void 0;
221
+ const errorResponseCachePathname = options?.__notFoundCachePathname ?? isrCachePathname;
222
+ const query = mergeRouteParamsIntoQuery(parseQueryString(renderRouteUrl), params);
150
223
  const isOnDemandRevalidate = isOnDemandRevalidateRequest(request.headers.get(PRERENDER_REVALIDATE_HEADER));
224
+ const revalidateOnlyGenerated = isOnDemandRevalidate && request.headers.has("x-prerender-revalidate-if-generated");
151
225
  const preview = isStaticPropsRoute || typeof pageModule.getServerSideProps === "function" ? getPagesPreviewState(request.headers.get("cookie"), { isOnDemandRevalidate }) : {
152
226
  data: false,
153
227
  shouldClear: false
@@ -161,7 +235,7 @@ function createPagesPageHandler(opts) {
161
235
  }),
162
236
  ...previewData === false ? {} : { isPreview: true }
163
237
  };
164
- const navigationIsReady = typeof getPagesNavigationIsReadyFromSerializedState === "function" ? getPagesNavigationIsReadyFromSerializedState(routePattern, new URL(routerAsPath, "http://_").search, pagesNextData) : true;
238
+ const navigationIsReady = isStaticPropsRender ? false : typeof getPagesNavigationIsReadyFromSerializedState === "function" ? getPagesNavigationIsReadyFromSerializedState(routePattern, originalRequestUrl.search, pagesNextData) : true;
165
239
  function applySSRContext(extra) {
166
240
  if (typeof setSSRContext === "function") setSSRContext({
167
241
  pathname: routePattern,
@@ -204,15 +278,16 @@ function createPagesPageHandler(opts) {
204
278
  pageModuleUrl,
205
279
  appModuleUrl,
206
280
  hasMiddleware,
207
- routeUrl
281
+ routeUrl: renderRouteUrl
208
282
  }
209
283
  };
210
284
  const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareHeaders);
285
+ const shouldApplyErrorResponsePolicy = previewData === false && !scriptNonce && isStatusErrorRender && (isStaticPropsRoute || isRouteMissErrorRender || options?.__forcedRoute !== void 0);
211
286
  let fontLinkHeader = "";
212
287
  let allFontPreloads = [];
213
288
  try {
214
289
  allFontPreloads = getFontPreloads();
215
- if (allFontPreloads.length > 0) fontLinkHeader = allFontPreloads.map((p) => "<" + appendAssetDeploymentIdQuery(p.href) + ">; rel=preload; as=font; type=" + p.type + "; crossorigin").join(", ");
290
+ if (allFontPreloads.length > 0) fontLinkHeader = allFontPreloads.map((p) => "<" + p.href + ">; rel=preload; as=font; type=" + p.type + "; crossorigin").join(", ");
216
291
  } catch {}
217
292
  const pagesResolvedUrl = (new URL(routeUrl, originalRequestUrl).pathname || "/") + originalRequestUrl.search;
218
293
  const createPageReqRes = () => {
@@ -229,6 +304,7 @@ function createPagesPageHandler(opts) {
229
304
  isDataReq,
230
305
  err: err instanceof Error ? err : void 0,
231
306
  applyRequestContexts: applySSRContext,
307
+ basePath: vinextConfig.basePath,
232
308
  buildId,
233
309
  deploymentId: process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID,
234
310
  htmlLimitedBots: vinextConfig.htmlLimitedBots,
@@ -250,9 +326,11 @@ function createPagesPageHandler(opts) {
250
326
  isBuildTimePrerendering: typeof process !== "undefined" && process.env && process.env.VINEXT_PRERENDER === "1",
251
327
  validatePropsSerialization: process.env.NODE_ENV !== "production" || process.env.VINEXT_PRERENDER === "1",
252
328
  isOnDemandRevalidate,
329
+ revalidateOnlyGenerated,
253
330
  previewData,
254
331
  pageModule,
255
332
  AppComponent,
333
+ router,
256
334
  params,
257
335
  query,
258
336
  asPath: routerAsPath,
@@ -260,11 +338,17 @@ function createPagesPageHandler(opts) {
260
338
  renderIsrPassToStringAsync,
261
339
  route: { isDynamic: route.isDynamic },
262
340
  routePattern,
263
- routeUrl,
341
+ routeUrl: renderRouteUrl,
342
+ isrCachePathname,
264
343
  runInFreshUnifiedContext(callback) {
265
- return runWithRequestContext(createRequestContext({ executionContext: null }), async () => {
344
+ const revalCtx = createRequestContext({ executionContext: null });
345
+ return runWithRequestContext(revalCtx, async () => {
266
346
  ensureFetchPatch();
267
- return callback();
347
+ try {
348
+ return await callback();
349
+ } finally {
350
+ await closeAfterResponse(revalCtx);
351
+ }
268
352
  });
269
353
  },
270
354
  safeJsonStringify,
@@ -280,15 +364,26 @@ function createPagesPageHandler(opts) {
280
364
  });
281
365
  if (pageDataResult.kind === "notFound") {
282
366
  const notFoundRoute = findNotFoundRoute();
283
- if (notFoundRoute && routePattern !== "/404" && routePattern !== "/_error") return finalizePagesPreviewResponse(await renderPage(request, url, manifest, middlewareHeaders, {
367
+ let notFoundResponse;
368
+ if (notFoundRoute && routePattern !== "/404" && routePattern !== "/_error") notFoundResponse = await renderPage(request, url, manifest, middlewareHeaders, {
284
369
  statusCode: 404,
285
370
  asPath: routerAsPath,
286
371
  renderErrorPageOnMiss: false,
287
- __forcedRoute: notFoundRoute
288
- }), preview);
289
- return finalizePagesPreviewResponse(buildDefaultPagesNotFoundResponse(), preview);
372
+ __forcedRoute: notFoundRoute,
373
+ __notFoundRevalidateSeconds: pageDataResult.revalidateSeconds,
374
+ __notFoundExpireSeconds: pageDataResult.expireSeconds,
375
+ __notFoundCachePathname: isrCachePathname
376
+ });
377
+ else notFoundResponse = buildDefaultPagesNotFoundResponse();
378
+ if (isOnDemandRevalidate) notFoundResponse = withPagesCacheState(notFoundResponse, "REVALIDATED");
379
+ else if (pageDataResult.cacheState) notFoundResponse = withPagesCacheState(notFoundResponse, pageDataResult.cacheState);
380
+ return finalizePagesPreviewResponse(notFoundResponse, preview);
381
+ }
382
+ if (pageDataResult.kind === "response") {
383
+ let response = isOnDemandRevalidate && pageDataResult.onDemandRevalidateSuccess !== false ? withPagesCacheState(pageDataResult.response, "REVALIDATED") : pageDataResult.response;
384
+ if (shouldApplyErrorResponsePolicy) response = applyPagesErrorCachePolicy(response, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
385
+ return finalizePagesPreviewResponse(response, preview);
290
386
  }
291
- if (pageDataResult.kind === "response") return finalizePagesPreviewResponse(pageDataResult.response, preview);
292
387
  let pageProps = pageDataResult.pageProps;
293
388
  let renderProps = pageDataResult.props;
294
389
  if (previewData !== false) renderProps = {
@@ -308,16 +403,12 @@ function createPagesPageHandler(opts) {
308
403
  const gsspRes = pageDataResult.gsspRes;
309
404
  const documentReqRes = serializedPagesNextData.autoExport === true ? null : pageDataResult.documentReqRes ?? createPageReqRes();
310
405
  const isrRevalidateSeconds = pageDataResult.isrRevalidateSeconds;
406
+ const isrExpireSeconds = pageDataResult.isrExpireSeconds;
311
407
  const isFallbackRender = pageDataResult.isFallback === true;
312
- if (isFallbackRender && typeof setSSRContext === "function") setSSRContext({
313
- pathname: routePattern,
314
- query,
315
- asPath: routerAsPath,
408
+ if (isFallbackRender) applySSRContext({
409
+ query: {},
410
+ asPath: routePattern,
316
411
  navigationIsReady: false,
317
- locale,
318
- locales: i18nConfig ? i18nConfig.locales : void 0,
319
- defaultLocale: currentDefaultLocale,
320
- domainLocales,
321
412
  isFallback: true
322
413
  });
323
414
  if (isDataReq) {
@@ -338,7 +429,7 @@ function createPagesPageHandler(opts) {
338
429
  }
339
430
  if (!hasUserCacheControl) init.headers["Cache-Control"] = NEVER_CACHE_CONTROL;
340
431
  } else if (isStaticPropsRoute) {
341
- if (isrRevalidateSeconds) {
432
+ if (isrRevalidateSeconds !== null) {
342
433
  const headers = new Headers(init.headers);
343
434
  applyCdnResponseHeaders(headers, { cacheControl: buildMissIsrCacheControl(isrRevalidateSeconds, vinextConfig.expireTime) });
344
435
  for (const [key, value] of headers) init.headers[key] = value;
@@ -353,7 +444,7 @@ function createPagesPageHandler(opts) {
353
444
  const pageModuleIds = [];
354
445
  if (appAssetPath) pageModuleIds.push(appAssetPath);
355
446
  if (route.filePath) pageModuleIds.push(route.filePath);
356
- return finalizePagesPreviewResponse(await renderPagesPageResponse({
447
+ let pageResponse = await renderPagesPageResponse({
357
448
  assetTags: collectAssetTags({
358
449
  manifest,
359
450
  moduleIds: pageModuleIds,
@@ -387,8 +478,10 @@ function createPagesPageHandler(opts) {
387
478
  documentReqRes,
388
479
  gsspRes,
389
480
  isrCacheKey: pageIsrCacheKey,
390
- expireSeconds: vinextConfig.expireTime,
481
+ isrCachePathname,
482
+ expireSeconds: isrExpireSeconds,
391
483
  isrRevalidateSeconds,
484
+ isOnDemandRevalidate,
392
485
  isStaticPropsRoute,
393
486
  isrSet,
394
487
  i18n: buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domainLocales),
@@ -404,7 +497,7 @@ function createPagesPageHandler(opts) {
404
497
  resetSSRHead: typeof resetSSRHead === "function" ? resetSSRHead : void 0,
405
498
  setDocumentInitialHead: typeof setDocumentInitialHead === "function" ? setDocumentInitialHead : void 0,
406
499
  routePattern,
407
- routeUrl,
500
+ routeUrl: renderRouteUrl,
408
501
  safeJsonStringify,
409
502
  scriptNonce,
410
503
  statusCode: renderStatusCode,
@@ -412,7 +505,9 @@ function createPagesPageHandler(opts) {
412
505
  userAgent: request.headers.get("user-agent") ?? void 0,
413
506
  ifNoneMatch: request.headers.get("if-none-match") ?? void 0,
414
507
  requestCacheControl: request.headers.get("cache-control") ?? void 0
415
- }), preview);
508
+ });
509
+ if (shouldApplyErrorResponsePolicy) pageResponse = applyPagesErrorCachePolicy(pageResponse, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
510
+ return finalizePagesPreviewResponse(pageResponse, preview);
416
511
  } catch (e) {
417
512
  console.error("[vinext] SSR error:", e);
418
513
  reportRequestError(e instanceof Error ? e : new Error(String(e)), {
@@ -446,7 +541,7 @@ function createPagesPageHandler(opts) {
446
541
  }
447
542
  return new Response("Internal Server Error", { status: 500 });
448
543
  }
449
- });
544
+ }), uCtx);
450
545
  }
451
546
  return renderPage;
452
547
  }
@@ -88,11 +88,13 @@ type RenderPagesPageResponseOptions = {
88
88
  setDocumentInitialHead?: ((head: ReactNode[]) => void) | undefined;
89
89
  documentReqRes?: PagesDocumentReqRes | null;
90
90
  gsspRes: PagesGsspResponse | null;
91
- isrCacheKey: (router: string, pathname: string) => string;
91
+ isrCacheKey: (router: string, pathname: string) => string; /** Filesystem-route identity used for ISR persistence and cache tags. */
92
+ isrCachePathname?: string;
92
93
  expireSeconds?: number;
93
- isrRevalidateSeconds: number | null;
94
+ isrRevalidateSeconds: number | false | null; /** Synchronous `res.revalidate()` render; cache persistence must finish before returning. */
95
+ isOnDemandRevalidate?: boolean;
94
96
  isStaticPropsRoute?: boolean;
95
- isrSet: (key: string, data: CachedPagesValue, revalidateSeconds: number, tags?: string[], expireSeconds?: number) => Promise<void>;
97
+ isrSet: (key: string, data: CachedPagesValue, revalidateSeconds: number | false, tags?: string[], expireSeconds?: number) => Promise<void>;
96
98
  i18n: PagesI18nRenderContext;
97
99
  /**
98
100
  * True when rendering a `getStaticPaths` fallback shell for a path that
@@ -1,6 +1,6 @@
1
1
  import { getRequestExecutionContext } from "../shims/request-context.js";
2
+ import { NEXTJS_CACHE_HEADER } from "./headers.js";
2
3
  import { reportRequestError } from "./instrumentation.js";
3
- import { setCacheStateHeaders } from "./cache-headers.js";
4
4
  import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders, shouldUseNextDeployCacheControl } from "./cache-control.js";
5
5
  import { buildMissIsrCacheControl } from "./isr-decision.js";
6
6
  import { fnv1a52 } from "../utils/hash.js";
@@ -9,29 +9,19 @@ import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
9
9
  import { withScriptNonce } from "../shims/script-nonce-context.js";
10
10
  import { createNonceAttribute, escapeHtmlAttr } from "./html.js";
11
11
  import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
12
+ import { setCacheStateHeaders } from "./cache-headers.js";
12
13
  import { readStreamAsText } from "../utils/text-stream.js";
13
14
  import { loadUserDocumentInitialProps, runDocumentRenderPage } from "./pages-document-initial-props.js";
14
15
  import { callDocumentGetInitialProps } from "./document-initial-head.js";
16
+ import { isBotUserAgent } from "../utils/html-limited-bots.js";
15
17
  import React from "react";
16
18
  //#region src/server/pages-page-response.ts
17
19
  /**
18
- * Crawlers that cannot handle streamed HTML: they read metadata only from
19
- * the first network chunk, so streaming would give them an incomplete <head>.
20
- * Pattern sourced from Next.js html-bots.ts (updated to match the canary).
21
- */
22
- const HTML_LIMITED_BOT_UA_RE = /[\w-]+-Google|Google-[\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight/i;
23
- /**
24
- * Googlebot (the main search crawler) executes JavaScript via a headless
25
- * browser, so it too cannot safely handle mid-stream HTML mutations.
26
- * Matches "Googlebot" but NOT suffixed variants like "Googlebot-Image".
27
- */
28
- const HEADLESS_BROWSER_BOT_UA_RE = /Googlebot(?!-)|Googlebot$/i;
29
- /**
30
20
  * Returns true when the User-Agent belongs to a bot or crawler that cannot
31
21
  * reliably consume a streamed HTML response.
32
22
  */
33
23
  function isPagesStreamingBot(userAgent) {
34
- return HEADLESS_BROWSER_BOT_UA_RE.test(userAgent) || HTML_LIMITED_BOT_UA_RE.test(userAgent);
24
+ return isBotUserAgent(userAgent);
35
25
  }
36
26
  function generatePagesETag(payload) {
37
27
  return "\"" + fnv1a52(payload).toString(36) + payload.length.toString(36) + "\"";
@@ -64,7 +54,7 @@ function buildPagesFontHeadHtml(fontLinks, fontPreloads, fontStyles, scriptNonce
64
54
  let html = "";
65
55
  const nonceAttr = createNonceAttribute(scriptNonce);
66
56
  for (const link of fontLinks) html += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(link))}" />\n `;
67
- for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(preload.href))}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n `;
57
+ for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(preload.href)}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n `;
68
58
  if (fontStyles.length > 0) html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join("\n")}</style>\n `;
69
59
  return html;
70
60
  }
@@ -72,7 +62,7 @@ function buildPagesNextDataScript(options) {
72
62
  const nextDataPayload = {
73
63
  props: options.props ?? { pageProps: options.pageProps },
74
64
  page: options.routePattern,
75
- query: options.params,
65
+ query: options.isFallback === true ? {} : options.params,
76
66
  buildId: options.buildId,
77
67
  isFallback: options.isFallback === true
78
68
  };
@@ -142,14 +132,18 @@ async function reportPagesIsrCacheWriteError(error, cacheKey, routePattern) {
142
132
  });
143
133
  } catch {}
144
134
  }
145
- function schedulePagesIsrCacheWrite(options) {
146
- const cacheWritePromise = readStreamAsText(options.stream).then((bodyHtml) => options.setCache(options.cacheKey, {
135
+ async function writePagesIsrCache(options) {
136
+ const bodyHtml = await readStreamAsText(options.stream);
137
+ await options.setCache(options.cacheKey, {
147
138
  kind: "PAGES",
148
139
  html: options.shellPrefix + bodyHtml + options.shellSuffix,
149
140
  pageData: options.pageData,
150
141
  headers: void 0,
151
142
  status: options.status
152
- }, options.revalidateSeconds, void 0, options.expireSeconds)).catch((error) => reportPagesIsrCacheWriteError(error, options.cacheKey, options.routePattern));
143
+ }, options.revalidateSeconds, void 0, options.expireSeconds);
144
+ }
145
+ function schedulePagesIsrCacheWrite(options) {
146
+ const cacheWritePromise = writePagesIsrCache(options).catch((error) => reportPagesIsrCacheWriteError(error, options.cacheKey, options.routePattern));
153
147
  getRequestExecutionContext()?.waitUntil(cacheWritePromise);
154
148
  }
155
149
  function applyGsspHeaders(headers, gsspRes, statusCode) {
@@ -235,15 +229,15 @@ async function renderPagesPageResponse(options) {
235
229
  const responseHeaders = new Headers({ "Content-Type": "text/html; charset=utf-8" });
236
230
  const finalStatus = applyGsspHeaders(responseHeaders, options.gsspRes ?? options.documentReqRes?.res ?? null, options.statusCode);
237
231
  let responseBodyStream = bodyStream;
238
- if (!options.scriptNonce && options.isrRevalidateSeconds !== null && options.isrRevalidateSeconds > 0) {
232
+ if (!options.scriptNonce && options.isrRevalidateSeconds !== null && (options.isrRevalidateSeconds === false || options.isrRevalidateSeconds > 0)) {
239
233
  const cacheBodyStreamPair = bodyStream.tee();
240
234
  responseBodyStream = cacheBodyStreamPair[0];
241
235
  const cacheBodyStream = cacheBodyStreamPair[1];
242
- const isrPathname = options.routeUrl.split("?")[0];
243
- schedulePagesIsrCacheWrite({
236
+ const isrPathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
237
+ const cacheWriteOptions = {
244
238
  cacheKey: options.isrCacheKey("pages", isrPathname),
245
239
  expireSeconds: options.expireSeconds,
246
- pageData: options.pageProps,
240
+ pageData: options.props ?? { pageProps: options.pageProps },
247
241
  revalidateSeconds: options.isrRevalidateSeconds,
248
242
  routePattern: options.routePattern,
249
243
  setCache: options.isrSet,
@@ -251,19 +245,22 @@ async function renderPagesPageResponse(options) {
251
245
  shellSuffix,
252
246
  status: finalStatus,
253
247
  stream: cacheBodyStream
254
- });
248
+ };
249
+ if (options.isOnDemandRevalidate) await writePagesIsrCache(cacheWriteOptions);
250
+ else schedulePagesIsrCacheWrite(cacheWriteOptions);
255
251
  }
256
252
  const compositeStream = await buildPagesCompositeStream(responseBodyStream, shellPrefix, shellSuffix);
257
253
  const userSetCacheControl = responseHeaders.has("Cache-Control");
258
254
  if (options.scriptNonce) responseHeaders.set("Cache-Control", NO_STORE_CACHE_CONTROL);
259
- else if (options.isrRevalidateSeconds) {
260
- const isrPathname = options.routeUrl.split("?")[0];
255
+ else if (options.isrRevalidateSeconds !== null) {
256
+ const isrPathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
261
257
  const stem = isrPathname.endsWith("/") ? isrPathname.slice(0, -1) : isrPathname;
262
258
  applyCdnResponseHeaders(responseHeaders, {
263
259
  cacheControl: buildMissIsrCacheControl(options.isrRevalidateSeconds, options.expireSeconds),
264
260
  tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
265
261
  });
266
- setCacheStateHeaders(responseHeaders, "MISS");
262
+ if (options.isOnDemandRevalidate) responseHeaders.set(NEXTJS_CACHE_HEADER, "REVALIDATED");
263
+ else setCacheStateHeaders(responseHeaders, "MISS");
267
264
  } else if (options.isStaticPropsRoute && shouldUseNextDeployCacheControl()) responseHeaders.set("Cache-Control", BROWSER_REVALIDATE_CACHE_CONTROL);
268
265
  else if (options.gsspRes && !userSetCacheControl) responseHeaders.set("Cache-Control", NEVER_CACHE_CONTROL);
269
266
  if (options.fontLinkHeader) responseHeaders.set("Link", options.fontLinkHeader);
@@ -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, serialized into `__NEXT_DATA__`. The dev SSR handler and the production
11
- * Pages page handler must compute this identically so server HTML and client
12
- * hydration agree see `getPagesNavigationIsReadyFromSerializedState` in
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,14 @@ type PagesPipelineDeps = {
44
44
  hasMiddleware: boolean;
45
45
  ctx?: unknown;
46
46
  rawSearch?: string;
47
+ configMatchPathname?: string;
48
+ /**
49
+ * Validate an on-demand revalidation credential using the runtime's
50
+ * authoritative build secret. Production adapters must inject the verifier
51
+ * exported by the generated server entry so this early middleware decision
52
+ * uses the same baked secret as the eventual page renderer.
53
+ */
54
+ authorizeOnDemandRevalidate?: (headerValue: string | null) => boolean;
47
55
  matchPageRoute?: ((pathname: string, request: Request) => PageRouteMatch | null) | null;
48
56
  runMiddleware?: ((request: Request, ctx: unknown, opts: {
49
57
  isDataRequest: boolean;