vinext 0.1.7 → 0.2.0

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 (279) hide show
  1. package/README.md +51 -30
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/layout-classification.js +1 -1
  5. package/dist/build/nitro-route-rules.js +1 -1
  6. package/dist/build/pages-client-assets-module.d.ts +11 -0
  7. package/dist/build/pages-client-assets-module.js +27 -0
  8. package/dist/build/prerender.d.ts +2 -1
  9. package/dist/build/prerender.js +13 -6
  10. package/dist/build/report.d.ts +13 -2
  11. package/dist/build/report.js +99 -2
  12. package/dist/build/run-prerender.d.ts +7 -0
  13. package/dist/build/run-prerender.js +10 -1
  14. package/dist/build/standalone.js +2 -0
  15. package/dist/cache/cache-adapters-virtual.js +3 -3
  16. package/dist/check.d.ts +18 -0
  17. package/dist/check.js +77 -19
  18. package/dist/cli-args.d.ts +1 -2
  19. package/dist/cli-args.js +1 -1
  20. package/dist/cli-dev-config.d.ts +12 -0
  21. package/dist/cli-dev-config.js +23 -0
  22. package/dist/cli.js +113 -97
  23. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  24. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  25. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  26. package/dist/{server → client}/dev-error-overlay.js +2 -2
  27. package/dist/client/navigation-runtime.d.ts +2 -0
  28. package/dist/client/navigation-runtime.js +3 -1
  29. package/dist/client/window-next.d.ts +2 -1
  30. package/dist/cloudflare/index.d.ts +2 -2
  31. package/dist/cloudflare/index.js +2 -2
  32. package/dist/config/config-matchers.js +14 -10
  33. package/dist/config/next-config.d.ts +6 -3
  34. package/dist/config/next-config.js +47 -1
  35. package/dist/config/prerender.d.ts +34 -0
  36. package/dist/config/prerender.js +55 -0
  37. package/dist/config/server-external-packages.d.ts +4 -0
  38. package/dist/config/server-external-packages.js +91 -0
  39. package/dist/entries/app-rsc-entry.d.ts +2 -1
  40. package/dist/entries/app-rsc-entry.js +89 -15
  41. package/dist/entries/app-rsc-manifest.js +10 -0
  42. package/dist/entries/pages-client-entry.d.ts +3 -0
  43. package/dist/entries/pages-client-entry.js +16 -1
  44. package/dist/entries/pages-server-entry.js +6 -2
  45. package/dist/image/image-adapters-virtual.d.ts +59 -0
  46. package/dist/image/image-adapters-virtual.js +59 -0
  47. package/dist/index.d.ts +33 -0
  48. package/dist/index.js +211 -118
  49. package/dist/init-cloudflare.d.ts +43 -0
  50. package/dist/init-cloudflare.js +839 -0
  51. package/dist/init-platform.d.ts +40 -0
  52. package/dist/init-platform.js +195 -0
  53. package/dist/init.d.ts +16 -38
  54. package/dist/init.js +208 -97
  55. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  56. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  57. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  58. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  59. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  60. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  61. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  62. package/dist/packages/cloudflare/src/deploy.js +276 -0
  63. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  64. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
  65. package/dist/plugins/ast-scope.d.ts +16 -0
  66. package/dist/plugins/ast-scope.js +62 -0
  67. package/dist/plugins/ast-utils.d.ts +27 -1
  68. package/dist/plugins/ast-utils.js +32 -1
  69. package/dist/plugins/css-module-imports.d.ts +14 -0
  70. package/dist/plugins/css-module-imports.js +59 -0
  71. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  72. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  73. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  74. package/dist/plugins/middleware-server-only.d.ts +8 -6
  75. package/dist/plugins/middleware-server-only.js +8 -7
  76. package/dist/plugins/optimize-imports.js +1 -1
  77. package/dist/plugins/typeof-window.d.ts +1 -1
  78. package/dist/plugins/typeof-window.js +28 -56
  79. package/dist/routing/app-route-graph.d.ts +29 -4
  80. package/dist/routing/app-route-graph.js +182 -40
  81. package/dist/routing/app-router.d.ts +5 -0
  82. package/dist/routing/app-router.js +5 -0
  83. package/dist/routing/file-matcher.d.ts +8 -0
  84. package/dist/routing/file-matcher.js +10 -1
  85. package/dist/routing/pages-router.js +2 -2
  86. package/dist/server/api-handler.js +9 -14
  87. package/dist/server/app-browser-action-result.d.ts +4 -1
  88. package/dist/server/app-browser-action-result.js +8 -1
  89. package/dist/server/app-browser-entry.js +194 -190
  90. package/dist/server/app-browser-history-controller.d.ts +2 -1
  91. package/dist/server/app-browser-history-controller.js +6 -2
  92. package/dist/server/app-browser-interception-context.d.ts +1 -0
  93. package/dist/server/app-browser-interception-context.js +4 -2
  94. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  95. package/dist/server/app-browser-navigation-controller.js +60 -31
  96. package/dist/server/app-browser-server-action-client.d.ts +32 -0
  97. package/dist/server/app-browser-server-action-client.js +127 -0
  98. package/dist/server/app-browser-state.d.ts +11 -1
  99. package/dist/server/app-browser-state.js +25 -8
  100. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  101. package/dist/server/app-browser-visible-commit.js +43 -25
  102. package/dist/server/app-elements-wire.d.ts +9 -2
  103. package/dist/server/app-elements-wire.js +8 -1
  104. package/dist/server/app-elements.d.ts +2 -2
  105. package/dist/server/app-elements.js +4 -3
  106. package/dist/server/app-fallback-renderer.d.ts +5 -2
  107. package/dist/server/app-fallback-renderer.js +15 -7
  108. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  109. package/dist/server/app-hydration-cache-publication.js +43 -0
  110. package/dist/server/app-middleware.d.ts +4 -3
  111. package/dist/server/app-middleware.js +8 -3
  112. package/dist/server/app-optimistic-routing.js +11 -4
  113. package/dist/server/app-page-boundary-render.d.ts +3 -0
  114. package/dist/server/app-page-boundary-render.js +14 -3
  115. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  116. package/dist/server/app-page-cache-finalizer.js +10 -3
  117. package/dist/server/app-page-cache-render.d.ts +1 -0
  118. package/dist/server/app-page-cache-render.js +8 -4
  119. package/dist/server/app-page-cache.d.ts +1 -0
  120. package/dist/server/app-page-cache.js +5 -2
  121. package/dist/server/app-page-dispatch.d.ts +33 -4
  122. package/dist/server/app-page-dispatch.js +63 -90
  123. package/dist/server/app-page-element-builder.d.ts +9 -2
  124. package/dist/server/app-page-element-builder.js +114 -23
  125. package/dist/server/app-page-head.d.ts +16 -1
  126. package/dist/server/app-page-head.js +44 -22
  127. package/dist/server/app-page-params.d.ts +2 -1
  128. package/dist/server/app-page-params.js +8 -1
  129. package/dist/server/app-page-ppr-runtime.d.ts +7 -0
  130. package/dist/server/app-page-ppr-runtime.js +70 -0
  131. package/dist/server/app-page-probe.d.ts +1 -0
  132. package/dist/server/app-page-probe.js +6 -1
  133. package/dist/server/app-page-render-identity.d.ts +1 -0
  134. package/dist/server/app-page-render-identity.js +1 -1
  135. package/dist/server/app-page-render.d.ts +4 -1
  136. package/dist/server/app-page-render.js +26 -3
  137. package/dist/server/app-page-request.d.ts +22 -1
  138. package/dist/server/app-page-request.js +92 -15
  139. package/dist/server/app-page-route-wiring.d.ts +14 -2
  140. package/dist/server/app-page-route-wiring.js +61 -25
  141. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  142. package/dist/server/app-page-search-params-observation.js +11 -7
  143. package/dist/server/app-page-segment-state.d.ts +2 -1
  144. package/dist/server/app-page-segment-state.js +3 -1
  145. package/dist/server/app-page-stream.d.ts +5 -0
  146. package/dist/server/app-page-stream.js +3 -1
  147. package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
  148. package/dist/server/app-route-handler-dispatch.js +1 -0
  149. package/dist/server/app-route-handler-execution.js +7 -2
  150. package/dist/server/app-route-handler-response.js +1 -0
  151. package/dist/server/app-route-handler-runtime.js +1 -1
  152. package/dist/server/app-route-module-loader.d.ts +2 -0
  153. package/dist/server/app-route-module-loader.js +1 -0
  154. package/dist/server/app-router-entry.js +16 -8
  155. package/dist/server/app-rsc-errors.js +7 -1
  156. package/dist/server/app-rsc-handler.d.ts +3 -1
  157. package/dist/server/app-rsc-handler.js +67 -39
  158. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  159. package/dist/server/app-rsc-request-normalization.js +6 -3
  160. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  161. package/dist/server/app-rsc-route-matching.js +36 -3
  162. package/dist/server/app-segment-config.d.ts +12 -0
  163. package/dist/server/app-segment-config.js +91 -5
  164. package/dist/server/app-server-action-execution.d.ts +5 -0
  165. package/dist/server/app-server-action-execution.js +94 -33
  166. package/dist/server/app-ssr-entry.d.ts +3 -0
  167. package/dist/server/app-ssr-entry.js +19 -8
  168. package/dist/server/app-ssr-stream.d.ts +7 -3
  169. package/dist/server/app-ssr-stream.js +10 -6
  170. package/dist/server/app-static-generation.d.ts +1 -0
  171. package/dist/server/app-static-generation.js +1 -0
  172. package/dist/server/app-visited-response-cache.d.ts +6 -0
  173. package/dist/server/app-visited-response-cache.js +3 -1
  174. package/dist/server/client-trace-metadata.js +26 -0
  175. package/dist/server/default-global-not-found-module.d.ts +14 -0
  176. package/dist/server/default-global-not-found-module.js +14 -0
  177. package/dist/server/dev-route-files.js +4 -0
  178. package/dist/server/dev-server.js +19 -18
  179. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  180. package/dist/server/dev-stack-sourcemap.js +1 -1
  181. package/dist/server/fetch-handler.d.ts +2 -0
  182. package/dist/server/fetch-handler.js +18 -0
  183. package/dist/server/headers.d.ts +5 -15
  184. package/dist/server/headers.js +4 -15
  185. package/dist/server/image-optimization.d.ts +51 -1
  186. package/dist/server/image-optimization.js +52 -2
  187. package/dist/server/implicit-tags.js +1 -1
  188. package/dist/server/isr-cache.d.ts +1 -1
  189. package/dist/server/isr-cache.js +2 -2
  190. package/dist/server/metadata-routes.d.ts +3 -1
  191. package/dist/server/metadata-routes.js +12 -2
  192. package/dist/server/middleware-runtime.js +6 -1
  193. package/dist/server/navigation-planner.d.ts +1 -0
  194. package/dist/server/navigation-planner.js +14 -3
  195. package/dist/server/pages-api-route.js +2 -2
  196. package/dist/server/pages-asset-tags.d.ts +4 -6
  197. package/dist/server/pages-asset-tags.js +12 -12
  198. package/dist/server/pages-client-assets.d.ts +12 -0
  199. package/dist/server/pages-client-assets.js +10 -0
  200. package/dist/server/pages-node-compat.d.ts +8 -1
  201. package/dist/server/pages-node-compat.js +32 -4
  202. package/dist/server/pages-page-data.d.ts +24 -1
  203. package/dist/server/pages-page-data.js +45 -24
  204. package/dist/server/pages-page-handler.d.ts +2 -1
  205. package/dist/server/pages-page-handler.js +19 -12
  206. package/dist/server/pages-page-response.d.ts +7 -0
  207. package/dist/server/pages-page-response.js +4 -1
  208. package/dist/server/pages-request-pipeline.d.ts +2 -0
  209. package/dist/server/pages-request-pipeline.js +25 -1
  210. package/dist/server/pages-router-entry.d.ts +30 -0
  211. package/dist/server/pages-router-entry.js +108 -0
  212. package/dist/server/prerender-manifest.d.ts +3 -1
  213. package/dist/server/prerender-route-params.js +1 -1
  214. package/dist/server/prod-server.d.ts +1 -1
  215. package/dist/server/prod-server.js +48 -26
  216. package/dist/server/request-pipeline.js +1 -0
  217. package/dist/server/seed-cache.js +4 -4
  218. package/dist/server/worker-utils.d.ts +2 -1
  219. package/dist/server/worker-utils.js +7 -1
  220. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  221. package/dist/shims/app-router-scroll-state.js +1 -0
  222. package/dist/shims/app-router-scroll.js +2 -1
  223. package/dist/shims/cache.js +19 -15
  224. package/dist/shims/cdn-cache.js +1 -1
  225. package/dist/shims/dynamic-preload-chunks.js +2 -1
  226. package/dist/shims/error-boundary.d.ts +19 -1
  227. package/dist/shims/error-boundary.js +11 -1
  228. package/dist/shims/form.d.ts +3 -1
  229. package/dist/shims/form.js +37 -43
  230. package/dist/shims/headers.d.ts +9 -1
  231. package/dist/shims/headers.js +31 -6
  232. package/dist/shims/image.js +75 -14
  233. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  234. package/dist/shims/internal/app-route-detection.js +4 -17
  235. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  236. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  237. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
  238. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  239. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
  240. package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
  241. package/dist/shims/internal/pages-data-target.d.ts +10 -9
  242. package/dist/shims/internal/pages-data-target.js +91 -12
  243. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  244. package/dist/shims/internal/pages-router-components.js +13 -0
  245. package/dist/shims/layout-segment-context.d.ts +4 -1
  246. package/dist/shims/layout-segment-context.js +18 -4
  247. package/dist/shims/link.js +70 -37
  248. package/dist/shims/metadata.d.ts +3 -2
  249. package/dist/shims/metadata.js +8 -4
  250. package/dist/shims/navigation.d.ts +5 -1
  251. package/dist/shims/navigation.js +45 -10
  252. package/dist/shims/navigation.react-server.js +1 -1
  253. package/dist/shims/root-params.d.ts +15 -1
  254. package/dist/shims/root-params.js +21 -1
  255. package/dist/shims/router.d.ts +5 -7
  256. package/dist/shims/router.js +374 -94
  257. package/dist/shims/server.js +3 -2
  258. package/dist/shims/slot.js +3 -6
  259. package/dist/typegen.js +6 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  261. package/dist/utils/client-runtime-metadata.js +31 -22
  262. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  263. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  264. package/dist/utils/domain-locale.d.ts +6 -3
  265. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  266. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  267. package/dist/utils/path.d.ts +2 -1
  268. package/dist/utils/path.js +1 -1
  269. package/dist/utils/project.d.ts +52 -2
  270. package/dist/utils/project.js +230 -5
  271. package/dist/utils/protocol-headers.d.ts +17 -0
  272. package/dist/utils/protocol-headers.js +17 -0
  273. package/dist/utils/react-version.d.ts +4 -0
  274. package/dist/utils/react-version.js +44 -0
  275. package/package.json +53 -4
  276. package/dist/deploy.d.ts +0 -190
  277. package/dist/deploy.js +0 -1033
  278. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  279. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -78,7 +78,8 @@ function parseImageParams(url, allowedWidths = [...DEFAULT_DEVICE_SIZES, ...DEFA
78
78
  const allowedParamNames = new Set([
79
79
  "url",
80
80
  "w",
81
- "q"
81
+ "q",
82
+ "dpl"
82
83
  ]);
83
84
  for (const name of url.searchParams.keys()) if (!allowedParamNames.has(name) || url.searchParams.getAll(name).length !== 1) return null;
84
85
  const imageUrl = url.searchParams.get("url");
@@ -225,5 +226,54 @@ async function handleImageOptimization(request, handlers, allowedWidths, imageCo
225
226
  return createPassthroughImageResponse(refetchedSource, imageConfig);
226
227
  }
227
228
  }
229
+ const _IMAGE_OPTIMIZER_KEY = Symbol.for("vinext.imageOptimizer");
230
+ const _gImageOptimizer = globalThis;
231
+ /**
232
+ * Register the active image optimizer (transform backend). An explicit
233
+ * registration always wins; passing `null` clears it (falling back to
234
+ * unoptimized passthrough).
235
+ *
236
+ * Configure this declaratively via the `images.optimizer` option on the
237
+ * `vinext()` plugin in your `vite.config.ts` rather than calling it directly.
238
+ * On Cloudflare Workers:
239
+ *
240
+ * ```ts
241
+ * import { vinext } from "vinext";
242
+ * import { imagesOptimizer } from "@vinext/cloudflare/images/images-optimizer";
243
+ *
244
+ * export default defineConfig({
245
+ * plugins: [vinext({ images: { optimizer: imagesOptimizer() } })],
246
+ * });
247
+ * ```
248
+ *
249
+ * The plugin registers the optimizer across every runtime/router entry, so you
250
+ * don't have to wire `env.IMAGES` into a custom worker entry. This setter
251
+ * remains the internal registration target.
252
+ */
253
+ function setImageOptimizer(optimizer) {
254
+ _gImageOptimizer[_IMAGE_OPTIMIZER_KEY] = optimizer ?? void 0;
255
+ }
256
+ /** Get the active image optimizer, or `null` when none is configured. */
257
+ function getImageOptimizer() {
258
+ return _gImageOptimizer[_IMAGE_OPTIMIZER_KEY] ?? null;
259
+ }
260
+ /**
261
+ * Handle an image optimization request using the configured optimizer (if any).
262
+ *
263
+ * This is the single entry point every runtime/router seam (App Router worker,
264
+ * Pages worker, Node prod server) should call: it reads the registered
265
+ * {@link ImageOptimizer} and wires its `transformImage` into
266
+ * {@link handleImageOptimization}, with the caller supplying the runtime's
267
+ * `fetchAsset` (e.g. the Cloudflare `ASSETS` binding, or filesystem reads on
268
+ * Node). When no optimizer is registered, the request is served unoptimized
269
+ * (passthrough) with the same security/cache headers.
270
+ */
271
+ function handleConfiguredImageOptimization(request, fetchAsset, allowedWidths, imageConfig) {
272
+ const optimizer = getImageOptimizer();
273
+ return handleImageOptimization(request, {
274
+ fetchAsset,
275
+ transformImage: optimizer ? (body, options) => optimizer.transformImage(body, options) : void 0
276
+ }, allowedWidths, imageConfig);
277
+ }
228
278
  //#endregion
229
- export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, VINEXT_IMAGE_OPTIMIZATION_PATH, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect };
279
+ export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, VINEXT_IMAGE_OPTIMIZATION_PATH, getImageOptimizer, handleConfiguredImageOptimization, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect, setImageOptimizer };
@@ -33,7 +33,7 @@ function buildAppPageTags(cleanPathname, extraTags, routeSegments) {
33
33
  return buildPageCacheTags(cleanPathname, extraTags, [...routeSegments], "page");
34
34
  }
