vinext 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/build/prerender.d.ts +9 -1
  5. package/dist/build/prerender.js +41 -12
  6. package/dist/build/run-prerender.d.ts +10 -2
  7. package/dist/build/run-prerender.js +15 -1
  8. package/dist/check.js +4 -3
  9. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  10. package/dist/client/app-nav-failure-handler.js +44 -0
  11. package/dist/client/navigation-runtime.d.ts +3 -2
  12. package/dist/client/vinext-next-data.d.ts +18 -1
  13. package/dist/client/window-next.d.ts +8 -5
  14. package/dist/client/window-next.js +12 -1
  15. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  16. package/dist/config/config-matchers.d.ts +11 -4
  17. package/dist/config/config-matchers.js +88 -16
  18. package/dist/config/next-config.d.ts +59 -4
  19. package/dist/config/next-config.js +149 -48
  20. package/dist/deploy.d.ts +30 -11
  21. package/dist/deploy.js +189 -101
  22. package/dist/entries/app-browser-entry.d.ts +9 -3
  23. package/dist/entries/app-browser-entry.js +21 -3
  24. package/dist/entries/app-rsc-entry.d.ts +2 -0
  25. package/dist/entries/app-rsc-entry.js +71 -6
  26. package/dist/entries/app-rsc-manifest.js +2 -0
  27. package/dist/entries/app-ssr-entry.js +1 -1
  28. package/dist/entries/pages-client-entry.js +54 -9
  29. package/dist/entries/pages-server-entry.js +48 -11
  30. package/dist/index.d.ts +0 -2
  31. package/dist/index.js +285 -139
  32. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  33. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  34. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  35. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  36. package/dist/plugins/og-assets.js +2 -2
  37. package/dist/plugins/optimize-imports.d.ts +10 -5
  38. package/dist/plugins/optimize-imports.js +27 -21
  39. package/dist/plugins/postcss.js +7 -7
  40. package/dist/plugins/sass.d.ts +53 -24
  41. package/dist/plugins/sass.js +249 -1
  42. package/dist/plugins/typeof-window.d.ts +14 -0
  43. package/dist/plugins/typeof-window.js +150 -0
  44. package/dist/plugins/wasm-module-import.d.ts +15 -0
  45. package/dist/plugins/wasm-module-import.js +50 -0
  46. package/dist/routing/app-route-graph.d.ts +25 -2
  47. package/dist/routing/app-route-graph.js +91 -22
  48. package/dist/routing/file-matcher.d.ts +10 -1
  49. package/dist/routing/file-matcher.js +23 -2
  50. package/dist/routing/pages-router.js +3 -3
  51. package/dist/routing/utils.d.ts +35 -6
  52. package/dist/routing/utils.js +59 -7
  53. package/dist/server/api-handler.d.ts +6 -1
  54. package/dist/server/api-handler.js +21 -15
  55. package/dist/server/app-browser-action-result.d.ts +19 -6
  56. package/dist/server/app-browser-action-result.js +19 -10
  57. package/dist/server/app-browser-entry.js +269 -297
  58. package/dist/server/app-browser-error.d.ts +10 -3
  59. package/dist/server/app-browser-error.js +47 -6
  60. package/dist/server/app-browser-history-controller.d.ts +104 -0
  61. package/dist/server/app-browser-history-controller.js +210 -0
  62. package/dist/server/app-browser-hydration.d.ts +2 -0
  63. package/dist/server/app-browser-hydration.js +1 -0
  64. package/dist/server/app-browser-navigation-controller.d.ts +7 -4
  65. package/dist/server/app-browser-navigation-controller.js +33 -9
  66. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  67. package/dist/server/app-browser-rsc-redirect.js +30 -8
  68. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  69. package/dist/server/app-browser-server-action-navigation.js +9 -0
  70. package/dist/server/app-browser-state.js +4 -7
  71. package/dist/server/app-browser-stream.js +86 -43
  72. package/dist/server/app-browser-visible-commit.js +1 -1
  73. package/dist/server/app-elements-wire.d.ts +6 -1
  74. package/dist/server/app-elements-wire.js +14 -4
  75. package/dist/server/app-elements.d.ts +2 -2
  76. package/dist/server/app-elements.js +2 -2
  77. package/dist/server/app-fallback-renderer.d.ts +3 -1
  78. package/dist/server/app-fallback-renderer.js +6 -2
  79. package/dist/server/app-middleware.js +1 -0
  80. package/dist/server/app-optimistic-routing.js +24 -3
  81. package/dist/server/app-page-boundary-render.d.ts +3 -1
  82. package/dist/server/app-page-boundary-render.js +31 -16
  83. package/dist/server/app-page-cache-render.d.ts +53 -0
  84. package/dist/server/app-page-cache-render.js +91 -0
  85. package/dist/server/app-page-cache.d.ts +16 -2
  86. package/dist/server/app-page-cache.js +71 -8
  87. package/dist/server/app-page-dispatch.d.ts +34 -0
  88. package/dist/server/app-page-dispatch.js +167 -97
  89. package/dist/server/app-page-element-builder.d.ts +23 -2
  90. package/dist/server/app-page-element-builder.js +42 -10
  91. package/dist/server/app-page-execution.d.ts +7 -2
  92. package/dist/server/app-page-execution.js +53 -18
  93. package/dist/server/app-page-probe.d.ts +1 -0
  94. package/dist/server/app-page-probe.js +4 -0
  95. package/dist/server/app-page-render-observation.d.ts +3 -1
  96. package/dist/server/app-page-render-observation.js +17 -1
  97. package/dist/server/app-page-render.d.ts +13 -2
  98. package/dist/server/app-page-render.js +48 -17
  99. package/dist/server/app-page-request.d.ts +3 -0
  100. package/dist/server/app-page-request.js +5 -3
  101. package/dist/server/app-page-response.js +1 -1
  102. package/dist/server/app-page-route-wiring.d.ts +5 -1
  103. package/dist/server/app-page-route-wiring.js +21 -11
  104. package/dist/server/app-page-stream.d.ts +16 -9
  105. package/dist/server/app-page-stream.js +12 -9
  106. package/dist/server/app-pages-bridge.d.ts +18 -0
  107. package/dist/server/app-pages-bridge.js +22 -5
  108. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  109. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  110. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  111. package/dist/server/app-ppr-fallback-shell.js +8 -1
  112. package/dist/server/app-route-handler-dispatch.js +9 -2
  113. package/dist/server/app-route-handler-policy.d.ts +1 -0
  114. package/dist/server/app-route-handler-response.js +11 -10
  115. package/dist/server/app-route-handler-runtime.js +12 -1
  116. package/dist/server/app-router-entry.js +5 -0
  117. package/dist/server/app-rsc-cache-busting.js +2 -0
  118. package/dist/server/app-rsc-handler.d.ts +25 -0
  119. package/dist/server/app-rsc-handler.js +153 -53
  120. package/dist/server/app-rsc-response-finalizer.js +1 -1
  121. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  122. package/dist/server/app-rsc-route-matching.js +2 -0
  123. package/dist/server/app-segment-config.d.ts +9 -1
  124. package/dist/server/app-segment-config.js +12 -3
  125. package/dist/server/app-server-action-execution.d.ts +12 -0
  126. package/dist/server/app-server-action-execution.js +47 -15
  127. package/dist/server/app-ssr-entry.d.ts +2 -0
  128. package/dist/server/app-ssr-entry.js +81 -8
  129. package/dist/server/app-ssr-stream.js +9 -1
  130. package/dist/server/cache-control.js +4 -0
  131. package/dist/server/dev-lockfile.js +2 -1
  132. package/dist/server/dev-server.d.ts +2 -2
  133. package/dist/server/dev-server.js +287 -63
  134. package/dist/server/headers.d.ts +8 -1
  135. package/dist/server/headers.js +8 -1
  136. package/dist/server/hybrid-route-priority.d.ts +22 -0
  137. package/dist/server/hybrid-route-priority.js +33 -0
  138. package/dist/server/image-optimization.d.ts +18 -9
  139. package/dist/server/image-optimization.js +37 -23
  140. package/dist/server/implicit-tags.d.ts +2 -1
  141. package/dist/server/implicit-tags.js +4 -1
  142. package/dist/server/instrumentation-runtime.d.ts +6 -0
  143. package/dist/server/instrumentation-runtime.js +8 -0
  144. package/dist/server/isr-decision.d.ts +79 -0
  145. package/dist/server/isr-decision.js +70 -0
  146. package/dist/server/metadata-route-response.js +5 -3
  147. package/dist/server/middleware-runtime.d.ts +13 -0
  148. package/dist/server/middleware-runtime.js +11 -7
  149. package/dist/server/middleware.js +1 -0
  150. package/dist/server/navigation-planner.d.ts +186 -22
  151. package/dist/server/navigation-planner.js +302 -0
  152. package/dist/server/navigation-trace.d.ts +18 -1
  153. package/dist/server/navigation-trace.js +18 -1
  154. package/dist/server/normalize-path.d.ts +0 -8
  155. package/dist/server/normalize-path.js +3 -1
  156. package/dist/server/otel-tracer-extension.d.ts +45 -0
  157. package/dist/server/otel-tracer-extension.js +89 -0
  158. package/dist/server/pages-api-route.d.ts +20 -3
  159. package/dist/server/pages-api-route.js +19 -3
  160. package/dist/server/pages-asset-tags.d.ts +16 -4
  161. package/dist/server/pages-asset-tags.js +22 -12
  162. package/dist/server/pages-data-route.d.ts +8 -1
  163. package/dist/server/pages-data-route.js +16 -3
  164. package/dist/server/pages-get-initial-props.d.ts +54 -4
  165. package/dist/server/pages-get-initial-props.js +43 -1
  166. package/dist/server/pages-node-compat.d.ts +3 -11
  167. package/dist/server/pages-node-compat.js +175 -122
  168. package/dist/server/pages-page-data.d.ts +39 -2
  169. package/dist/server/pages-page-data.js +261 -46
  170. package/dist/server/pages-page-handler.d.ts +5 -2
  171. package/dist/server/pages-page-handler.js +78 -25
  172. package/dist/server/pages-page-response.d.ts +47 -2
  173. package/dist/server/pages-page-response.js +73 -9
  174. package/dist/server/pages-readiness.d.ts +1 -1
  175. package/dist/server/pages-request-pipeline.d.ts +16 -1
  176. package/dist/server/pages-request-pipeline.js +96 -38
  177. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  178. package/dist/server/pregenerated-concrete-paths.js +2 -19
  179. package/dist/server/prerender-manifest.d.ts +33 -0
  180. package/dist/server/prerender-manifest.js +54 -0
  181. package/dist/server/prerender-route-params.d.ts +1 -2
  182. package/dist/server/prod-server.d.ts +39 -1
  183. package/dist/server/prod-server.js +107 -37
  184. package/dist/server/request-pipeline.d.ts +3 -15
  185. package/dist/server/request-pipeline.js +58 -47
  186. package/dist/server/rsc-stream-hints.d.ts +5 -1
  187. package/dist/server/rsc-stream-hints.js +6 -1
  188. package/dist/server/seed-cache.js +10 -18
  189. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  190. package/dist/shims/app-router-scroll-state.js +14 -2
  191. package/dist/shims/app-router-scroll.d.ts +3 -0
  192. package/dist/shims/app-router-scroll.js +28 -18
  193. package/dist/shims/cache-runtime.js +12 -4
  194. package/dist/shims/cache.d.ts +1 -0
  195. package/dist/shims/cache.js +1 -1
  196. package/dist/shims/cdn-cache.d.ts +5 -5
  197. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  198. package/dist/shims/dynamic-preload-chunks.js +79 -0
  199. package/dist/shims/dynamic.d.ts +4 -0
  200. package/dist/shims/dynamic.js +4 -2
  201. package/dist/shims/error-boundary.d.ts +6 -4
  202. package/dist/shims/error-boundary.js +7 -0
  203. package/dist/shims/error.js +38 -11
  204. package/dist/shims/error.react-server.d.ts +9 -0
  205. package/dist/shims/error.react-server.js +6 -0
  206. package/dist/shims/fetch-cache.d.ts +11 -1
  207. package/dist/shims/fetch-cache.js +55 -20
  208. package/dist/shims/hash-scroll.js +6 -1
  209. package/dist/shims/head.js +6 -1
  210. package/dist/shims/headers.d.ts +16 -2
  211. package/dist/shims/headers.js +66 -5
  212. package/dist/shims/image-config.js +7 -1
  213. package/dist/shims/internal/als-registry.js +28 -1
  214. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  215. package/dist/shims/internal/app-route-detection.js +18 -23
  216. package/dist/shims/internal/app-router-context.d.ts +5 -0
  217. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  218. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  219. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  220. package/dist/shims/internal/navigation-untracked.js +55 -0
  221. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  222. package/dist/shims/internal/pages-data-target.js +17 -8
  223. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  224. package/dist/shims/internal/pages-router-accessor.js +13 -0
  225. package/dist/shims/internal/router-context.d.ts +2 -1
  226. package/dist/shims/internal/router-context.js +3 -1
  227. package/dist/shims/link.js +12 -5
  228. package/dist/shims/metadata.d.ts +6 -2
  229. package/dist/shims/metadata.js +32 -14
  230. package/dist/shims/navigation.d.ts +14 -17
  231. package/dist/shims/navigation.js +93 -46
  232. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  233. package/dist/shims/ppr-fallback-shell.js +28 -7
  234. package/dist/shims/router.d.ts +13 -2
  235. package/dist/shims/router.js +434 -116
  236. package/dist/shims/script-nonce-context.d.ts +1 -1
  237. package/dist/shims/script-nonce-context.js +11 -3
  238. package/dist/shims/server.d.ts +33 -2
  239. package/dist/shims/server.js +75 -18
  240. package/dist/shims/slot.js +1 -1
  241. package/dist/shims/unified-request-context.js +2 -0
  242. package/dist/typegen.js +1 -0
  243. package/dist/utils/built-asset-url.d.ts +4 -0
  244. package/dist/utils/built-asset-url.js +11 -0
  245. package/dist/utils/client-build-manifest.js +15 -5
  246. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  247. package/dist/utils/client-runtime-metadata.js +63 -0
  248. package/dist/utils/commonjs-loader.d.ts +16 -0
  249. package/dist/utils/commonjs-loader.js +100 -0
  250. package/dist/utils/deployment-id.d.ts +8 -0
  251. package/dist/utils/deployment-id.js +22 -0
  252. package/dist/utils/hash.d.ts +17 -1
  253. package/dist/utils/hash.js +36 -1
  254. package/dist/utils/html-limited-bots.d.ts +18 -1
  255. package/dist/utils/html-limited-bots.js +23 -1
  256. package/dist/utils/lazy-chunks.d.ts +27 -1
  257. package/dist/utils/lazy-chunks.js +65 -1
  258. package/dist/utils/manifest-paths.d.ts +20 -2
  259. package/dist/utils/manifest-paths.js +38 -3
  260. package/dist/utils/parse-cookie.d.ts +13 -0
  261. package/dist/utils/parse-cookie.js +52 -0
  262. package/dist/utils/path.d.ts +8 -1
  263. package/dist/utils/path.js +13 -1
  264. package/package.json +2 -2
  265. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  266. package/dist/shims/internal/parse-cookie-header.js +0 -30
