vinext 0.1.8 → 0.2.1

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 (285) hide show
  1. package/README.md +51 -30
  2. package/dist/build/css-url-assets.d.ts +3 -1
  3. package/dist/build/css-url-assets.js +18 -1
  4. package/dist/build/inject-pregenerated-paths.d.ts +7 -0
  5. package/dist/build/inject-pregenerated-paths.js +21 -0
  6. package/dist/build/layout-classification.js +1 -1
  7. package/dist/build/nitro-route-rules.js +1 -1
  8. package/dist/build/pages-client-assets-module.d.ts +11 -0
  9. package/dist/build/pages-client-assets-module.js +27 -0
  10. package/dist/build/prerender-server-entry.d.ts +1 -0
  11. package/dist/build/prerender-server-entry.js +49 -0
  12. package/dist/build/prerender-server-pool.d.ts +44 -0
  13. package/dist/build/prerender-server-pool.js +194 -0
  14. package/dist/build/prerender.d.ts +2 -1
  15. package/dist/build/prerender.js +98 -27
  16. package/dist/build/report.d.ts +13 -2
  17. package/dist/build/report.js +99 -2
  18. package/dist/build/run-prerender.d.ts +7 -0
  19. package/dist/build/run-prerender.js +12 -2
  20. package/dist/build/standalone.js +2 -0
  21. package/dist/cache/cache-adapters-virtual.js +3 -3
  22. package/dist/check.d.ts +4 -6
  23. package/dist/check.js +48 -11
  24. package/dist/cli-args.d.ts +1 -2
  25. package/dist/cli-args.js +1 -1
  26. package/dist/cli-dev-config.d.ts +12 -0
  27. package/dist/cli-dev-config.js +23 -0
  28. package/dist/cli.js +112 -96
  29. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  30. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  31. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  32. package/dist/{server → client}/dev-error-overlay.js +2 -2
  33. package/dist/client/navigation-runtime.d.ts +2 -0
  34. package/dist/client/navigation-runtime.js +3 -1
  35. package/dist/client/vinext-next-data.d.ts +4 -1
  36. package/dist/client/window-next.d.ts +2 -1
  37. package/dist/cloudflare/index.d.ts +2 -2
  38. package/dist/cloudflare/index.js +2 -2
  39. package/dist/config/config-matchers.js +45 -19
  40. package/dist/config/next-config.d.ts +41 -9
  41. package/dist/config/next-config.js +60 -3
  42. package/dist/config/prerender.d.ts +34 -0
  43. package/dist/config/prerender.js +55 -0
  44. package/dist/entries/app-browser-entry.js +5 -1
  45. package/dist/entries/app-rsc-entry.d.ts +5 -3
  46. package/dist/entries/app-rsc-entry.js +44 -10
  47. package/dist/entries/app-rsc-manifest.js +2 -0
  48. package/dist/entries/pages-client-entry.d.ts +3 -0
  49. package/dist/entries/pages-client-entry.js +28 -3
  50. package/dist/entries/pages-server-entry.js +23 -6
  51. package/dist/image/image-adapters-virtual.d.ts +59 -0
  52. package/dist/image/image-adapters-virtual.js +59 -0
  53. package/dist/index.d.ts +33 -0
  54. package/dist/index.js +482 -120
  55. package/dist/init-cloudflare.d.ts +43 -0
  56. package/dist/init-cloudflare.js +839 -0
  57. package/dist/init-platform.d.ts +40 -0
  58. package/dist/init-platform.js +195 -0
  59. package/dist/init.d.ts +16 -38
  60. package/dist/init.js +209 -99
  61. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  62. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  63. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  64. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  65. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +9 -2
  66. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  67. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  68. package/dist/packages/cloudflare/src/deploy.js +272 -0
  69. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  70. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +44 -20
  71. package/dist/plugins/ast-scope.d.ts +16 -0
  72. package/dist/plugins/ast-scope.js +62 -0
  73. package/dist/plugins/ast-utils.d.ts +27 -1
  74. package/dist/plugins/ast-utils.js +32 -1
  75. package/dist/plugins/css-module-imports.d.ts +14 -0
  76. package/dist/plugins/css-module-imports.js +59 -0
  77. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  78. package/dist/plugins/fonts.js +1 -1
  79. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  80. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  81. package/dist/plugins/og-assets.js +2 -1
  82. package/dist/plugins/optimize-imports.js +1 -1
  83. package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
  84. package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
  85. package/dist/plugins/sass.d.ts +17 -1
  86. package/dist/plugins/sass.js +74 -1
  87. package/dist/plugins/styled-jsx.d.ts +16 -0
  88. package/dist/plugins/styled-jsx.js +149 -0
  89. package/dist/plugins/typeof-window.d.ts +1 -1
  90. package/dist/plugins/typeof-window.js +28 -56
  91. package/dist/routing/app-route-graph.d.ts +23 -2
  92. package/dist/routing/app-route-graph.js +138 -38
  93. package/dist/routing/file-matcher.d.ts +11 -1
  94. package/dist/routing/file-matcher.js +18 -3
  95. package/dist/routing/pages-router.js +2 -2
  96. package/dist/server/api-handler.js +9 -14
  97. package/dist/server/app-browser-action-result.d.ts +4 -1
  98. package/dist/server/app-browser-action-result.js +8 -1
  99. package/dist/server/app-browser-entry.js +198 -57
  100. package/dist/server/app-browser-interception-context.d.ts +1 -0
  101. package/dist/server/app-browser-interception-context.js +4 -2
  102. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  103. package/dist/server/app-browser-navigation-controller.js +60 -31
  104. package/dist/server/app-browser-server-action-client.d.ts +1 -1
  105. package/dist/server/app-browser-server-action-client.js +8 -7
  106. package/dist/server/app-browser-state.d.ts +12 -1
  107. package/dist/server/app-browser-state.js +25 -8
  108. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  109. package/dist/server/app-browser-visible-commit.js +42 -24
  110. package/dist/server/app-elements-wire.d.ts +9 -2
  111. package/dist/server/app-elements-wire.js +8 -1
  112. package/dist/server/app-elements.d.ts +2 -2
  113. package/dist/server/app-elements.js +4 -3
  114. package/dist/server/app-fallback-renderer.d.ts +2 -1
  115. package/dist/server/app-fallback-renderer.js +10 -6
  116. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  117. package/dist/server/app-hydration-cache-publication.js +43 -0
  118. package/dist/server/app-middleware.d.ts +4 -3
  119. package/dist/server/app-middleware.js +8 -3
  120. package/dist/server/app-optimistic-routing.js +11 -4
  121. package/dist/server/app-page-boundary.js +2 -1
  122. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  123. package/dist/server/app-page-cache-finalizer.js +5 -4
  124. package/dist/server/app-page-cache-render.d.ts +1 -0
  125. package/dist/server/app-page-cache-render.js +8 -4
  126. package/dist/server/app-page-cache.d.ts +1 -0
  127. package/dist/server/app-page-cache.js +27 -7
  128. package/dist/server/app-page-dispatch.d.ts +1 -0
  129. package/dist/server/app-page-dispatch.js +26 -8
  130. package/dist/server/app-page-element-builder.d.ts +2 -1
  131. package/dist/server/app-page-element-builder.js +59 -4
  132. package/dist/server/app-page-execution.js +2 -1
  133. package/dist/server/app-page-probe.js +5 -0
  134. package/dist/server/app-page-render-identity.d.ts +2 -0
  135. package/dist/server/app-page-render-identity.js +3 -2
  136. package/dist/server/app-page-render.d.ts +2 -0
  137. package/dist/server/app-page-render.js +85 -16
  138. package/dist/server/app-page-request.d.ts +14 -0
  139. package/dist/server/app-page-request.js +69 -4
  140. package/dist/server/app-page-response.d.ts +7 -0
  141. package/dist/server/app-page-response.js +16 -4
  142. package/dist/server/app-page-route-wiring.d.ts +8 -1
  143. package/dist/server/app-page-route-wiring.js +32 -18
  144. package/dist/server/app-page-segment-state.d.ts +2 -1
  145. package/dist/server/app-page-segment-state.js +3 -1
  146. package/dist/server/app-page-stream.d.ts +7 -1
  147. package/dist/server/app-page-stream.js +3 -1
  148. package/dist/server/app-route-handler-execution.js +5 -1
  149. package/dist/server/app-route-handler-response.js +1 -0
  150. package/dist/server/app-route-handler-runtime.js +1 -1
  151. package/dist/server/app-route-tree-prefetch.d.ts +43 -0
  152. package/dist/server/app-route-tree-prefetch.js +187 -0
  153. package/dist/server/app-router-entry.js +9 -2
  154. package/dist/server/app-rsc-cache-busting.d.ts +2 -1
  155. package/dist/server/app-rsc-cache-busting.js +9 -4
  156. package/dist/server/app-rsc-handler.d.ts +7 -0
  157. package/dist/server/app-rsc-handler.js +148 -39
  158. package/dist/server/app-rsc-render-mode.d.ts +3 -2
  159. package/dist/server/app-rsc-render-mode.js +4 -1
  160. package/dist/server/app-rsc-request-normalization.d.ts +6 -6
  161. package/dist/server/app-rsc-request-normalization.js +10 -8
  162. package/dist/server/app-segment-config.d.ts +11 -0
  163. package/dist/server/app-segment-config.js +62 -6
  164. package/dist/server/app-server-action-execution.d.ts +1 -0
  165. package/dist/server/app-server-action-execution.js +61 -30
  166. package/dist/server/app-ssr-entry.d.ts +3 -0
  167. package/dist/server/app-ssr-entry.js +13 -5
  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-visited-response-cache.d.ts +6 -0
  171. package/dist/server/app-visited-response-cache.js +3 -1
  172. package/dist/server/cache-control.d.ts +3 -1
  173. package/dist/server/cache-control.js +13 -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.d.ts +11 -1
  179. package/dist/server/dev-server.js +94 -35
  180. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  181. package/dist/server/dev-stack-sourcemap.js +1 -1
  182. package/dist/server/fetch-handler.d.ts +2 -0
  183. package/dist/server/fetch-handler.js +18 -0
  184. package/dist/server/headers.d.ts +7 -15
  185. package/dist/server/headers.js +11 -18
  186. package/dist/server/image-optimization.d.ts +51 -1
  187. package/dist/server/image-optimization.js +52 -2
  188. package/dist/server/implicit-tags.js +1 -1
  189. package/dist/server/isr-cache.d.ts +3 -2
  190. package/dist/server/isr-cache.js +9 -5
  191. package/dist/server/metadata-routes.d.ts +3 -1
  192. package/dist/server/metadata-routes.js +12 -2
  193. package/dist/server/middleware-runtime.js +6 -1
  194. package/dist/server/navigation-planner.d.ts +1 -0
  195. package/dist/server/navigation-planner.js +14 -3
  196. package/dist/server/pages-api-route.js +2 -2
  197. package/dist/server/pages-asset-tags.d.ts +4 -6
  198. package/dist/server/pages-asset-tags.js +12 -12
  199. package/dist/server/pages-client-assets.d.ts +12 -0
  200. package/dist/server/pages-client-assets.js +10 -0
  201. package/dist/server/pages-data-route.d.ts +4 -2
  202. package/dist/server/pages-data-route.js +18 -4
  203. package/dist/server/pages-dev-module-url.d.ts +2 -1
  204. package/dist/server/pages-dev-module-url.js +6 -3
  205. package/dist/server/pages-node-compat.d.ts +19 -1
  206. package/dist/server/pages-node-compat.js +81 -4
  207. package/dist/server/pages-page-data.d.ts +33 -1
  208. package/dist/server/pages-page-data.js +62 -33
  209. package/dist/server/pages-page-handler.d.ts +2 -1
  210. package/dist/server/pages-page-handler.js +38 -19
  211. package/dist/server/pages-page-response.d.ts +8 -0
  212. package/dist/server/pages-page-response.js +7 -3
  213. package/dist/server/pages-request-pipeline.d.ts +9 -5
  214. package/dist/server/pages-request-pipeline.js +55 -7
  215. package/dist/server/pages-router-entry.d.ts +30 -0
  216. package/dist/server/pages-router-entry.js +108 -0
  217. package/dist/server/prerender-manifest.d.ts +3 -1
  218. package/dist/server/prerender-route-params.js +1 -1
  219. package/dist/server/prod-server.d.ts +5 -3
  220. package/dist/server/prod-server.js +68 -39
  221. package/dist/server/request-pipeline.js +2 -1
  222. package/dist/server/seed-cache.js +4 -4
  223. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  224. package/dist/shims/app-router-scroll-state.js +1 -0
  225. package/dist/shims/app-router-scroll.js +2 -1
  226. package/dist/shims/cache-handler.js +8 -1
  227. package/dist/shims/cache.js +22 -15
  228. package/dist/shims/cdn-cache.js +1 -1
  229. package/dist/shims/dynamic-preload-chunks.js +2 -1
  230. package/dist/shims/fetch-cache.d.ts +3 -1
  231. package/dist/shims/fetch-cache.js +77 -52
  232. package/dist/shims/form.d.ts +4 -2
  233. package/dist/shims/form.js +37 -43
  234. package/dist/shims/headers.d.ts +7 -1
  235. package/dist/shims/headers.js +17 -3
  236. package/dist/shims/image.js +75 -14
  237. package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
  238. package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
  239. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  240. package/dist/shims/internal/app-route-detection.js +4 -17
  241. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  242. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  243. package/dist/shims/internal/hybrid-client-route-owner.d.ts +3 -15
  244. package/dist/shims/internal/hybrid-client-route-owner.js +40 -58
  245. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +10 -5
  246. package/dist/shims/internal/pages-data-fetch-dedup.js +84 -14
  247. package/dist/shims/internal/pages-data-target.d.ts +18 -12
  248. package/dist/shims/internal/pages-data-target.js +97 -13
  249. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  250. package/dist/shims/internal/pages-router-components.js +13 -0
  251. package/dist/shims/layout-segment-context.d.ts +4 -1
  252. package/dist/shims/layout-segment-context.js +18 -4
  253. package/dist/shims/link.d.ts +1 -1
  254. package/dist/shims/link.js +224 -58
  255. package/dist/shims/navigation.d.ts +19 -3
  256. package/dist/shims/navigation.js +245 -47
  257. package/dist/shims/request-context.js +18 -0
  258. package/dist/shims/root-params.d.ts +15 -1
  259. package/dist/shims/root-params.js +21 -1
  260. package/dist/shims/router.d.ts +5 -7
  261. package/dist/shims/router.js +387 -102
  262. package/dist/shims/server.js +3 -2
  263. package/dist/shims/slot.js +3 -6
  264. package/dist/shims/unified-request-context.js +1 -0
  265. package/dist/typegen.js +1 -1
  266. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  267. package/dist/utils/client-runtime-metadata.js +31 -22
  268. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  269. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  270. package/dist/utils/domain-locale.d.ts +6 -3
  271. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  272. package/dist/{server → utils}/middleware-request-headers.js +3 -3
  273. package/dist/utils/project.d.ts +48 -2
  274. package/dist/utils/project.js +225 -4
  275. package/dist/utils/protocol-headers.d.ts +23 -0
  276. package/dist/utils/protocol-headers.js +23 -0
  277. package/dist/utils/react-version.d.ts +4 -0
  278. package/dist/utils/react-version.js +44 -0
  279. package/dist/utils/vite-version.d.ts +2 -0
  280. package/dist/utils/vite-version.js +11 -1
  281. package/package.json +47 -2
  282. package/dist/deploy.d.ts +0 -197
  283. package/dist/deploy.js +0 -1040
  284. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  285. /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));