35
35
  function buildPageCacheTags(pathname, extraTags, routeSegments, leafKind) {
36
- const tags = [pathname, `${NEXT_CACHE_IMPLICIT_TAG_ID}${pathname}`];
36
+ const tags = [pathname, `${NEXT_CACHE_IMPLICIT_TAG_ID}${pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname}`];
37
37
  if (pathname === "/") appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}/index`);
38
38
  if (pathname === "/index") appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}/`);
39
39
  appendDerivedTags(tags, buildRouteCachePath(routeSegments, leafKind));
@@ -95,7 +95,7 @@ declare function buildPagesCacheValue(html: string, pageData: object, status?: n
95
95
  /**
96
96
  * Build a CachedAppPageValue for the App Router ISR cache.
97
97
  */
98
- declare function buildAppPageCacheValue(html: string, rscData?: ArrayBuffer, status?: number, renderObservation?: RenderObservation): CachedAppPageValue;
98
+ declare function buildAppPageCacheValue(html: string, rscData?: ArrayBuffer, status?: number, renderObservation?: RenderObservation, headers?: CachedAppPageValue["headers"]): CachedAppPageValue;
99
99
  /**
100
100
  * Compute an ISR cache key for a given router type and pathname.
101
101
  * Long pathnames are hashed to stay within KV key-length limits (512 bytes).
@@ -188,12 +188,12 @@ function buildPagesCacheValue(html, pageData, status) {
188
188
  /**
189
189
  * Build a CachedAppPageValue for the App Router ISR cache.
190
190
  */
191
- function buildAppPageCacheValue(html, rscData, status, renderObservation) {
191
+ function buildAppPageCacheValue(html, rscData, status, renderObservation, headers) {
192
192
  const value = {
193
193
  kind: "APP_PAGE",
194
194
  html,
195
195
  rscData,
196
- headers: void 0,
196
+ headers,
197
197
  postponed: void 0,
198
198
  status
199
199
  };
@@ -131,9 +131,11 @@ declare function getMetadataImageRouteKind(route: Pick<MetadataFileRoute, "type"
131
131
  declare function isValidMetadataImageId(id: string): boolean;
132
132
  declare function matchMetadataRoutePattern(urlParts: string[], patternParts: string[]): Record<string, string | string[]> | null;
133
133
  declare function matchMetadataFileBaseName(metaType: string, baseName: string): string | null;
134
+ /** Clear the {@link scanMetadataFiles} cache (call when app files change in dev). */
135
+ declare function invalidateMetadataFileCache(): void;
134
136
  /**
135
137
  * Scan an app directory for metadata files.
136
138
  */
137
139
  declare function scanMetadataFiles(appDir: string): MetadataFileRoute[];
138
140
  //#endregion
139
- export { METADATA_FILE_MAP, ManifestConfig, MetadataFileRoute, MetadataRouteHeadData, RobotsConfig, SitemapEntry, fillStaticMetadataSegment, getMetadataImageRouteKind, getMetadataRouteKind, isValidMetadataImageId, manifestToJson, matchMetadataFileBaseName, matchMetadataRoutePattern, robotsToText, scanMetadataFiles, sitemapToXml };
141
+ export { METADATA_FILE_MAP, ManifestConfig, MetadataFileRoute, MetadataRouteHeadData, RobotsConfig, SitemapEntry, fillStaticMetadataSegment, getMetadataImageRouteKind, getMetadataRouteKind, invalidateMetadataFileCache, isValidMetadataImageId, manifestToJson, matchMetadataFileBaseName, matchMetadataRoutePattern, robotsToText, scanMetadataFiles, sitemapToXml };
@@ -357,10 +357,18 @@ function matchMetadataFileBaseName(metaType, baseName) {
357
357
  }
358
358
  return null;
359
359
  }
360
+ let cachedMetadataRoutes = null;
361
+ let cachedMetadataAppDir = null;
362
+ /** Clear the {@link scanMetadataFiles} cache (call when app files change in dev). */
363
+ function invalidateMetadataFileCache() {
364
+ cachedMetadataRoutes = null;
365
+ cachedMetadataAppDir = null;
366
+ }
360
367
  /**
361
368
  * Scan an app directory for metadata files.
362
369
  */
363
370
  function scanMetadataFiles(appDir) {
371
+ if (cachedMetadataRoutes && cachedMetadataAppDir === appDir) return cachedMetadataRoutes;
364
372
  const routes = [];
365
373
  function scan(dir, urlPrefix, parentSegments) {
366
374
  if (!fs.existsSync(dir)) return;
@@ -409,7 +417,9 @@ function scanMetadataFiles(appDir) {
409
417
  if (!existing) byUrl.set(route.servedUrl, route);
410
418
  else if (route.isDynamic && !existing.isDynamic) byUrl.set(route.servedUrl, route);
411
419
  }
412
- return Array.from(byUrl.values());
420
+ cachedMetadataRoutes = Array.from(byUrl.values());
421
+ cachedMetadataAppDir = appDir;
422
+ return cachedMetadataRoutes;
413
423
  }
414
424
  function resolveStaticMetadataAltFilePath(dir, baseName) {
415
425
  const altPath = path.join(dir, `${baseName}.alt.txt`);
@@ -430,4 +440,4 @@ function getStaticContentType(ext, fallback) {
430
440
  }[ext] ?? fallback;
431
441
  }
432
442
  //#endregion
433
- export { METADATA_FILE_MAP, fillStaticMetadataSegment, getMetadataImageRouteKind, getMetadataRouteKind, isValidMetadataImageId, manifestToJson, matchMetadataFileBaseName, matchMetadataRoutePattern, robotsToText, scanMetadataFiles, sitemapToXml };
443
+ export { METADATA_FILE_MAP, fillStaticMetadataSegment, getMetadataImageRouteKind, getMetadataRouteKind, invalidateMetadataFileCache, isValidMetadataImageId, manifestToJson, matchMetadataFileBaseName, matchMetadataRoutePattern, robotsToText, scanMetadataFiles, sitemapToXml };
@@ -2,8 +2,9 @@ import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
2
2
  import { addBasePathToPathname, hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
3
3
  import "./server-globals.js";
4
4
  import { getRequestExecutionContext, runWithExecutionContext } from "../shims/request-context.js";
5
+ import "../utils/protocol-headers.js";
5
6
  import { MIDDLEWARE_REWRITE_HEADER } from "./headers.js";
6
- import { shouldKeepMiddlewareHeader } from "./middleware-request-headers.js";
7
+ import { shouldKeepMiddlewareHeader } from "../utils/middleware-request-headers.js";
7
8
  import { NextFetchEvent, NextRequest } from "../shims/server.js";
8
9
  import { normalizePath } from "./normalize-path.js";
9
10
  import { matchesMiddleware } from "./middleware-matcher.js";
@@ -141,6 +142,10 @@ async function executeMiddleware(options) {
141
142
  const matchPathname = options.basePath ? stripBasePath(normalizedPathname, options.basePath) : normalizedPathname;
142
143
  if (!matchesMiddleware(matchPathname, middlewareMatcher(options.module), options.request, options.i18nConfig)) return { continue: true };
143
144
  const nextRequest = createNextRequest(options.request, normalizedPathname, options.i18nConfig, options.basePath, options.trailingSlash, hadBasePath);
145
+ if (options.isDataRequest) Object.defineProperty(nextRequest, "__isData", {
146
+ enumerable: false,
147
+ value: true
148
+ });
144
149
  const fetchEvent = new NextFetchEvent({ page: removeTrailingSlash(matchPathname) });
145
150
  let response;
146
151
  try {
@@ -103,6 +103,7 @@ type NavigationDecision = {
103
103
  type FlightResult = {
104
104
  cacheEntryReuseProof?: CacheEntryReuseProof;
105
105
  href: string;
106
+ restoredHistorySnapshot?: boolean;
106
107
  targetSnapshot: RouteSnapshot;
107
108
  };
108
109
  type RscFetchResultSource = "cached" | "live";
@@ -1,8 +1,8 @@
1
1
  import { splitPathnameForRouteMatch } from "../routing/utils.js";
2
2
  import { stripBasePath } from "../utils/base-path.js";
3
- import { matchRoutePattern, matchRoutePatternPrefix, matchRoutePatternWithOptionalDynamicSegments } from "../routing/route-pattern.js";
4
3
  import { compareAppElementsSlotIds } from "./app-elements-wire.js";
5
4
  import "./app-elements.js";
5
+ import { matchRoutePattern, matchRoutePatternPrefix, matchRoutePatternWithOptionalDynamicSegments } from "../routing/route-pattern.js";
6
6
  import { resolveHardNavigationTargetFromRscResponse, resolveRscCompatibilityNavigationDecision } from "./app-rsc-cache-busting.js";
7
7
  import { resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop } from "./app-browser-rsc-redirect.js";
8
8
  import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
@@ -291,6 +291,11 @@ function stripInterceptionContextFromRouteId(routeId) {
291
291
  const separatorIndex = routeId.indexOf(ROUTE_INTERCEPTION_CONTEXT_SEPARATOR);
292
292
  return separatorIndex === -1 ? routeId : routeId.slice(0, separatorIndex);
293
293
  }
294
+ function matchedUrlFromConcreteRouteId(routeId) {
295
+ const normalizedRouteId = stripInterceptionContextFromRouteId(routeId);
296
+ if (!normalizedRouteId.startsWith("route:/")) return null;
297
+ return normalizedRouteId.slice(6);
298
+ }
294
299
  function getMatchedUrlPathname(matchedUrl) {
295
300
  try {
296
301
  return new URL(matchedUrl, "https://vinext.local").pathname;
@@ -315,6 +320,11 @@ function findRouteManifestRouteByIdOrMatchedUrl(options) {
315
320
  const routeId = stripInterceptionContextFromRouteId(options.routeId);
316
321
  const route = options.routeManifest.segmentGraph.routes.get(routeId);
317
322
  if (route && routeManifestRouteMatchesUrl(route, options.matchedUrl)) return route;
323
+ const concreteRouteMatchedUrl = route === void 0 ? matchedUrlFromConcreteRouteId(options.routeId) : null;
324
+ if (concreteRouteMatchedUrl !== null) {
325
+ const concreteRoute = findRouteManifestRouteByMatchedUrl(options.routeManifest, concreteRouteMatchedUrl);
326
+ if (concreteRoute !== null) return concreteRoute;
327
+ }
318
328
  return findRouteManifestRouteByMatchedUrl(options.routeManifest, options.matchedUrl);
319
329
  }
320
330
  function findRouteManifestRouteForSnapshot(routeManifest, snapshot) {
@@ -480,7 +490,7 @@ function getVisibleInterceptionSourceIdentity(snapshot) {
480
490
  routeId: snapshot.interception.sourceRouteId
481
491
  };
482
492
  return {
483
- matchedUrl: snapshot.matchedUrl,
493
+ matchedUrl: matchedUrlFromConcreteRouteId(snapshot.routeId) ?? snapshot.matchedUrl,
484
494
  routeId: snapshot.routeId
485
495
  };
486
496
  }
@@ -567,7 +577,7 @@ function validateInterceptedPreservation(options) {
567
577
  reasonCode: NavigationTraceReasonCodes.interceptedRejectedTargetMismatch
568
578
  };
569
579
  const sourceIdentity = getVisibleInterceptionSourceIdentity(options.currentSnapshot);
570
- if (proof.sourceMatchedUrl !== sourceIdentity.matchedUrl || proof.sourceRouteId !== sourceIdentity.routeId) return {
580
+ if (!options.restoredHistorySnapshot && (proof.sourceMatchedUrl !== sourceIdentity.matchedUrl || proof.sourceRouteId !== sourceIdentity.routeId)) return {
571
581
  kind: "rejected",
572
582
  reasonCode: NavigationTraceReasonCodes.interceptedRejectedUnknownSource
573
583
  };
@@ -654,6 +664,7 @@ function planFlightResponseArrived(options) {
654
664
  const validation = validateInterceptedPreservation({
655
665
  currentSnapshot: options.state.visibleSnapshot,
656
666
  currentTopology: currentTopology.topology,
667
+ restoredHistorySnapshot: options.event.result.restoredHistorySnapshot === true,
657
668
  routeManifest: options.routeManifest,
658
669
  targetSnapshot,
659
670
  targetTopology: targetTopology.topology
@@ -4,10 +4,10 @@ import { NextRequest } from "../shims/server.js";
4
4
  import { internalServerErrorResponse } from "./http-error-responses.js";
5
5
  import { cloneRequestWithUrl } from "./request-pipeline.js";
6
6
  import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
7
- import { PagesBodyParseError } from "./pages-media-type.js";
8
- import { isEdgeApiRuntime } from "./edge-api-runtime.js";
9
7
  import { resolveBodyParserConfig } from "./pages-body-parser-config.js";
8
+ import { PagesBodyParseError } from "./pages-media-type.js";
10
9
  import { createPagesReqRes, parsePagesApiBody } from "./pages-node-compat.js";
10
+ import { isEdgeApiRuntime } from "./edge-api-runtime.js";
11
11
  //#region src/server/pages-api-route.ts
12
12
  function resolveModuleRuntime(module) {
13
13
  return module.runtime ?? module.config?.runtime;
@@ -10,9 +10,8 @@
10
10
  * template string.
11
11
  */
12
12
  /**
13
- * Resolve the effective SSR manifest: prefer the caller-supplied object (dev
14
- * or test) and fall back to the Worker-embedded `globalThis.__VINEXT_SSR_MANIFEST__`
15
- * injected by `vinext:cloudflare-build` at build time.
13
+ * Resolve the effective SSR manifest: prefer the caller-supplied object and
14
+ * fall back to the registered client build metadata.
16
15
  */
17
16
  declare function resolveSsrManifest(manifest: Record<string, string[]> | null | undefined): Record<string, string[]> | null;
18
17
  /**
@@ -34,7 +33,7 @@ declare function resolveClientModuleUrl(manifest: Record<string, string[]> | nul
34
33
  type CollectAssetTagsOptions = {
35
34
  /**
36
35
  * SSR manifest mapping module file paths to their associated asset list.
37
- * When empty/null the Worker-embedded `__VINEXT_SSR_MANIFEST__` is used.
36
+ * When empty/null the registered client build manifest is used.
38
37
  */
39
38
  manifest: Record<string, string[]> | null | undefined;
40
39
  /**
@@ -66,8 +65,7 @@ type CollectAssetTagsOptions = {
66
65
  * - CSS files → `<link rel="stylesheet">`.
67
66
  * - JS files → `<link rel="modulepreload">` + `<script type="module" defer>`.
68
67
  * - Lazy chunks (behind `React.lazy` / `next/dynamic`) are skipped.
69
- * - The Worker-embedded client-entry bootstrap (`__VINEXT_CLIENT_ENTRY__`) is
70
- * injected first so hydration starts as early as possible.
68
+ * - The registered client-entry bootstrap is injected first.
71
69
  * - Shared framework / vinext runtime chunks are always included alongside
72
70
  * page-specific chunks.
73
71
  *
@@ -1,6 +1,7 @@
1
1
  import { appendDeploymentIdQuery } from "../utils/deployment-id.js";
2
2
  import { createNonceAttribute } from "./html.js";
3
3
  import { assetServingUrlFromBaseAnchored } from "../utils/manifest-paths.js";
4
+ import { getPagesClientAssets } from "./pages-client-assets.js";
4
5
  //#region src/server/pages-asset-tags.ts
5
6
  /**
6
7
  * Pages Router SSR asset-tag helpers.
@@ -13,13 +14,12 @@ import { assetServingUrlFromBaseAnchored } from "../utils/manifest-paths.js";
13
14
  * template string.
14
15
  */
15
16
  /**
16
- * Resolve the effective SSR manifest: prefer the caller-supplied object (dev
17
- * or test) and fall back to the Worker-embedded `globalThis.__VINEXT_SSR_MANIFEST__`
18
- * injected by `vinext:cloudflare-build` at build time.
17
+ * Resolve the effective SSR manifest: prefer the caller-supplied object and
18
+ * fall back to the registered client build metadata.
19
19
  */
20
20
  function resolveSsrManifest(manifest) {
21
21
  if (manifest && Object.keys(manifest).length > 0) return manifest;
22
- return (typeof globalThis !== "undefined" ? globalThis.__VINEXT_SSR_MANIFEST__ : null) ?? null;
22
+ return getPagesClientAssets().ssrManifest ?? null;
23
23
  }
24
24
  /**
25
25
  * Look up the asset-file list for a module ID in the SSR manifest.
@@ -58,8 +58,7 @@ function resolveClientModuleUrl(manifest, moduleId, basePath = "", assetPrefix =
58
58
  * - CSS files → `<link rel="stylesheet">`.
59
59
  * - JS files → `<link rel="modulepreload">` + `<script type="module" defer>`.
60
60
  * - Lazy chunks (behind `React.lazy` / `next/dynamic`) are skipped.
61
- * - The Worker-embedded client-entry bootstrap (`__VINEXT_CLIENT_ENTRY__`) is
62
- * injected first so hydration starts as early as possible.
61
+ * - The registered client-entry bootstrap is injected first.
63
62
  * - Shared framework / vinext runtime chunks are always included alongside
64
63
  * page-specific chunks.
65
64
  *
@@ -77,13 +76,14 @@ function collectAssetTags(options) {
77
76
  const url = assetServingUrlFromBaseAnchored(value, basePath, assetPrefix);
78
77
  return value.endsWith(".js") ? url : appendDeploymentIdQuery(url, options.deploymentId);
79
78
  };
80
- const lazyChunks = typeof globalThis !== "undefined" && globalThis.__VINEXT_LAZY_CHUNKS__ || null;
79
+ const runtimeAssets = getPagesClientAssets();
80
+ const lazyChunks = runtimeAssets.lazyChunks ?? null;
81
81
  const lazySet = lazyChunks && lazyChunks.length > 0 ? new Set(lazyChunks) : null;
82
- if (typeof globalThis !== "undefined" && globalThis.__VINEXT_CLIENT_ENTRY__) {
83
- const entry = globalThis.__VINEXT_CLIENT_ENTRY__;
84
- seen.add(entry);
85
- tags.push("<link rel=\"modulepreload\"" + nonceAttr + " href=\"" + href(entry) + "\" />");
86
- tags.push("<script type=\"module\"" + deferAttr + nonceAttr + " src=\"" + href(entry) + "\" crossorigin><\/script>");
82
+ const clientEntry = runtimeAssets.clientEntry;
83
+ if (clientEntry) {
84
+ seen.add(clientEntry);
85
+ tags.push("<link rel=\"modulepreload\"" + nonceAttr + " href=\"" + href(clientEntry) + "\" />");
86
+ tags.push("<script type=\"module\"" + deferAttr + nonceAttr + " src=\"" + href(clientEntry) + "\" crossorigin><\/script>");
87
87
  }
88
88
  if (m) {
89
89
  const allFiles = [];
@@ -0,0 +1,12 @@
1
+ //#region src/server/pages-client-assets.d.ts
2
+ type PagesClientAssets = {
3
+ clientEntry?: string;
4
+ appBootstrapPreinitModules?: string[];
5
+ ssrManifest?: Record<string, string[]>;
6
+ lazyChunks?: string[];
7
+ dynamicPreloads?: Record<string, string[]>;
8
+ };
9
+ declare function setPagesClientAssets(assets: PagesClientAssets | undefined): void;
10
+ declare function getPagesClientAssets(): PagesClientAssets;
11
+ //#endregion
12
+ export { PagesClientAssets, getPagesClientAssets, setPagesClientAssets };
@@ -0,0 +1,10 @@
1
+ //#region src/server/pages-client-assets.ts
2
+ let pagesClientAssets = {};
3
+ function setPagesClientAssets(assets) {
4
+ pagesClientAssets = assets ?? {};
5
+ }
6
+ function getPagesClientAssets() {
7
+ return pagesClientAssets;
8
+ }
9
+ //#endregion
10
+ export { getPagesClientAssets, setPagesClientAssets };
@@ -28,6 +28,12 @@ type PagesReqResResponse = Writable & {
28
28
  getHeaders: () => PagesReqResHeaders;
29
29
  revalidate: (urlPath: string, opts?: RevalidateOptions) => Promise<void>;
30
30
  };
31
+ type PagesRequestCookiesCarrier = {
32
+ headers: {
33
+ cookie?: string | string[] | null | undefined;
34
+ };
35
+ cookies?: unknown;
36
+ };
31
37
  type CreatePagesReqResOptions = {
32
38
  body: unknown;
33
39
  query: PagesRequestQuery;
@@ -50,6 +56,7 @@ type CreatePagesReqResResult = {
50
56
  * @see https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config
51
57
  */
52
58
  declare function parsePagesApiBody(request: Request, maxBytes?: number): Promise<unknown>;
59
+ declare function attachPagesRequestCookies(req: PagesRequestCookiesCarrier): void;
53
60
  declare function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult;
54
61
  //#endregion
55
- export { PagesBodyParseError as PagesApiBodyParseError, PagesReqResRequest, PagesReqResResponse, PagesRequestQuery, createPagesReqRes, parsePagesApiBody };
62
+ export { PagesBodyParseError as PagesApiBodyParseError, PagesReqResRequest, PagesReqResResponse, PagesRequestQuery, attachPagesRequestCookies, createPagesReqRes, parsePagesApiBody };
@@ -1,7 +1,7 @@
1
1
  import { parseCookieHeader } from "../utils/parse-cookie.js";
2
2
  import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
3
- import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-media-type.js";
4
3
  import { DEFAULT_PAGES_API_BODY_SIZE_LIMIT } from "./pages-body-parser-config.js";
4
+ import { PagesBodyParseError, getMediaType, isJsonMediaType } from "./pages-media-type.js";
5
5
  import { performOnDemandRevalidate } from "./pages-revalidate.js";
6
6
  import { decode } from "node:querystring";
7
7
  import { Readable, Writable } from "node:stream";
@@ -61,6 +61,34 @@ async function* requestBodyChunks(request) {
61
61
  function createRequestReadable(request) {
62
62
  return Readable.from(requestBodyChunks(request), { objectMode: false });
63
63
  }
64
+ function parsePagesRequestCookies(cookieHeader) {
65
+ return parseCookieHeader(Array.isArray(cookieHeader) ? cookieHeader.join("; ") : cookieHeader);
66
+ }
67
+ function attachPagesRequestCookies(req) {
68
+ if (Object.hasOwn(req, "cookies")) return;
69
+ Object.defineProperty(req, "cookies", {
70
+ configurable: true,
71
+ enumerable: true,
72
+ get() {
73
+ const cookies = parsePagesRequestCookies(req.headers.cookie);
74
+ Object.defineProperty(req, "cookies", {
75
+ configurable: true,
76
+ enumerable: true,
77
+ value: cookies,
78
+ writable: true
79
+ });
80
+ return cookies;
81
+ },
82
+ set(value) {
83
+ Object.defineProperty(req, "cookies", {
84
+ configurable: true,
85
+ enumerable: true,
86
+ value,
87
+ writable: true
88
+ });
89
+ }
90
+ });
91
+ }
64
92
  var PagesResponseStream = class extends Writable {
65
93
  resolveResponse;
66
94
  rejectResponse;
@@ -216,9 +244,9 @@ function createPagesReqRes(options) {
216
244
  url: options.url,
217
245
  headers: headersObj,
218
246
  query: options.query,
219
- body: options.body,
220
- cookies: parseCookieHeader(options.request.headers.get("cookie"))
247
+ body: options.body
221
248
  });
249
+ attachPagesRequestCookies(req);
222
250
  let resolveResponse;
223
251
  let rejectResponse;
224
252
  const responsePromise = new Promise((resolve, reject) => {
@@ -232,4 +260,4 @@ function createPagesReqRes(options) {
232
260
  };
233
261
  }
234
262
  //#endregion
235
- export { PagesBodyParseError as PagesApiBodyParseError, createPagesReqRes, parsePagesApiBody };
263
+ export { PagesBodyParseError as PagesApiBodyParseError, attachPagesRequestCookies, createPagesReqRes, parsePagesApiBody };
@@ -197,6 +197,7 @@ type ResolvePagesPageDataOptions = {
197
197
  };
198
198
  type ResolvePagesPageDataRenderResult = {
199
199
  kind: "render";
200
+ documentReqRes: PagesGsspContextResponse | null;
200
201
  gsspRes: PagesGsspResponse | null;
201
202
  isrRevalidateSeconds: number | null;
202
203
  pageProps: Record<string, unknown>;
@@ -217,7 +218,29 @@ type ResolvePagesPageDataNotFoundResult = {
217
218
  kind: "notFound";
218
219
  };
219
220
  type ResolvePagesPageDataResult = ResolvePagesPageDataRenderResult | ResolvePagesPageDataResponseResult | ResolvePagesPageDataNotFoundResult;
221
+ /**
222
+ * Compare a `getStaticPaths` entry against the actual request params.
223
+ *
224
+ * Handles both shapes Next.js allows:
225
+ * - { params: { ... } }
226
+ * - "string-path"
227
+ *
228
+ * For a string entry, compare the entry against the current request URL using
229
+ * the shared `normalizeStaticPathname` helper from
230
+ * `../routing/route-pattern.ts` (which mirrors the Next.js
231
+ * `removeTrailingSlash` behaviour in
232
+ * `.nextjs-ref/packages/next/src/build/static-paths/pages.ts`). For an object
233
+ * entry with a missing `params` key, return false rather than throwing — the
234
+ * caller will respond with a 404 just like Next.js does for unlisted paths.
235
+ */
236
+ type PagesRouteParam = {
237
+ key: string;
238
+ repeat: boolean;
239
+ optional: boolean;
240
+ };
241
+ declare function getPagesRouteParams(routePattern: string): PagesRouteParam[];
242
+ declare function matchesPagesStaticPath(pathEntry: PagesStaticPathsEntry, params: Record<string, unknown>, routeParams: PagesRouteParam[], routeUrl: string): boolean;
220
243
  declare function renderPagesIsrHtml(options: RenderPagesIsrHtmlOptions): Promise<string>;
221
244
  declare function resolvePagesPageData(options: ResolvePagesPageDataOptions): Promise<ResolvePagesPageDataResult>;
222
245
  //#endregion
223
- export { PagesPageModule, ResolvePagesPageDataOptions, renderPagesIsrHtml, resolvePagesPageData };
246
+ export { PagesPageModule, PagesRouteParam, PagesStaticPathsEntry, ResolvePagesPageDataOptions, getPagesRouteParams, matchesPagesStaticPath, renderPagesIsrHtml, resolvePagesPageData };
@@ -1,15 +1,15 @@
1
1
  import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
2
- import { normalizeStaticPathname } from "../routing/route-pattern.js";
3
2
  import { buildCacheStateHeaders } from "./cache-headers.js";
4
3
  import { isUnknownRecord } from "../utils/record.js";
5
4
  import { applyCdnResponseHeaders } from "./cache-control.js";
6
5
  import { decideIsr } from "./isr-decision.js";
7
6
  import { buildPagesCacheValue } from "./isr-cache.js";
8
- import { isSerializableProps } from "./pages-serializable-props.js";
7
+ import { normalizeStaticPathname } from "../routing/route-pattern.js";
8
+ import { buildPagesNextDataScript, etagMatches, generatePagesETag, isPagesStreamingBot, requestsNoCache } from "./pages-page-response.js";
9
9
  import { hasPagesGetInitialProps, isResponseSent, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
10
- import { isBotUserAgent } from "../utils/html-limited-bots.js";
11
10
  import { buildNextDataPropsJsonResponse } from "./pages-data-route.js";
12
- import { buildPagesNextDataScript, etagMatches, generatePagesETag, isPagesStreamingBot, requestsNoCache } from "./pages-page-response.js";
11
+ import { isSerializableProps } from "./pages-serializable-props.js";
12
+ import { isBotUserAgent } from "../utils/html-limited-bots.js";
13
13
  //#region src/server/pages-page-data.ts
14
14
  function buildPagesDataNotFoundResponse(deploymentId) {
15
15
  const headers = { "Content-Type": "application/json" };
@@ -128,28 +128,45 @@ function buildPagesRedirectResponse(redirect, options, props = { pageProps: {} }
128
128
  headers: { Location: destination }
129
129
  });
130
130
  }
131
- /**
132
- * Compare a `getStaticPaths` entry against the actual request params.
133
- *
134
- * Handles both shapes Next.js allows:
135
- * - { params: { ... } }
136
- * - "string-path"
137
- *
138
- * For a string entry, compare the entry against the current request URL using
139
- * the shared `normalizeStaticPathname` helper from
140
- * `../routing/route-pattern.ts` (which mirrors the Next.js
141
- * `removeTrailingSlash` behaviour in
142
- * `.nextjs-ref/packages/next/src/build/static-paths/pages.ts`). For an object
143
- * entry with a missing `params` key, return false rather than throwing — the
144
- * caller will respond with a 404 just like Next.js does for unlisted paths.
145
- */
146
- function matchesPagesStaticPath(pathEntry, params, routeUrl) {
131
+ function getPagesRouteParams(routePattern) {
132
+ return routePattern.split("/").map((segment) => {
133
+ const optionalCatchAll = segment.match(/^\[\[\.\.\.(.+)\]\]$/);
134
+ if (optionalCatchAll) return {
135
+ key: optionalCatchAll[1],
136
+ repeat: true,
137
+ optional: true
138
+ };
139
+ const requiredCatchAll = segment.match(/^\[\.\.\.(.+)\]$/);
140
+ if (requiredCatchAll) return {
141
+ key: requiredCatchAll[1],
142
+ repeat: true,
143
+ optional: false
144
+ };
145
+ const dynamic = segment.match(/^\[(.+)\]$/);
146
+ if (dynamic) return {
147
+ key: dynamic[1],
148
+ repeat: false,
149
+ optional: false
150
+ };
151
+ return null;
152
+ }).filter((param) => param !== null);
153
+ }
154
+ function matchesPagesStaticPath(pathEntry, params, routeParams, routeUrl) {
147
155
  if (typeof pathEntry === "string") return normalizeStaticPathname(pathEntry) === normalizeStaticPathname(routeUrl);
148
156
  const entryParams = pathEntry.params;
149
157
  if (entryParams === void 0 || entryParams === null) return false;
150
- return Object.entries(entryParams).every(([key, value]) => {
158
+ return routeParams.every(({ key, repeat, optional }) => {
159
+ if (!Object.hasOwn(entryParams, key)) return false;
160
+ let value = entryParams[key];
161
+ if (optional && (value === null || value === void 0 || value === false)) value = [];
162
+ if (repeat) {
163
+ if (!Array.isArray(value) || !optional && value.length === 0) return false;
164
+ } else if (typeof value !== "string") return false;
151
165
  const actual = params[key];
152
- if (Array.isArray(value)) return Array.isArray(actual) && value.join("/") === actual.join("/");
166
+ if (Array.isArray(value)) {
167
+ if (optional && value.length === 0 && actual === void 0) return true;
168
+ return Array.isArray(actual) && value.join("/") === actual.join("/");
169
+ }
153
170
  return String(value) === String(actual);
154
171
  });
155
172
  }
@@ -237,7 +254,9 @@ async function resolvePagesPageData(options) {
237
254
  defaultLocale: options.i18n.defaultLocale ?? ""
238
255
  });
239
256
  const fallback = pathsResult?.fallback ?? false;
240
- const isValidPath = (pathsResult?.paths ?? []).some((pathEntry) => matchesPagesStaticPath(pathEntry, options.params, options.routeUrl));
257
+ const paths = pathsResult?.paths ?? [];
258
+ const routeParams = getPagesRouteParams(options.routePattern);
259
+ const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, options.params, routeParams, options.routeUrl));
241
260
  if (fallback === false && !isValidPath) return buildPagesNotFoundResult(options);
242
261
  const isBotRequest = !!options.userAgent && isBotUserAgent(options.userAgent, options.htmlLimitedBots);
243
262
  if (fallback === true && !isValidPath && !options.isDataReq && !isBotRequest) isFallback = true;
@@ -273,6 +292,7 @@ async function resolvePagesPageData(options) {
273
292
  };
274
293
  return {
275
294
  kind: "render",
295
+ documentReqRes: sharedReqRes,
276
296
  gsspRes: null,
277
297
  isrRevalidateSeconds: null,
278
298
  pageProps,
@@ -473,6 +493,7 @@ async function resolvePagesPageData(options) {
473
493
  }
474
494
  return {
475
495
  kind: "render",
496
+ documentReqRes: sharedReqRes,
476
497
  gsspRes,
477
498
  isrRevalidateSeconds,
478
499
  pageProps,
@@ -481,4 +502,4 @@ async function resolvePagesPageData(options) {
481
502
  };
482
503
  }
483
504
  //#endregion
484
- export { renderPagesIsrHtml, resolvePagesPageData };
505
+ export { getPagesRouteParams, matchesPagesStaticPath, renderPagesIsrHtml, resolvePagesPageData };
@@ -35,6 +35,7 @@ type VinextConfigSubset = {
35
35
  clientTraceMetadata?: readonly string[];
36
36
  disableOptimizedLoading: boolean;
37
37
  };
38
+ declare function shouldEmitPagesClientTraceMetadata(pageModule: PagesPageModule, appComponent: unknown): boolean;
38
39
  /**
39
40
  * Options accepted by `createPagesPageHandler`.
40
41
  *
@@ -97,4 +98,4 @@ type RenderPageOptions = {
97
98
  */
98
99
  declare function createPagesPageHandler(opts: CreatePagesPageHandlerOptions): (request: Request, url: string, manifest: Record<string, string[]> | null | undefined, middlewareHeaders: Headers | null | undefined, options: RenderPageOptions | null | undefined) => Promise<Response>;
99
100
  //#endregion
100
- export { CreatePagesPageHandlerOptions, createPagesPageHandler };
101
+ export { CreatePagesPageHandlerOptions, createPagesPageHandler, shouldEmitPagesClientTraceMetadata };