package/README.md CHANGED
@@ -528,22 +528,19 @@ The cache is pluggable. The default `MemoryCacheHandler` works out of the box. S
528
528
 
529
529
  #### Configuring cache adapters from `vite.config`
530
530
 
531
- Instead of wiring up cache handlers imperatively from a worker entry, you can declare them in the `vinext()` plugin config. The `@vinext/cloudflare` package ships two Cloudflare adapters for this:
531
+ Instead of wiring up cache handlers imperatively from a worker entry, you can declare them in the `vinext()` plugin config. The `@vinext/cloudflare` package ships Cloudflare adapters for this:
532
532
 
533
533
  - **`kvDataAdapter()`** (`@vinext/cloudflare/cache/kv-data-adapter`) — backs the `"use cache"` data cache with a Workers KV namespace.
534
- - **`cdnAdapter()`** (`@vinext/cloudflare/cache/cdn-adapter`) — backs full-route CDN caching with the Workers Cache API.
535
534
 
536
535
  ```ts
537
536
  import { defineConfig } from "vite";
538
537
  import vinext from "vinext";
539
- import { cdnAdapter } from "@vinext/cloudflare/cache/cdn-adapter";
540
538
  import { kvDataAdapter } from "@vinext/cloudflare/cache/kv-data-adapter";
541
539
 
542
540
  export default defineConfig({
543
541
  plugins: [
544
542
  vinext({
545
543
  cache: {
546
- cdn: cdnAdapter(),
547
544
  data: kvDataAdapter(),
548
545
  },
549
546
  }),
@@ -559,7 +556,7 @@ The KV data adapter reads `env[binding]` at runtime, so add the matching KV name
559
556
  }
560
557
  ```