@@ -34,6 +34,7 @@ declare const PRERENDER_REVALIDATE_HEADER = "x-prerender-revalidate";
34
34
  */
35
35
  declare const PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER = "x-prerender-revalidate-if-generated";
36
36
  declare function getRevalidateSecret(): string;
37
+ declare function isRevalidateSecret(value: string | null | undefined): boolean;
37
38
  /**
38
39
  * Authorize an incoming request as an on-demand revalidation trigger. Mirrors
39
40
  * Next.js's `checkIsOnDemandRevalidate`: the {@link PRERENDER_REVALIDATE_HEADER}
@@ -95,7 +96,7 @@ declare function buildPagesCacheValue(html: string, pageData: object, status?: n
95
96
  /**
96
97
  * Build a CachedAppPageValue for the App Router ISR cache.
97
98
  */
98
- declare function buildAppPageCacheValue(html: string, rscData?: ArrayBuffer, status?: number, renderObservation?: RenderObservation): CachedAppPageValue;
99
+ declare function buildAppPageCacheValue(html: string, rscData?: ArrayBuffer, status?: number, renderObservation?: RenderObservation, headers?: CachedAppPageValue["headers"]): CachedAppPageValue;
99
100
  /**
100
101
  * Compute an ISR cache key for a given router type and pathname.
101
102
  * Long pathnames are hashed to stay within KV key-length limits (512 bytes).
@@ -124,4 +125,4 @@ declare function setRevalidateDuration(key: string, seconds: number): void;
124
125
  */