561
558
 
562
- `binding` defaults to `VINEXT_KV_CACHE`, so `kvDataAdapter()` with no options works as long as that's your binding name. Other options: `appPrefix` (namespace cache keys to isolate multiple apps in one KV namespace), `ttlSeconds` (default KV `expirationTtl`, default 30 days), and `tagCacheTtlMs` (in-memory tag-invalidation cache TTL, default 5s). `cdnAdapter()` takes no options — it just needs the Workers Cache, which is always available on Workers.
559
+ `binding` defaults to `VINEXT_KV_CACHE`, so `kvDataAdapter()` with no options works as long as that's your binding name. Other options: `appPrefix` (namespace cache keys to isolate multiple apps in one KV namespace), `ttlSeconds` (default KV `expirationTtl`, default 30 days), and `tagCacheTtlMs` (in-memory tag-invalidation cache TTL, default 5s).
563
560
 
564
561
  Each builder returns a plain, serializable `{ adapter, options }` descriptor — **it never touches the Workers runtime**, so nothing throws at build or dev time when bindings aren't available. The actual adapter (and its `env` binding lookup) is instantiated lazily on the first request.
565
562
 
@@ -51,10 +51,16 @@ declare function createClientManualChunks(shimsDir: string): (id: string) => str
51
51
  * compression efficiency — small files restart the compression dictionary,