125
126
  declare function getRevalidateDuration(key: string): number | undefined;
126
127
  //#endregion
127
- export { ISRCacheEntry, PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, getRevalidateDuration, getRevalidateSecret, isOnDemandRevalidateRequest, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, setRevalidateDuration, triggerBackgroundRegeneration };
128
+ export { ISRCacheEntry, PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, getRevalidateDuration, getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, setRevalidateDuration, triggerBackgroundRegeneration };
@@ -80,6 +80,10 @@ function safeEqual(a, b) {
80
80
  for (let i = 0; i < a.length; i++) mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);
81
81
  return mismatch === 0;
82
82
  }
83
+ function isRevalidateSecret(value) {
84
+ if (typeof value !== "string" || value.length === 0) return false;
85
+ return safeEqual(value, getRevalidateSecret());
86
+ }
83
87
  /**
84
88
  * Authorize an incoming request as an on-demand revalidation trigger. Mirrors
85
89
  * Next.js's `checkIsOnDemandRevalidate`: the {@link PRERENDER_REVALIDATE_HEADER}
@@ -87,8 +91,8 @@ function safeEqual(a, b) {
87
91
  * NOT sufficient — see the security note on {@link PRERENDER_REVALIDATE_HEADER}.
88
92
  */
89
93
  function isOnDemandRevalidateRequest(headerValue) {
90
- if (typeof headerValue !== "string" || headerValue.length === 0) return false;
91
- return safeEqual(headerValue, getRevalidateSecret());
94
+ if (typeof headerValue !== "string") return false;
95
+ return isRevalidateSecret(headerValue);
92
96
  }
93
97
  /**
94
98
  * Get a cache entry with staleness information.
@@ -188,12 +192,12 @@ function buildPagesCacheValue(html, pageData, status) {
188
192
  /**
189
193
  * Build a CachedAppPageValue for the App Router ISR cache.
190
194
  */
191
- function buildAppPageCacheValue(html, rscData, status, renderObservation) {
195
+ function buildAppPageCacheValue(html, rscData, status, renderObservation, headers) {
192
196
  const value = {
193
197
  kind: "APP_PAGE",
194
198
  html,
195
199
  rscData,
196
- headers: void 0,
200
+ headers,
197
201
  postponed: void 0,
198
202
  status
199
203
  };
@@ -279,4 +283,4 @@ function getRevalidateDuration(key) {
279
283
  return revalidateDurations.get(key);
280
284
  }
281
285
  //#endregion
282
- export { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, getRevalidateDuration, getRevalidateSecret, isOnDemandRevalidateRequest, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, setRevalidateDuration, triggerBackgroundRegeneration };
286
+ export { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, getRevalidateDuration, getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, setRevalidateDuration, triggerBackgroundRegeneration };
@@ -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 };
@@ -51,6 +51,7 @@ declare function isNextDataPathname(pathname: string): boolean;
51
51
  * `/_next/data/<buildId>/about` → null (missing .json suffix)
52
52
  */
53
53
  declare function parseNextDataPathname(pathname: string, buildId: string): NextDataMatch | null;
54
+ declare function normalizeNextDataPagePathname(pagePathname: string, trailingSlash?: boolean): string;
54
55
  /**
55
56
  * Build the JSON envelope returned by `/_next/data/<buildId>/<page>.json`.
56
57
  * Mirrors Next.js' `RenderResult(JSON.stringify(props))` path in
@@ -79,6 +80,7 @@ declare function buildNextDataPropsJsonResponse(props: Record<string, unknown>,
79
80
  * before checking the status code.
80
81
  */
81
82
  declare function buildNextDataNotFoundResponse(): Response;
83
+ declare function buildMiddlewarePrefetchSkipResponse(matchedPathname: string): Response;
82
84
  type NormalizePagesDataRequestResult = {
83
85
  isDataReq: false;
84
86
  request: Request;
@@ -116,6 +118,6 @@ type NormalizePagesDataRequestResult = {
116
118
  * Extracted from `entries/pages-server-entry.ts` so both `renderPage` and
117
119
  * `runMiddleware` share a single implementation.
118
120
  */
119
- declare function normalizePagesDataRequest(request: Request, buildId: string | null, basePath?: string): NormalizePagesDataRequestResult;
121
+ declare function normalizePagesDataRequest(request: Request, buildId: string | null, basePath?: string, trailingSlash?: boolean): NormalizePagesDataRequestResult;
120
122
  //#endregion
121
- export { buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizePagesDataRequest, parseNextDataPathname };
123
+ export { buildMiddlewarePrefetchSkipResponse, buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizeNextDataPagePathname, normalizePagesDataRequest, parseNextDataPathname };
@@ -1,4 +1,5 @@
1
1
  import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
2
+ import { MIDDLEWARE_SKIP_HEADER } from "../utils/protocol-headers.js";
2
3
  import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
3
4
  //#region src/server/pages-data-route.ts
4
5
  /**
@@ -58,6 +59,10 @@ function parseNextDataPathname(pathname, buildId) {
58
59
  if (rest.startsWith("index/")) return { pagePathname: `/${rest.slice(6)}` };
59
60
  return { pagePathname: `/${rest}` };
60
61
  }
62
+ function normalizeNextDataPagePathname(pagePathname, trailingSlash = false) {
63
+ if (!trailingSlash || pagePathname === "/" || pagePathname.endsWith("/")) return pagePathname;
64
+ return `${pagePathname}/`;
65
+ }
61
66
  /**
62
67
  * Build the JSON envelope returned by `/_next/data/<buildId>/<page>.json`.
63
68
  * Mirrors Next.js' `RenderResult(JSON.stringify(props))` path in
@@ -106,6 +111,14 @@ function buildNextDataNotFoundResponse() {
106
111
  headers
107
112
  });
108
113
  }
114
+ function buildMiddlewarePrefetchSkipResponse(matchedPathname) {
115
+ return new Response("{}", { headers: {
116
+ "Content-Type": "application/json",
117
+ "x-matched-path": matchedPathname,
118
+ [MIDDLEWARE_SKIP_HEADER]: "1",
119
+ "Cache-Control": "private, no-cache, no-store, max-age=0, must-revalidate"
120
+ } });
121
+ }
109
122
  /**
110
123
  * Detect and normalize `/_next/data/<buildId>/<page>.json` requests in one
111
124
  * place so the Pages Router pipeline and middleware shim do not need to know
@@ -124,7 +137,7 @@ function buildNextDataNotFoundResponse() {
124
137
  * Extracted from `entries/pages-server-entry.ts` so both `renderPage` and
125
138
  * `runMiddleware` share a single implementation.
126
139
  */
127
- function normalizePagesDataRequest(request, buildId, basePath = "") {
140
+ function normalizePagesDataRequest(request, buildId, basePath = "", trailingSlash = false) {
128
141
  const reqUrl = new URL(request.url);
129
142
  const hadBasePath = !!basePath && hasBasePath(reqUrl.pathname, basePath);
130
143
  const dataPathname = basePath ? stripBasePath(reqUrl.pathname, basePath) : reqUrl.pathname;
@@ -143,15 +156,16 @@ function normalizePagesDataRequest(request, buildId, basePath = "") {
143
156
  search: "",
144
157
  notFoundResponse: buildNextDataNotFoundResponse()
145
158
  };
159
+ const pagePathname = normalizeNextDataPagePathname(dataMatch.pagePathname, trailingSlash);
146
160
  const normalizedUrl = new URL(reqUrl);
147
- normalizedUrl.pathname = hadBasePath ? addBasePathToPathname(dataMatch.pagePathname, basePath) : dataMatch.pagePathname;
161
+ normalizedUrl.pathname = hadBasePath ? addBasePathToPathname(pagePathname, basePath) : pagePathname;
148
162
  return {
149
163
  isDataReq: true,
150
164
  request: new Request(normalizedUrl, request),
151
- normalizedPathname: dataMatch.pagePathname,
165
+ normalizedPathname: pagePathname,
152
166
  search: reqUrl.search,
153
167
  notFoundResponse: null
154
168
  };
155
169
  }
156
170
  //#endregion
157
- export { buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizePagesDataRequest, parseNextDataPathname };
171
+ export { buildMiddlewarePrefetchSkipResponse, buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizeNextDataPagePathname, normalizePagesDataRequest, parseNextDataPathname };
@@ -1,4 +1,5 @@
1
1
  //#region src/server/pages-dev-module-url.d.ts
2
+ declare function createPagesDevAssetUrl(assetPath: string): string;
2
3
  declare function createPagesDevModuleUrl(viteRoot: string, moduleFilePath: string, viteBase: string): string;
3
4
  //#endregion
4
- export { createPagesDevModuleUrl };
5
+ export { createPagesDevAssetUrl, createPagesDevModuleUrl };
@@ -4,12 +4,15 @@ function normalizeBase(base) {
4
4
  if (!base || base === "/") return "/";
5
5
  return `/${base.replace(/^\/+|\/+$/g, "")}/`;
6
6
  }
7
- function encodeModulePath(modulePath) {
7
+ function encodePagesDevModulePath(modulePath) {
8
8
  return encodeURI(modulePath).replace(/%5B/gi, "[").replace(/%5D/gi, "]").replace(/\?/g, "%3F").replace(/#/g, "%23");
9
9
  }
10
+ function createPagesDevAssetUrl(assetPath) {
11
+ return "/" + encodePagesDevModulePath(assetPath.replace(/^\/+/, ""));
12
+ }
10
13
  function createPagesDevModuleUrl(viteRoot, moduleFilePath, viteBase) {
11
14
  const relativePath = (/^[A-Za-z]:[\\/]/.test(viteRoot) ? path.win32 : path).relative(viteRoot, moduleFilePath).replace(/\\/g, "/");
12
- return normalizeBase(viteBase) + encodeModulePath(relativePath);
15
+ return normalizeBase(viteBase) + encodePagesDevModulePath(relativePath);
13
16
  }
14
17
  //#endregion
15
- export { createPagesDevModuleUrl };
18
+ export { createPagesDevAssetUrl, createPagesDevModuleUrl };
@@ -27,6 +27,16 @@ type PagesReqResResponse = Writable & {
27
27
  redirect: (statusOrUrl: number | string, url?: string) => void;
28
28
  getHeaders: () => PagesReqResHeaders;
29
29
  revalidate: (urlPath: string, opts?: RevalidateOptions) => Promise<void>;
30
+ setPreviewData: (data: object | string, options?: {
31
+ maxAge?: number;
32
+ path?: string;
33
+ }) => PagesReqResResponse;
34
+ };
35
+ type PagesRequestCookiesCarrier = {
36
+ headers: {
37
+ cookie?: string | string[] | null | undefined;
38
+ };
39
+ cookies?: unknown;
30
40
  };
31
41
  type CreatePagesReqResOptions = {
32
42
  body: unknown;
@@ -39,6 +49,7 @@ type CreatePagesReqResResult = {
39
49
  res: PagesReqResResponse;
40
50
  responsePromise: Promise<Response>;
41
51
  };
52
+ type PagesPreviewData = object | string;
42
53
  /**
43
54
  * Read and parse a Pages Router API request body for the Workers/prod path.
44
55
  *
@@ -50,6 +61,13 @@ type CreatePagesReqResResult = {
50
61
  * @see https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config
51
62
  */
52
63
  declare function parsePagesApiBody(request: Request, maxBytes?: number): Promise<unknown>;
64
+ declare function getPagesPreviewDataFromCookieHeader(cookieHeader: string | string[] | null | undefined, options?: {
65
+ isOnDemandRevalidate?: boolean;
66
+ }): PagesPreviewData | false;
67
+ declare function getPagesPreviewData(request: Request, options?: {
68
+ isOnDemandRevalidate?: boolean;
69
+ }): PagesPreviewData | false;
70
+ declare function attachPagesRequestCookies(req: PagesRequestCookiesCarrier): void;
53
71
  declare function createPagesReqRes(options: CreatePagesReqResOptions): CreatePagesReqResResult;
54
72
  //#endregion
55
- export { PagesBodyParseError as PagesApiBodyParseError, PagesReqResRequest, PagesReqResResponse, PagesRequestQuery, createPagesReqRes, parsePagesApiBody };
73
+ export { PagesBodyParseError as PagesApiBodyParseError, PagesPreviewData, PagesReqResRequest, PagesReqResResponse, PagesRequestQuery, attachPagesRequestCookies, createPagesReqRes, getPagesPreviewData, getPagesPreviewDataFromCookieHeader, parsePagesApiBody };