52
52
  * adding ~5-15% wire overhead vs fewer larger chunks.
53
53
  */
54
+ declare function createClientFileNameConfig(assetsDir: string): {
55
+ entryFileNames: string;
56
+ chunkFileNames: string;
57
+ };
54
58
  declare function createClientOutputConfig(clientManualChunks: (id: string) => string | undefined, assetsDir: string): {
55
59
  assetFileNames: (assetInfo: ClientAssetFileNameInfo) => string;
56
60
  manualChunks: (id: string) => string | undefined;
57
61
  experimentalMinChunkSize: number;
62
+ entryFileNames: string;
63
+ chunkFileNames: string;
58
64
  };
59
65
  declare function createClientCodeSplittingConfig(clientManualChunks: (id: string) => string | undefined): {
60
66
  minSize: number;
@@ -155,4 +161,4 @@ type VinextBuildConfigWithLegacy = VinextBuildConfig & {
155
161
  declare function getBuildBundlerOptions(build: UserConfig["build"] | undefined): VinextBuildBundlerOptions | undefined;
156
162
  declare function withBuildBundlerOptions(viteMajorVersion: number, bundlerOptions: VinextBuildBundlerOptions): Partial<VinextBuildConfigWithLegacy>;
157
163
  //#endregion
158
- export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
164
+ export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
@@ -89,8 +89,16 @@ function createClientManualChunks(shimsDir) {
89
89
  * compression efficiency — small files restart the compression dictionary,
90
90
  * adding ~5-15% wire overhead vs fewer larger chunks.
91
91
  */
92
+ function createClientFileNameConfig(assetsDir) {
93
+ const chunksDir = `${assetsDir}/chunks`;
94
+ return {
95
+ entryFileNames: `${chunksDir}/[name]-[hash].js`,
96
+ chunkFileNames: `${chunksDir}/[name]-[hash].js`
97
+ };
98
+ }
92
99
  function createClientOutputConfig(clientManualChunks, assetsDir) {
93
100
  return {
101
+ ...createClientFileNameConfig(assetsDir),
94
102
  assetFileNames: createClientAssetFileNames(assetsDir),
95
103
  manualChunks: clientManualChunks,
96
104
  experimentalMinChunkSize: 1e4
@@ -228,4 +236,4 @@ function withBuildBundlerOptions(viteMajorVersion, bundlerOptions) {
228
236
  return viteMajorVersion >= 8 ? { rolldownOptions: bundlerOptions } : { rollupOptions: bundlerOptions };
229
237
  }
230
238
  //#endregion
231
- export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
239
+ export { RSC_FRAMEWORK_CHUNK_TEST, clientTreeshakeConfig, createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, isRscFrameworkModule, withBuildBundlerOptions };
@@ -22,7 +22,8 @@ type PrerenderRouteResult = {
22
22
  * Omitted for non-dynamic routes where pattern === path.
23
23
  */
24
24
  path?: string; /** Which router produced this route. Used by cache seeding. */
25
- router: "app" | "pages";
25
+ router: "app" | "pages"; /** Set to true when this is a PPR fallback shell. */
26
+ fallback?: boolean;
26
27
  } | {
27
28
  route: string;
28
29
  status: "skipped";
@@ -31,6 +32,13 @@ type PrerenderRouteResult = {
31
32
  route: string;
32
33
  status: "error";
33
34
  error: string;
35
+ /**
36
+ * Set when the error must fail the build in ALL modes (default included),
37
+ * not just `output: 'export'`. Used for a thrown generateStaticParams /
38
+ * getStaticPaths, which Next.js treats as a fatal build error rather than a
39
+ * silently-skipped route. Refs cloudflare/vinext#1982
40
+ */
41
+ fatal?: true;
34
42
  };
35
43
  /** Called after each route is resolved (rendered, skipped, or error). */
36
44
  type PrerenderProgressCallback = (update: {
@@ -7,11 +7,11 @@ import { classifyAppRoute, classifyPagesRoute, getAppRouteRenderEntryPath } from
7
7
  import { BLOCKED_PAGES } from "../shims/constants.js";
8
8
  import { concatUint8Arrays, decodeRscEmbeddedChunk } from "../server/app-rsc-embedded-chunks.js";
9
9
  import { navigationRuntimeRscBootstrapExpression } from "../server/app-ssr-stream.js";
10
+ import { createAppPprFallbackShells, markAppPprDynamicFallbackShellHtml } from "../server/app-ppr-fallback-shell.js";
10
11
  import { encodePrerenderRouteParams, serializePrerenderRouteParamsHeader } from "../server/prerender-route-params.js";
11
12
  import { readPrerenderSecret } from "./server-manifest.js";
12
13
  import { getOutputPath, getRscOutputPath } from "../utils/prerender-output-paths.js";
13
14
  import { startProdServer } from "../server/prod-server.js";
14
- import { createAppPprFallbackShells } from "../server/app-ppr-fallback-shell.js";
15
15
  import fs from "node:fs";
16
16
  import path from "node:path";
17
17
  import os from "node:os";
@@ -33,9 +33,21 @@ import os from "node:os";
33
33
  * 'default' — skips SSR routes (served at request time); ISR routes rendered
34
34
  * 'export' — SSR routes are build errors; ISR treated as static (no revalidate)
35
35
  */
36
+ const EXPERIMENTAL_PPR_FALLBACK_SHELLS_ENV = "__VINEXT_EXPERIMENTAL_PPR_FALLBACK_SHELLS";
37
+ function isExperimentalPprFallbackShellGenerationEnabled(env = process.env) {
38
+ return env[EXPERIMENTAL_PPR_FALLBACK_SHELLS_ENV] === "1";
39
+ }
36
40
  function getErrorMessageWithStack(err) {
37
41
  return err.stack || err.message;
38
42
  }
43
+ var PrerenderUserFunctionError = class extends Error {};
44
+ function parsePrerenderEndpointError(text) {
45
+ try {
46
+ const parsed = JSON.parse(text);
47
+ if (parsed && typeof parsed === "object" && "error" in parsed) return typeof parsed.error === "string" && parsed.error.length > 0 ? parsed.error : "Unknown prerender endpoint error";
48
+ } catch {}
49
+ return text || "Unknown prerender endpoint error";
50
+ }
39
51
  /** Sentinel path used to trigger 404 rendering without a real route match. */
40
52
  const NOT_FOUND_SENTINEL_PATH = "/__vinext_nonexistent_for_404__";
41
53
  const DEFAULT_CONCURRENCY = Math.min(os.availableParallelism(), 8);
@@ -275,6 +287,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
275
287
  const res = await fetch(`${baseUrl}/__vinext/prerender/pages-static-paths?${search}`, { headers: secretHeaders });
276
288
  const text = await res.text();
277
289
  if (!res.ok) {
290
+ if (res.status === 500) throw new PrerenderUserFunctionError(parsePrerenderEndpointError(text));
278
291
  console.warn(`[vinext] Warning: /__vinext/prerender/pages-static-paths returned ${res.status} for ${r.pattern}. Dynamic paths will be skipped. This may indicate a stale or missing prerender secret.`);
279
292
  return {
280
293
  paths: [],
@@ -322,10 +335,21 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
322
335
  });
323
336
  continue;
324
337
  }
325
- const pathsResult = await route.module.getStaticPaths({
326
- locales: [],
327
- defaultLocale: ""
328
- });
338
+ let pathsResult;
339
+ try {
340
+ pathsResult = await route.module.getStaticPaths({
341
+ locales: [],
342
+ defaultLocale: ""
343
+ });
344
+ } catch (e) {
345
+ results.push({
346
+ route: route.pattern,
347
+ status: "error",
348
+ error: `Failed to call getStaticPaths(): ${e.message}`,
349
+ ...e instanceof PrerenderUserFunctionError ? { fatal: true } : {}
350
+ });
351
+ continue;
352
+ }
329
353
  const fallback = pathsResult?.fallback ?? false;
330
354
  if (mode === "export" && fallback !== false) {
331
355
  results.push({
@@ -521,6 +545,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
521
545
  const res = await fetch(`${baseUrl}/__vinext/prerender/static-params?${search}`, { headers: secretHeaders });
522
546
  const text = await res.text();
523
547
  if (!res.ok) {
548
+ if (res.status === 500) throw new PrerenderUserFunctionError(parsePrerenderEndpointError(text));
524
549
  console.warn(`[vinext] Warning: /__vinext/prerender/static-params returned ${res.status} for ${pattern}. Static params will be skipped. This may indicate a stale or missing prerender secret.`);
525
550
  return null;
526
551
  }
@@ -642,7 +667,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
642
667
  revalidate,
643
668
  isSpeculative: false
644
669
  });
645
- if (config.cacheComponents === true) for (const fallbackShell of createAppPprFallbackShells(route, params)) {
670
+ if (config.cacheComponents === true && isExperimentalPprFallbackShellGenerationEnabled()) for (const fallbackShell of createAppPprFallbackShells(route, params)) {
646
671
  if (queuedRouteUrls.has(fallbackShell.pathname)) continue;
647
672
  queuedRouteUrls.add(fallbackShell.pathname);
648
673
  urlsToRender.push({
@@ -650,7 +675,8 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
650
675
  routePattern: route.pattern,
651
676
  prerenderRouteParams: encodePrerenderRouteParams(route.pattern, fallbackShell.params, fallbackShell.fallbackParamNames),
652
677
  revalidate,
653
- isSpeculative: false
678
+ isSpeculative: false,
679
+ isFallback: true
654
680
  });
655
681
  }
656
682
  }
@@ -660,7 +686,8 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
660
686
  results.push({
661
687
  route: route.pattern,
662
688
  status: "error",
663
- error: `Failed to call generateStaticParams(): ${detail}`
689
+ error: `Failed to call generateStaticParams(): ${detail}`,
690
+ ...e instanceof PrerenderUserFunctionError ? { fatal: true } : {}
664
691
  });
665
692
  }
666
693
  else if (type === "unknown") urlsToRender.push({
@@ -684,7 +711,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
684
711
  * exactly once per URL after this function returns, keeping the callback
685
712
  * at a single, predictable call site.
686
713
  */
687
- async function renderUrl({ urlPath, routePattern, prerenderRouteParams, revalidate, isSpeculative }) {
714
+ async function renderUrl({ urlPath, routePattern, prerenderRouteParams, revalidate, isSpeculative, isFallback }) {
688
715
  try {
689
716
  const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParams);
690
717
  const htmlHeaders = new Headers();
@@ -736,7 +763,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
736
763
  status: "error",
737
764
  error: "RSC handler returned no prerender HTML"
738
765
  };
739
- const html = htmlRender.html;
766
+ const html = isFallback ? markAppPprDynamicFallbackShellHtml(htmlRender.html) : htmlRender.html;
740
767
  let rscData = extractRscPayloadFromPrerenderedHtml(html);
741
768
  if (rscData === null) {
742
769
  const rscHeaders = new Headers({
@@ -772,7 +799,8 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
772
799
  revalidate: renderedRevalidate,
773
800
  ...typeof renderedRevalidate === "number" ? { expire: renderedCacheControl.expire } : {},
774
801
  router: "app",
775
- ...urlPath !== routePattern ? { path: urlPath } : {}
802
+ ...urlPath !== routePattern ? { path: urlPath } : {},
803
+ ...isFallback ? { fallback: true } : {}
776
804
  };
777
805
  } catch (e) {
778
806
  if (isSpeculative) return {
@@ -878,7 +906,8 @@ function writePrerenderIndex(routes, outDir, options) {
878
906
  revalidate: r.revalidate,
879
907
  ...typeof r.revalidate === "number" ? { expire: r.expire } : {},
880
908
  router: r.router,
881
- ...r.path ? { path: r.path } : {}
909
+ ...r.path ? { path: r.path } : {},
910
+ ...r.fallback ? { fallback: true } : {}
882
911
  };
883
912
  if (r.status === "skipped") return {
884
913
  route: r.route,
@@ -1,5 +1,5 @@
1
1
  import { ResolvedNextConfig } from "../config/next-config.js";
2
- import { PrerenderResult } from "./prerender.js";
2
+ import { PrerenderResult, PrerenderRouteResult } from "./prerender.js";
3
3
 
4
4
  //#region src/build/run-prerender.d.ts
5
5
  type RunPrerenderOptions = {
@@ -48,6 +48,14 @@ type RunPrerenderOptions = {
48
48
  * If a required production bundle does not exist, an error is thrown directing
49
49
  * the user to run `vinext build` first.
50
50
  */
51
+ /**
52
+ * Throw if any route is a `fatal` error (a thrown generateStaticParams /
53
+ * getStaticPaths). These fail the build in ALL modes — default included —
54
+ * matching `next build`, unlike intentionally-skipped dynamic/SSR routes and
55
+ * non-fatal errors (e.g. transport failures), which only fail under
56
+ * `output: 'export'`. Exported for direct unit testing. Refs cloudflare/vinext#1982
57
+ */
58
+ declare function assertNoFatalPrerenderRoutes(routes: readonly PrerenderRouteResult[]): void;
51
59
  declare function runPrerender(options: RunPrerenderOptions): Promise<PrerenderResult | null>;
52
60
  //#endregion
53
- export { runPrerender };
61
+ export { assertNoFatalPrerenderRoutes, runPrerender };
@@ -82,6 +82,19 @@ function readBuiltBuildId(serverDir) {
82
82
  * If a required production bundle does not exist, an error is thrown directing
83
83
  * the user to run `vinext build` first.
84
84
  */
85
+ /**
86
+ * Throw if any route is a `fatal` error (a thrown generateStaticParams /
87
+ * getStaticPaths). These fail the build in ALL modes — default included —
88
+ * matching `next build`, unlike intentionally-skipped dynamic/SSR routes and
89
+ * non-fatal errors (e.g. transport failures), which only fail under
90
+ * `output: 'export'`. Exported for direct unit testing. Refs cloudflare/vinext#1982
91
+ */
92
+ function assertNoFatalPrerenderRoutes(routes) {
93
+ const fatalRoutes = routes.filter((r) => r.status === "error" && r.fatal === true);
94
+ if (fatalRoutes.length === 0) return;
95
+ const fatalList = fatalRoutes.map((r) => ` ${r.route}: ${r.error}`).join("\n");
96
+ throw new Error(`Prerender failed: ${fatalRoutes.length} route${fatalRoutes.length !== 1 ? "s" : ""} errored during static generation.\n${fatalList}`);
97
+ }
85
98
  async function runPrerender(options) {
86
99
  const { root } = options;
87
100
  const appDir = findDir(root, "app", "src/app");
@@ -197,6 +210,7 @@ async function runPrerender(options) {
197
210
  } finally {
198
211
  progress.finish(rendered, skipped, errors);
199
212
  }
213
+ assertNoFatalPrerenderRoutes(allRoutes);
200
214
  if (mode === "export" && errors > 0) {
201
215
  const errorRoutes = allRoutes.filter((r) => r.status === "error").map((r) => ` ${r.route}: ${r.error}`).join("\n");
202
216
  throw new Error(`Static export failed: ${errors} route${errors !== 1 ? "s" : ""} cannot be statically exported.\n${errorRoutes}\n\nRemove server-side data fetching (getServerSideProps, force-dynamic, revalidate) from these routes, or remove \`output: "export"\` from next.config.js.`);
@@ -207,4 +221,4 @@ async function runPrerender(options) {
207
221
  };
208
222
  }
209
223
  //#endregion
210
- export { runPrerender };
224
+ export { assertNoFatalPrerenderRoutes, runPrerender };
package/dist/check.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { detectPackageManager } from "./utils/project.js";
2
+ import { normalizePathSeparators } from "./utils/path.js";
2
3
  import fs from "node:fs";
3
4
  import path from "node:path";
4
5
  import { parseAst } from "vite";
@@ -342,7 +343,7 @@ function findSourceFiles(dir, extensions = [
342
343
  if (!fs.existsSync(dir)) return results;
343
344
  const entries = fs.readdirSync(dir, { withFileTypes: true });
344
345
  for (const entry of entries) {
345
- const fullPath = path.join(dir, entry.name);
346
+ const fullPath = normalizePathSeparators(path.join(dir, entry.name));
346
347
  if (entry.isDirectory()) {
347
348
  if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist" || entry.name === ".git") continue;
348
349
  results.push(...findSourceFiles(fullPath, extensions));
@@ -563,7 +564,7 @@ function scanImports(root) {
563
564
  if (mod.startsWith("next/") || mod === "next" || mod === "server-only" || mod === "client-only") {
564
565
  const normalized = mod === "next" ? "next" : mod;
565
566
  if (!importUsage.has(normalized)) importUsage.set(normalized, []);
566
- const relFile = path.relative(root, file);
567
+ const relFile = normalizePathSeparators(path.relative(root, file));
567
568
  const usedInFiles = importUsage.get(normalized) ?? [];
568
569
  if (!usedInFiles.includes(relFile)) usedInFiles.push(relFile);
569
570
  }
@@ -876,7 +877,7 @@ function checkConventions(root) {
876
877
  const cjsGlobalFiles = [];
877
878
  for (const file of allSourceFiles) {
878
879
  const content = fs.readFileSync(file, "utf-8");
879
- const rel = path.relative(root, file);
880
+ const rel = normalizePathSeparators(path.relative(root, file));
880
881
  if (viewTransitionRegex.test(content)) viewTransitionFiles.push(rel);
881
882
  if (hasFreeCjsGlobal(content)) cjsGlobalFiles.push(rel);
882
883
  }
@@ -0,0 +1,8 @@
1
+ //#region src/client/app-nav-failure-handler.d.ts
2
+ declare function stageAppNavigationFailureTarget(href: string): void;
3
+ declare function getAppNavigationFailureTarget(href: string): URL | null;
4
+ declare function clearAppNavigationFailureTarget(target?: string | URL): void;
5
+ declare function handleAppNavigationFailure(error: unknown): boolean;
6
+ declare function installAppNavigationFailureListeners(): () => void;
7
+ //#endregion
8
+ export { clearAppNavigationFailureTarget, getAppNavigationFailureTarget, handleAppNavigationFailure, installAppNavigationFailureListeners, stageAppNavigationFailureTarget };
@@ -0,0 +1,44 @@
1
+ import { installWindowNext } from "./window-next.js";
2
+ //#region src/client/app-nav-failure-handler.ts
3
+ function getPendingUrl() {
4
+ if (typeof window === "undefined") return null;
5
+ return window.next?.__pendingUrl ?? null;
6
+ }
7
+ function stageAppNavigationFailureTarget(href) {
8
+ if (!process.env.__NEXT_APP_NAV_FAIL_HANDLING || typeof window === "undefined") return;
9
+ installWindowNext({ __pendingUrl: new URL(href, window.location.href) });
10
+ }
11
+ function getAppNavigationFailureTarget(href) {
12
+ const pendingUrl = getPendingUrl();
13
+ if (pendingUrl === null || typeof window === "undefined") return null;
14
+ return pendingUrl.href === new URL(href, window.location.href).href ? pendingUrl : null;
15
+ }
16
+ function clearAppNavigationFailureTarget(target) {
17
+ if (typeof window === "undefined" || window.next?.__pendingUrl === void 0) return;
18
+ if (target instanceof URL) {
19
+ if (window.next.__pendingUrl !== target) return;
20
+ } else if (target !== void 0 && window.next.__pendingUrl.href !== new URL(target, window.location.href).href) return;
21
+ delete window.next.__pendingUrl;
22
+ }
23
+ function handleAppNavigationFailure(error) {
24
+ if (!process.env.__NEXT_APP_NAV_FAIL_HANDLING || typeof window === "undefined") return false;
25
+ const pendingUrl = getPendingUrl();
26
+ if (pendingUrl === null || pendingUrl.href === window.location.href) return false;
27
+ console.error("Error occurred during navigation, falling back to hard navigation", error);
28
+ window.location.assign(pendingUrl.href);
29
+ return true;
30
+ }
31
+ function installAppNavigationFailureListeners() {
32
+ if (!process.env.__NEXT_APP_NAV_FAIL_HANDLING || typeof window === "undefined") return () => {};
33
+ const listener = (event) => {
34
+ handleAppNavigationFailure("reason" in event ? event.reason : event.error);
35
+ };
36
+ window.addEventListener("error", listener);
37
+ window.addEventListener("unhandledrejection", listener);
38
+ return () => {
39
+ window.removeEventListener("error", listener);
40
+ window.removeEventListener("unhandledrejection", listener);
41
+ };
42
+ }
43
+ //#endregion
44
+ export { clearAppNavigationFailureTarget, getAppNavigationFailureTarget, handleAppNavigationFailure, installAppNavigationFailureListeners, stageAppNavigationFailureTarget };
@@ -15,12 +15,13 @@ type NavigationRuntimeRscBootstrap = {
15
15
  };
16
16
  type NavigationRuntimeKind = "navigate" | "traverse" | "refresh";
17
17
  type NavigationRuntimeHistoryUpdateMode = "push" | "replace";
18
+ type NavigationRuntimeVisibleCommitMode = "transition" | "synchronous";
18
19
  type NavigationRuntimeTraversalIntent = {
19
20
  direction: "back" | "forward" | "unknown";
20
21
  historyState: unknown;
21
22
  targetHistoryIndex: number | null;
22
23
  };
23
- type NavigationRuntimeNavigate = (href: string, redirectDepth?: number, navigationKind?: NavigationRuntimeKind, historyUpdateMode?: NavigationRuntimeHistoryUpdateMode, previousNextUrlOverride?: string | null, programmaticTransition?: boolean, traversalIntent?: NavigationRuntimeTraversalIntent, scrollIntent?: AppRouterScrollIntent | null) => Promise<void>;
24
+ type NavigationRuntimeNavigate = (href: string, redirectDepth?: number, navigationKind?: NavigationRuntimeKind, historyUpdateMode?: NavigationRuntimeHistoryUpdateMode, previousNextUrlOverride?: string | null, programmaticTransition?: boolean, traversalIntent?: NavigationRuntimeTraversalIntent, scrollIntent?: AppRouterScrollIntent | null, visibleCommitMode?: NavigationRuntimeVisibleCommitMode) => Promise<void>;
24
25
  type NavigationRuntimeFunctions = {
25
26
  clearNavigationCaches?: () => void;
26
27
  commitHashNavigation?: (href: string, historyUpdateMode: NavigationRuntimeHistoryUpdateMode, scroll: boolean) => void;
@@ -66,4 +67,4 @@ declare function hasAppNavigationRuntime(): boolean;
66
67
  */
67
68
  declare function hasAppNavigationRuntimeBootstrap(): boolean;
68
69
  //#endregion
69
- export { NAVIGATION_RUNTIME_KEY, NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION, NavigationRuntime, NavigationRuntimeBootstrap, NavigationRuntimeFunctions, NavigationRuntimeNavigate, NavigationRuntimeRscBootstrap, NavigationRuntimeRscChunk, NavigationRuntimeSnapshot, ensureNavigationRuntimeRscBootstrap, getNavigationRuntime, hasAppNavigationRuntime, hasAppNavigationRuntimeBootstrap, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions, subscribeNavigationRuntimeRscChunk };
70
+ export { NAVIGATION_RUNTIME_KEY, NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION, NavigationRuntime, NavigationRuntimeBootstrap, NavigationRuntimeFunctions, NavigationRuntimeNavigate, NavigationRuntimeRscBootstrap, NavigationRuntimeRscChunk, NavigationRuntimeSnapshot, NavigationRuntimeVisibleCommitMode, ensureNavigationRuntimeRscBootstrap, getNavigationRuntime, hasAppNavigationRuntime, hasAppNavigationRuntimeBootstrap, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions, subscribeNavigationRuntimeRscChunk };
@@ -3,6 +3,23 @@ import { NEXT_DATA } from "../shims/internal/utils.js";
3
3
  //#region src/client/vinext-next-data.d.ts
4
4
  type VinextLinkPrefetchRoute = {
5
5
  canPrefetchLoadingShell: boolean;
6
+ documentOnly?: boolean;
7
+ isDynamic: boolean;
8
+ patternParts: string[];
9
+ };
10
+ /**
11
+ * Pages Router route pattern exposed to the client so the App Router's
12
+ * navigation runtime can decide whether a soft-navigated URL should be
13
+ * handled by Pages (hard nav) or App (RSC). Mirrors the public shape of
14
+ * `VinextLinkPrefetchRoute` so a single trie matcher handles both.
15
+ *
16
+ * `canPrefetchLoadingShell` is always `false` for Pages routes — Pages
17
+ * does not have a separate loading boundary and its prefetch surface is
18
+ * `_next/data/<buildId>/<page>.json`.
19
+ */
20
+ type VinextPagesLinkPrefetchRoute = {
21
+ canPrefetchLoadingShell: false;
22
+ documentOnly?: boolean;
6
23
  isDynamic: boolean;
7
24
  patternParts: string[];
8
25
  };
@@ -24,4 +41,4 @@ declare function extractVinextNextDataJson(html: string): string | null;
24
41
  declare function parseVinextNextDataJson(json: string): BrowserVinextNextData;
25
42
  declare function applyVinextLocaleGlobals(target: VinextLocaleGlobalTarget, nextData: VinextNextData): void;
26
43
  //#endregion
27
- export { VinextLinkPrefetchRoute, VinextNextData, applyVinextLocaleGlobals, extractVinextNextDataJson, parseVinextNextDataJson };
44
+ export { VinextLinkPrefetchRoute, VinextNextData, VinextPagesLinkPrefetchRoute, applyVinextLocaleGlobals, extractVinextNextDataJson, parseVinextNextDataJson };
@@ -40,10 +40,9 @@
40
40
  * `window.next.router`. Mirrors the `publicAppRouterInstance` shape from
41
41
  * `packages/next/src/client/components/app-router-instance.ts`.
42
42
  *
43
- * `hmrRefresh` and `experimental_gesturePush` are intentionally omitted —
44
- * vinext does not implement them. Library callers that branch on their
45
- * presence (`typeof router.hmrRefresh === "function"`) will skip the
46
- * branch, matching what they would do on a production Next.js build.
43
+ * `hmrRefresh` is intentionally omitted — vinext does not implement it.
44
+ * `experimental_gesturePush` is attached only when
45
+ * `experimental.gestureTransition` is enabled, matching Next.js.
47
46
  */
48
47
  type AppRouterPublicInstance = {
49
48
  push: (href: string, options?: {
@@ -57,6 +56,9 @@ type AppRouterPublicInstance = {
57
56
  refresh: () => void;
58
57
  prefetch: (href: string, options?: {
59
58
  onInvalidate?: () => void;
59
+ }) => void;
60
+ experimental_gesturePush?: (href: string, options?: {
61
+ scroll?: boolean;
60
62
  }) => void; /** Default placeholder, matches Next.js. */
61
63
  bfcacheId?: string;
62
64
  };
@@ -161,5 +163,6 @@ type WindowNext = {
161
163
  * resets state.
162
164
  */
163
165
  declare function installWindowNext(fields: Partial<WindowNext>): void;
166
+ declare function setWindowNextInternalSourcePage(sourcePage: string | null): void;
164
167
  //#endregion
165
- export { PagesRouterPublicInstance, installWindowNext };
168
+ export { PagesRouterPublicInstance, installWindowNext, setWindowNextInternalSourcePage };
@@ -42,5 +42,16 @@ function installWindowNext(fields) {
42
42
  ...fields
43
43
  };
44
44
  }
45
+ function setWindowNextInternalSourcePage(sourcePage) {
46
+ if (typeof window === "undefined") return;
47
+ installWindowNext({});
48
+ if (sourcePage === null) {
49
+ delete window.next?.__internal_src_page;
50
+ return;
51
+ }
52
+ const next = window.next;
53
+ if (!next) return;
54
+ next.__internal_src_page = sourcePage;
55
+ }
45
56
  //#endregion
46
- export { installWindowNext };
57
+ export { installWindowNext, setWindowNextInternalSourcePage };
@@ -73,7 +73,12 @@ var CloudflareCdnCacheAdapter = class {
73
73
  async set(_key, _data, _ctx) {}
74
74
  buildResponseHeaders(input) {
75
75
  if (!input.cacheControl) return { "Cache-Control": NO_STORE };
76
- if (/\b(?:no-store|no-cache|private)\b/.test(input.cacheControl)) return { "Cache-Control": input.cacheControl };
76
+ if (/\b(?:no-store|no-cache|private)\b/.test(input.cacheControl)) return {
77
+ "Cache-Control": input.cacheControl,
78
+ "CDN-Cache-Control": null,
79
+ "Cloudflare-CDN-Cache-Control": null,
80
+ "Cache-Tag": null
81
+ };
77
82
  const headers = {
78
83
  "Cache-Control": BROWSER_REVALIDATE,
79
84
  "CDN-Cache-Control": toEdgeCacheControl(input.cacheControl)
@@ -32,10 +32,10 @@ declare function escapeHeaderSource(source: string): string;
32
32
  * Callers extract the relevant parts from the incoming Request.
33
33
  */
34
34
  type RequestContext = {
35
- headers: Headers;
36
- cookies: Record<string, string>;
37
- query: URLSearchParams;
38
- host: string;
35
+ readonly headers: Headers;
36
+ readonly cookies: Record<string, string>;
37
+ readonly query: URLSearchParams;
38
+ readonly host: string;
39
39
  };
40
40
  /**
41
41
  * basePath gating state passed alongside the pathname to every matcher.
@@ -65,6 +65,13 @@ type BasePathMatchState = {
65
65
  declare function parseCookies(cookieHeader: string | null): Record<string, string>;
66
66
  /**
67
67
  * Build a RequestContext from a Web Request object.
68
+ *
69
+ * `cookies` and `query` are lazy memoized getters: they are consumed only by
70
+ * `has`/`missing` condition evaluation (`checkHasConditions` /
71
+ * `matchesRuleConditions`), and most apps configure no such conditions. The
72
+ * cookie split and `searchParams` access are therefore deferred until first
73
+ * read and computed at most once. Mirrors `headersContextFromRequest` in
74
+ * `shims/headers.ts`.
68
75
  */
69
76
  declare function requestContextFromRequest(request: Request): RequestContext;
70
77
  declare function normalizeHost(hostHeader: string | null, fallbackHostname: string): string;