vinext 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/README.md +51 -30
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/layout-classification.js +1 -1
  5. package/dist/build/nitro-route-rules.js +1 -1
  6. package/dist/build/pages-client-assets-module.d.ts +11 -0
  7. package/dist/build/pages-client-assets-module.js +27 -0
  8. package/dist/build/prerender.d.ts +2 -1
  9. package/dist/build/prerender.js +13 -6
  10. package/dist/build/report.d.ts +13 -2
  11. package/dist/build/report.js +99 -2
  12. package/dist/build/run-prerender.d.ts +7 -0
  13. package/dist/build/run-prerender.js +10 -1
  14. package/dist/build/standalone.js +2 -0
  15. package/dist/cache/cache-adapters-virtual.js +3 -3
  16. package/dist/check.d.ts +18 -0
  17. package/dist/check.js +77 -19
  18. package/dist/cli-args.d.ts +1 -2
  19. package/dist/cli-args.js +1 -1
  20. package/dist/cli-dev-config.d.ts +12 -0
  21. package/dist/cli-dev-config.js +23 -0
  22. package/dist/cli.js +113 -97
  23. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  24. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  25. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  26. package/dist/{server → client}/dev-error-overlay.js +2 -2
  27. package/dist/client/navigation-runtime.d.ts +2 -0
  28. package/dist/client/navigation-runtime.js +3 -1
  29. package/dist/client/window-next.d.ts +2 -1
  30. package/dist/cloudflare/index.d.ts +2 -2
  31. package/dist/cloudflare/index.js +2 -2
  32. package/dist/config/config-matchers.js +14 -10
  33. package/dist/config/next-config.d.ts +6 -3
  34. package/dist/config/next-config.js +47 -1
  35. package/dist/config/prerender.d.ts +34 -0
  36. package/dist/config/prerender.js +55 -0
  37. package/dist/config/server-external-packages.d.ts +4 -0
  38. package/dist/config/server-external-packages.js +91 -0
  39. package/dist/entries/app-rsc-entry.d.ts +2 -1
  40. package/dist/entries/app-rsc-entry.js +89 -15
  41. package/dist/entries/app-rsc-manifest.js +10 -0
  42. package/dist/entries/pages-client-entry.d.ts +3 -0
  43. package/dist/entries/pages-client-entry.js +16 -1
  44. package/dist/entries/pages-server-entry.js +6 -2
  45. package/dist/image/image-adapters-virtual.d.ts +59 -0
  46. package/dist/image/image-adapters-virtual.js +59 -0
  47. package/dist/index.d.ts +33 -0
  48. package/dist/index.js +211 -118
  49. package/dist/init-cloudflare.d.ts +43 -0
  50. package/dist/init-cloudflare.js +839 -0
  51. package/dist/init-platform.d.ts +40 -0
  52. package/dist/init-platform.js +195 -0
  53. package/dist/init.d.ts +16 -38
  54. package/dist/init.js +208 -97
  55. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  56. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  57. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  58. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  59. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  60. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  61. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  62. package/dist/packages/cloudflare/src/deploy.js +276 -0
  63. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  64. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
  65. package/dist/plugins/ast-scope.d.ts +16 -0
  66. package/dist/plugins/ast-scope.js +62 -0
  67. package/dist/plugins/ast-utils.d.ts +27 -1
  68. package/dist/plugins/ast-utils.js +32 -1
  69. package/dist/plugins/css-module-imports.d.ts +14 -0
  70. package/dist/plugins/css-module-imports.js +59 -0
  71. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  72. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  73. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  74. package/dist/plugins/middleware-server-only.d.ts +8 -6
  75. package/dist/plugins/middleware-server-only.js +8 -7
  76. package/dist/plugins/optimize-imports.js +1 -1
  77. package/dist/plugins/typeof-window.d.ts +1 -1
  78. package/dist/plugins/typeof-window.js +28 -56
  79. package/dist/routing/app-route-graph.d.ts +29 -4
  80. package/dist/routing/app-route-graph.js +182 -40
  81. package/dist/routing/app-router.d.ts +5 -0
  82. package/dist/routing/app-router.js +5 -0
  83. package/dist/routing/file-matcher.d.ts +8 -0
  84. package/dist/routing/file-matcher.js +10 -1
  85. package/dist/routing/pages-router.js +2 -2
  86. package/dist/server/api-handler.js +9 -14
  87. package/dist/server/app-browser-action-result.d.ts +4 -1
  88. package/dist/server/app-browser-action-result.js +8 -1
  89. package/dist/server/app-browser-entry.js +194 -190
  90. package/dist/server/app-browser-history-controller.d.ts +2 -1
  91. package/dist/server/app-browser-history-controller.js +6 -2
  92. package/dist/server/app-browser-interception-context.d.ts +1 -0
  93. package/dist/server/app-browser-interception-context.js +4 -2
  94. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  95. package/dist/server/app-browser-navigation-controller.js +60 -31
  96. package/dist/server/app-browser-server-action-client.d.ts +32 -0
  97. package/dist/server/app-browser-server-action-client.js +127 -0
  98. package/dist/server/app-browser-state.d.ts +11 -1
  99. package/dist/server/app-browser-state.js +25 -8
  100. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  101. package/dist/server/app-browser-visible-commit.js +43 -25
  102. package/dist/server/app-elements-wire.d.ts +9 -2
  103. package/dist/server/app-elements-wire.js +8 -1
  104. package/dist/server/app-elements.d.ts +2 -2
  105. package/dist/server/app-elements.js +4 -3
  106. package/dist/server/app-fallback-renderer.d.ts +5 -2
  107. package/dist/server/app-fallback-renderer.js +15 -7
  108. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  109. package/dist/server/app-hydration-cache-publication.js +43 -0
  110. package/dist/server/app-middleware.d.ts +4 -3
  111. package/dist/server/app-middleware.js +8 -3
  112. package/dist/server/app-optimistic-routing.js +11 -4
  113. package/dist/server/app-page-boundary-render.d.ts +3 -0
  114. package/dist/server/app-page-boundary-render.js +14 -3
  115. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  116. package/dist/server/app-page-cache-finalizer.js +10 -3
  117. package/dist/server/app-page-cache-render.d.ts +1 -0
  118. package/dist/server/app-page-cache-render.js +8 -4
  119. package/dist/server/app-page-cache.d.ts +1 -0
  120. package/dist/server/app-page-cache.js +5 -2
  121. package/dist/server/app-page-dispatch.d.ts +33 -4
  122. package/dist/server/app-page-dispatch.js +63 -90
  123. package/dist/server/app-page-element-builder.d.ts +9 -2
  124. package/dist/server/app-page-element-builder.js +114 -23
  125. package/dist/server/app-page-head.d.ts +16 -1
  126. package/dist/server/app-page-head.js +44 -22
  127. package/dist/server/app-page-params.d.ts +2 -1
  128. package/dist/server/app-page-params.js +8 -1
  129. package/dist/server/app-page-ppr-runtime.d.ts +7 -0
  130. package/dist/server/app-page-ppr-runtime.js +70 -0
  131. package/dist/server/app-page-probe.d.ts +1 -0
  132. package/dist/server/app-page-probe.js +6 -1
  133. package/dist/server/app-page-render-identity.d.ts +1 -0
  134. package/dist/server/app-page-render-identity.js +1 -1
  135. package/dist/server/app-page-render.d.ts +4 -1
  136. package/dist/server/app-page-render.js +26 -3
  137. package/dist/server/app-page-request.d.ts +22 -1
  138. package/dist/server/app-page-request.js +92 -15
  139. package/dist/server/app-page-route-wiring.d.ts +14 -2
  140. package/dist/server/app-page-route-wiring.js +61 -25
  141. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  142. package/dist/server/app-page-search-params-observation.js +11 -7
  143. package/dist/server/app-page-segment-state.d.ts +2 -1
  144. package/dist/server/app-page-segment-state.js +3 -1
  145. package/dist/server/app-page-stream.d.ts +5 -0
  146. package/dist/server/app-page-stream.js +3 -1
  147. package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
  148. package/dist/server/app-route-handler-dispatch.js +1 -0
  149. package/dist/server/app-route-handler-execution.js +7 -2
  150. package/dist/server/app-route-handler-response.js +1 -0
  151. package/dist/server/app-route-handler-runtime.js +1 -1
  152. package/dist/server/app-route-module-loader.d.ts +2 -0
  153. package/dist/server/app-route-module-loader.js +1 -0
  154. package/dist/server/app-router-entry.js +16 -8
  155. package/dist/server/app-rsc-errors.js +7 -1
  156. package/dist/server/app-rsc-handler.d.ts +3 -1
  157. package/dist/server/app-rsc-handler.js +67 -39
  158. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  159. package/dist/server/app-rsc-request-normalization.js +6 -3
  160. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  161. package/dist/server/app-rsc-route-matching.js +36 -3
  162. package/dist/server/app-segment-config.d.ts +12 -0
  163. package/dist/server/app-segment-config.js +91 -5
  164. package/dist/server/app-server-action-execution.d.ts +5 -0
  165. package/dist/server/app-server-action-execution.js +94 -33
  166. package/dist/server/app-ssr-entry.d.ts +3 -0
  167. package/dist/server/app-ssr-entry.js +19 -8
  168. package/dist/server/app-ssr-stream.d.ts +7 -3
  169. package/dist/server/app-ssr-stream.js +10 -6
  170. package/dist/server/app-static-generation.d.ts +1 -0
  171. package/dist/server/app-static-generation.js +1 -0
  172. package/dist/server/app-visited-response-cache.d.ts +6 -0
  173. package/dist/server/app-visited-response-cache.js +3 -1
  174. package/dist/server/client-trace-metadata.js +26 -0
  175. package/dist/server/default-global-not-found-module.d.ts +14 -0
  176. package/dist/server/default-global-not-found-module.js +14 -0
  177. package/dist/server/dev-route-files.js +4 -0
  178. package/dist/server/dev-server.js +19 -18
  179. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  180. package/dist/server/dev-stack-sourcemap.js +1 -1
  181. package/dist/server/fetch-handler.d.ts +2 -0
  182. package/dist/server/fetch-handler.js +18 -0
  183. package/dist/server/headers.d.ts +5 -15
  184. package/dist/server/headers.js +4 -15
  185. package/dist/server/image-optimization.d.ts +51 -1
  186. package/dist/server/image-optimization.js +52 -2
  187. package/dist/server/implicit-tags.js +1 -1
  188. package/dist/server/isr-cache.d.ts +1 -1
  189. package/dist/server/isr-cache.js +2 -2
  190. package/dist/server/metadata-routes.d.ts +3 -1
  191. package/dist/server/metadata-routes.js +12 -2
  192. package/dist/server/middleware-runtime.js +6 -1
  193. package/dist/server/navigation-planner.d.ts +1 -0
  194. package/dist/server/navigation-planner.js +14 -3
  195. package/dist/server/pages-api-route.js +2 -2
  196. package/dist/server/pages-asset-tags.d.ts +4 -6
  197. package/dist/server/pages-asset-tags.js +12 -12
  198. package/dist/server/pages-client-assets.d.ts +12 -0
  199. package/dist/server/pages-client-assets.js +10 -0
  200. package/dist/server/pages-node-compat.d.ts +8 -1
  201. package/dist/server/pages-node-compat.js +32 -4
  202. package/dist/server/pages-page-data.d.ts +24 -1
  203. package/dist/server/pages-page-data.js +45 -24
  204. package/dist/server/pages-page-handler.d.ts +2 -1
  205. package/dist/server/pages-page-handler.js +19 -12
  206. package/dist/server/pages-page-response.d.ts +7 -0
  207. package/dist/server/pages-page-response.js +4 -1
  208. package/dist/server/pages-request-pipeline.d.ts +2 -0
  209. package/dist/server/pages-request-pipeline.js +25 -1
  210. package/dist/server/pages-router-entry.d.ts +30 -0
  211. package/dist/server/pages-router-entry.js +108 -0
  212. package/dist/server/prerender-manifest.d.ts +3 -1
  213. package/dist/server/prerender-route-params.js +1 -1
  214. package/dist/server/prod-server.d.ts +1 -1
  215. package/dist/server/prod-server.js +48 -26
  216. package/dist/server/request-pipeline.js +1 -0
  217. package/dist/server/seed-cache.js +4 -4
  218. package/dist/server/worker-utils.d.ts +2 -1
  219. package/dist/server/worker-utils.js +7 -1
  220. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  221. package/dist/shims/app-router-scroll-state.js +1 -0
  222. package/dist/shims/app-router-scroll.js +2 -1
  223. package/dist/shims/cache.js +19 -15
  224. package/dist/shims/cdn-cache.js +1 -1
  225. package/dist/shims/dynamic-preload-chunks.js +2 -1
  226. package/dist/shims/error-boundary.d.ts +19 -1
  227. package/dist/shims/error-boundary.js +11 -1
  228. package/dist/shims/form.d.ts +3 -1
  229. package/dist/shims/form.js +37 -43
  230. package/dist/shims/headers.d.ts +9 -1
  231. package/dist/shims/headers.js +31 -6
  232. package/dist/shims/image.js +75 -14
  233. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  234. package/dist/shims/internal/app-route-detection.js +4 -17
  235. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  236. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  237. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
  238. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  239. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
  240. package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
  241. package/dist/shims/internal/pages-data-target.d.ts +10 -9
  242. package/dist/shims/internal/pages-data-target.js +91 -12
  243. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  244. package/dist/shims/internal/pages-router-components.js +13 -0
  245. package/dist/shims/layout-segment-context.d.ts +4 -1
  246. package/dist/shims/layout-segment-context.js +18 -4
  247. package/dist/shims/link.js +70 -37
  248. package/dist/shims/metadata.d.ts +3 -2
  249. package/dist/shims/metadata.js +8 -4
  250. package/dist/shims/navigation.d.ts +5 -1
  251. package/dist/shims/navigation.js +45 -10
  252. package/dist/shims/navigation.react-server.js +1 -1
  253. package/dist/shims/root-params.d.ts +15 -1
  254. package/dist/shims/root-params.js +21 -1
  255. package/dist/shims/router.d.ts +5 -7
  256. package/dist/shims/router.js +374 -94
  257. package/dist/shims/server.js +3 -2
  258. package/dist/shims/slot.js +3 -6
  259. package/dist/typegen.js +6 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  261. package/dist/utils/client-runtime-metadata.js +31 -22
  262. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  263. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  264. package/dist/utils/domain-locale.d.ts +6 -3
  265. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  266. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  267. package/dist/utils/path.d.ts +2 -1
  268. package/dist/utils/path.js +1 -1
  269. package/dist/utils/project.d.ts +52 -2
  270. package/dist/utils/project.js +230 -5
  271. package/dist/utils/protocol-headers.d.ts +17 -0
  272. package/dist/utils/protocol-headers.js +17 -0
  273. package/dist/utils/react-version.d.ts +4 -0
  274. package/dist/utils/react-version.js +44 -0
  275. package/package.json +53 -4
  276. package/dist/deploy.d.ts +0 -190
  277. package/dist/deploy.js +0 -1033
  278. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  279. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -1,15 +1,21 @@
1
+ import { NEXTJS_CACHE_HEADER, VINEXT_CACHE_HEADER } from "./headers.js";
1
2
  import { setCacheStateHeaders } from "./cache-headers.js";
2
3
  import { applyCdnResponseHeaders } from "./cache-control.js";
3
4
  import { buildAppPageCacheValue } from "./isr-cache.js";
4
5
  import { readStreamAsText } from "../utils/text-stream.js";
5
6
  import { createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
6
7
  //#region src/server/app-page-cache-finalizer.ts
7
- function applyPendingDynamicCdnHeaders(headers, tags) {
8
+ function applyPendingDynamicCdnHeaders(headers, tags, options = {}) {
8
9
  applyCdnResponseHeaders(headers, {
9
10
  cacheControl: headers.get("Cache-Control") ?? "",
10
11
  pendingDynamicCheck: true,
11
12
  tags
12
13
  });
14
+ if (options.omitCacheState === true) {
15
+ headers.delete(VINEXT_CACHE_HEADER);
16
+ headers.delete(NEXTJS_CACHE_HEADER);
17
+ return;
18
+ }
13
19
  setCacheStateHeaders(headers, "MISS");
14
20
  }
15
21
  function resolveAppPageCacheWritePolicy(options) {
@@ -30,7 +36,7 @@ function finalizeAppPageHtmlCacheResponse(response, options) {
30
36
  const htmlKey = options.isrHtmlKey(options.cleanPathname);
31
37
  const rscKey = options.isrRscKey(options.cleanPathname, null, void 0, options.interceptionContext);
32
38
  const clientHeaders = new Headers(response.headers);
33
- if (options.preserveClientResponseHeaders !== true) applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags());
39
+ if (options.preserveClientResponseHeaders !== true) applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags(), { omitCacheState: options.omitPendingDynamicCacheState === true });
34
40
  const cachePromise = (async () => {
35
41
  try {
36
42
  const cachedHtml = await readStreamAsText(streamForCache);
@@ -57,7 +63,8 @@ function finalizeAppPageHtmlCacheResponse(response, options) {
57
63
  cacheTags: pageTags,
58
64
  state: observationState
59
65
  });
60
- const writes = [options.isrSet(htmlKey, buildAppPageCacheValue(cachedHtml, void 0, 200, htmlRenderObservation), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)];
66
+ const linkHeader = response.headers.get("link");
67
+ const writes = [options.isrSet(htmlKey, buildAppPageCacheValue(cachedHtml, void 0, 200, htmlRenderObservation, linkHeader ? { link: linkHeader } : void 0), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)];
61
68
  if (options.capturedRscDataPromise) writes.push(options.capturedRscDataPromise.then((rscData) => options.isrSet(rscKey, buildAppPageCacheValue("", rscData, 200, rscRenderObservation), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)));
62
69
  await Promise.all(writes);
63
70
  options.isrDebug?.("HTML cache written", htmlKey);
@@ -38,6 +38,7 @@ type RenderAppPageCacheArtifactsResult = {
38
38
  cacheControl?: CacheControlMetadata;
39
39
  html: string;
40
40
  htmlRenderObservation: ReturnType<typeof createAppPageRenderObservation>;
41
+ linkHeader?: string;
41
42
  rscData?: ArrayBuffer;
42
43
  rscRenderObservation?: ReturnType<typeof createAppPageRenderObservation>;
43
44
  tags: string[];
@@ -2,9 +2,9 @@ import { consumeDynamicUsage, consumeInvalidDynamicUsageError } from "../shims/h
2
2
  import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
3
3
  import { getCollectedFetchTags } from "../shims/fetch-cache.js";
4
4
  import { readStreamAsText } from "../utils/text-stream.js";
5
- import { teeAppPageRscStreamForCapture } from "./app-page-execution.js";
5
+ import { buildAppPageFontLinkHeader, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
6
6
  import { consumeAppPageRenderObservationState, createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
7
- import { isAppSsrRenderResult } from "./app-page-stream.js";
7
+ import { buildAppPageLinkHeader, isAppSsrRenderResult } from "./app-page-stream.js";
8
8
  import { buildAppPageTags } from "./implicit-tags.js";
9
9
  //#region src/server/app-page-cache-render.ts
10
10
  /**
@@ -16,10 +16,11 @@ import { buildAppPageTags } from "./implicit-tags.js";
16
16
  async function renderAppPageCacheArtifacts(options) {
17
17
  const rscCapture = teeAppPageRscStreamForCapture(options.renderToReadableStream(options.element, { onError: options.onError }), options.captureRscData);
18
18
  const capturedRscDataRef = { value: null };
19
+ const fontPreloads = options.getFontPreloads();
19
20
  const htmlResult = await (await options.loadSsrHandler()).handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
20
21
  links: options.getFontLinks(),
21
22
  styles: options.getFontStyles(),
22
- preloads: options.getFontPreloads()
23
+ preloads: fontPreloads
23
24
  }, {
24
25
  basePath: options.basePath,
25
26
  clientTraceMetadata: options.clientTraceMetadata,
@@ -31,7 +32,9 @@ async function renderAppPageCacheArtifacts(options) {
31
32
  capturedRscDataRef
32
33
  } : {}
33
34
  });
34
- const html = await readStreamAsText(isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult);
35
+ const htmlStream = isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult;
36
+ const linkHeader = buildAppPageLinkHeader(isAppSsrRenderResult(htmlResult) ? htmlResult.linkHeader : void 0, buildAppPageFontLinkHeader(fontPreloads), options.reactMaxHeadersLength);
37
+ const html = await readStreamAsText(htmlStream);
35
38
  let rscData;
36
39
  if (options.captureRscData) {
37
40
  const capturedPromise = capturedRscDataRef.value;
@@ -60,6 +63,7 @@ async function renderAppPageCacheArtifacts(options) {
60
63
  params: options.navigationParams,
61
64
  state: observationState
62
65
  }),
66
+ ...linkHeader ? { linkHeader } : {},
63
67
  tags,
64
68
  cacheControl: typeof cacheLife?.revalidate === "number" ? {
65
69
  revalidate: cacheLife.revalidate,
@@ -25,6 +25,7 @@ type AppPageCacheRenderResult = {
25
25
  cacheControl?: CacheControlMetadata;
26
26
  html: string;
27
27
  htmlRenderObservation?: RenderObservation;
28
+ linkHeader?: string;
28
29
  rscData: ArrayBuffer;
29
30
  rscRenderObservation?: RenderObservation;
30
31
  tags: string[];
@@ -19,7 +19,7 @@ function recordAppPageCacheOutcome(recordCacheOutcome, input) {
19
19
  function buildAppPageCacheTags(pathname, extraTags) {
20
20
  const tags = [
21
21
  pathname,
22
- `_N_T_${pathname}`,
22
+ `_N_T_${pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname}`,
23
23
  "_N_T_/layout"
24
24
  ];
25
25
  const segments = pathname.split("/");
@@ -43,6 +43,8 @@ function buildAppPageCachedHeaders(options) {
43
43
  applyCdnResponseHeaders(headers, { cacheControl: options.cacheControl });
44
44
  setCacheStateHeaders(headers, options.cacheState);
45
45
  applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
46
+ if (options.linkHeader) if (Array.isArray(options.linkHeader)) for (const value of options.linkHeader) headers.append("Link", value);
47
+ else headers.set("Link", options.linkHeader);
46
48
  if (options.mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
47
49
  mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
48
50
  return headers;
@@ -84,6 +86,7 @@ function buildAppPageCachedResponse(cachedValue, options) {
84
86
  cacheState: options.cacheState,
85
87
  contentType: "text/html; charset=utf-8",
86
88
  isEdgeRuntime: options.isEdgeRuntime,
89
+ linkHeader: cachedValue.headers?.link,
87
90
  middlewareHeaders: options.middlewareHeaders
88
91
  });
89
92
  return new Response(cachedValue.html, {
@@ -177,7 +180,7 @@ async function readAppPageCacheResponse(options) {
177
180
  const revalidateSeconds = revalidatedPage.cacheControl?.revalidate ?? options.revalidateSeconds;
178
181
  const expireSeconds = revalidatedPage.cacheControl?.expire ?? options.expireSeconds;
179
182
  const writes = [options.isrSet(options.isRscRequest ? isrKey : options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode, options.interceptionContext), buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation), revalidateSeconds, revalidatedPage.tags, expireSeconds)];
180
- if (!options.isRscRequest) writes.push(options.isrSet(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation), revalidateSeconds, revalidatedPage.tags, expireSeconds));
183
+ if (!options.isRscRequest) writes.push(options.isrSet(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? { link: revalidatedPage.linkHeader } : void 0), revalidateSeconds, revalidatedPage.tags, expireSeconds));
181
184
  await Promise.all(writes);
182
185
  options.isrDebug?.("regen complete", options.cleanPathname);
183
186
  });
@@ -10,8 +10,10 @@ import { AppPageSsrHandler } from "./app-page-stream.js";
10
10
  import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
11
11
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
12
12
  import { ISRCacheEntry } from "./isr-cache.js";
13
+ import { PprFallbackShellState } from "../shims/ppr-fallback-shell.js";
13
14
  import { FetchCacheMode } from "../shims/fetch-cache.js";
14
15
  import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
16
+ import { WarmPprFallbackShellCachesOptions } from "./app-ppr-fallback-shell-render.js";
15
17
  import { ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
16
18
  import { ReactNode } from "react";
17
19
  import { ReactFormState } from "react-dom/client";
@@ -32,7 +34,10 @@ type AppPageBackgroundRegenerationErrorContext = {
32
34
  type AppPageBackgroundRegenerator = (key: string, renderFn: () => Promise<void>, errorContext?: AppPageBackgroundRegenerationErrorContext) => void;
33
35
  type AppPageDispatchIntercept<TPage = unknown> = {
34
36
  interceptLayouts?: readonly unknown[] | null;
37
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
38
+ interceptBranchSegments?: readonly string[] | null;
35
39
  matchedParams: AppPageParams;
40
+ sourceMatchedParams?: AppPageParams;
36
41
  page: TPage;
37
42
  slotId?: string | null;
38
43
  slotKey: string;
@@ -42,6 +47,8 @@ type AppPageDispatchIntercept<TPage = unknown> = {
42
47
  type AppPageDispatchInterceptOptions<TPage = unknown> = {
43
48
  interceptionContext: string | null;
44
49
  interceptLayouts?: readonly unknown[] | null;
50
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
51
+ interceptBranchSegments?: readonly string[] | null;
45
52
  interceptPage: TPage;
46
53
  interceptParams: AppPageParams;
47
54
  interceptSlotId?: string | null;
@@ -80,6 +87,14 @@ type AppPageDispatchRoute = {
80
87
  unauthorized?: AppPageModule | null;
81
88
  unauthorizeds?: readonly (AppPageModule | null | undefined)[];
82
89
  };
90
+ type AppPagePprRuntime<TRoute extends AppPageDispatchRoute> = {
91
+ beginFinalRender(state: AppPagePprState): void;
92
+ getState(): AppPagePprState | null;
93
+ run<T>(shell: NonNullable<DispatchAppPageOptions<TRoute>["pprFallbackShell"]>, fn: () => T): T;
94
+ tryServe(options: DispatchAppPageOptions<TRoute>, currentRevalidateSeconds: number | null, isDraftMode: boolean, isForceStatic: boolean, isForceDynamic: boolean): Promise<Response | null>;
95
+ warm(options: WarmPprFallbackShellCachesOptions): Promise<void>;
96
+ };
97
+ type AppPagePprState = PprFallbackShellState;
83
98
  type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
84
99
  /** Configured basePath (e.g. "/blog"). Used to prefix redirect Locations. */basePath?: string;
85
100
  /**
@@ -94,7 +109,10 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
94
109
  * `next.config`. Undefined falls back to the React default downstream.
95
110
  */
96
111
  reactMaxHeadersLength?: number;
97
- buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<AppPageElement>;
112
+ buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker, options?: {
113
+ observeMetadataSearchParamsAccess?: boolean;
114
+ observePageSearchParamsAccess?: boolean;
115
+ }) => Promise<AppPageElement>;
98
116
  clientReuseManifest?: ClientReuseManifestParseResult;
99
117
  cleanPathname: string;
100
118
  displayPathname?: string;
@@ -147,6 +165,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
147
165
  fallbackParamNames: readonly string[];
148
166
  routePattern: string;
149
167
  };
168
+ pprRuntime?: AppPagePprRuntime<TRoute>;
150
169
  /**
151
170
  * Set of concrete URL paths that were pre-rendered at build time for this
152
171
  * route. When the exact cache entry for a known pregenerated path is absent
@@ -159,9 +178,9 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
159
178
  staticParamsValidationParams?: AppPageParams;
160
179
  rootParams?: RootParams;
161
180
  probeLayoutAt: (layoutIndex: number, layoutParamAccess?: AppLayoutParamAccessTracker) => unknown;
162
- probePage: () => unknown;
181
+ probePage: (searchParams?: URLSearchParams) => unknown;
163
182
  expireSeconds?: number;
164
- renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;
183
+ renderErrorBoundaryPage: (error: unknown, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
165
184
  renderHttpAccessFallbackPage: (statusCode: number, opts: {
166
185
  boundaryComponent?: unknown;
167
186
  boundaryModule?: AppPageModule | null;
@@ -197,6 +216,16 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
197
216
  }) => void;
198
217
  renderMode?: AppRscRenderMode;
199
218
  };
219
+ declare function shouldReadAppPageCache(options: {
220
+ isProgressiveActionRender: boolean;
221
+ isDraftMode: boolean;
222
+ isForceDynamic: boolean;
223
+ isProduction: boolean;
224
+ isRscRequest: boolean;
225
+ revalidateSeconds: number | null;
226
+ scriptNonce?: string;
227
+ }): boolean;
228
+ declare function hasSearchParams(searchParams: URLSearchParams | null | undefined): boolean;
200
229
  declare function dispatchAppPage<TRoute extends AppPageDispatchRoute>(options: DispatchAppPageOptions<TRoute>): Promise<Response>;
201
230
  //#endregion
202
- export { dispatchAppPage };
231
+ export { AppPageBoundaryOnError, AppPageDispatchRoute, AppPagePprRuntime, AppPagePprState, AppPageRenderableElement, DispatchAppPageOptions, dispatchAppPage, hasSearchParams, shouldReadAppPageCache };
@@ -3,8 +3,7 @@ import { getRequestExecutionContext } from "../shims/request-context.js";
3
3
  import { AppElementsWire } from "./app-elements-wire.js";
4
4
  import { shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
5
5
  import "./app-elements.js";
6
- import { beginPprFallbackShellFinalRender, createPprFallbackShellState, getPprFallbackShellState, runWithPprFallbackShellState } from "../shims/ppr-fallback-shell.js";
7
- import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, isDraftModeRequest, markDynamicUsage, peekRenderRequestApiUsage, setHeadersContext } from "../shims/headers.js";
6
+ import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersContext, isDraftModeRequest, markDynamicUsage, peekDynamicUsage, peekRenderRequestApiUsage, setHeadersContext } from "../shims/headers.js";
8
7
  import { _consumeRequestScopedCacheLife, _peekRequestScopedCacheLife } from "../shims/cache-request-state.js";
9
8
  import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
10
9
  import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
@@ -108,6 +107,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
108
107
  const { createStaticGenerationHeadersContext } = await import("./app-static-generation.js");
109
108
  return runWithRequestContext(createRequestContext({
110
109
  headersContext: createStaticGenerationHeadersContext({
110
+ draftModeEnabled: false,
111
111
  draftModeSecret: options.draftModeSecret,
112
112
  dynamicConfig: options.dynamicConfig,
113
113
  routeKind: "page",
@@ -132,6 +132,8 @@ function toInterceptOptions(interceptionContext, intercept) {
132
132
  return {
133
133
  interceptionContext,
134
134
  interceptLayouts: intercept.interceptLayouts,
135
+ interceptLayoutSegments: intercept.interceptLayoutSegments,
136
+ interceptBranchSegments: intercept.interceptBranchSegments,
135
137
  interceptPage: intercept.page,
136
138
  interceptParams: intercept.matchedParams,
137
139
  interceptSlotId: intercept.slotId ?? null,
@@ -140,75 +142,10 @@ function toInterceptOptions(interceptionContext, intercept) {
140
142
  interceptSourcePageSegments: intercept.sourcePageSegments ?? null
141
143
  };
142
144
  }
143
- /**
144
- * Request-phase fallback-shell gate. Callers must run the exact cache read and
145
- * static-param validation before this classification step.
146
- */
147
- function classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
148
- if (options.renderedConcreteUrlPaths?.has(options.cleanPathname) === true) return { kind: "skip-known-pregenerated-route" };
149
- const fallbackShells = options.pprFallbackCacheShells;
150
- if (!fallbackShells || fallbackShells.length === 0) return { kind: "skip-no-fallback-shells" };
151
- if (options.isRscRequest) return { kind: "skip-rsc-request" };
152
- if (options.request.method !== "GET") return { kind: "skip-non-get" };
153
- if (!isForceStatic && hasSearchParams(options.searchParams)) return { kind: "skip-search-params" };
154
- if (!shouldReadAppPageCache({
155
- isDraftMode,
156
- isForceDynamic,
157
- isProgressiveActionRender: options.isProgressiveActionRender === true,
158
- isProduction: options.isProduction,
159
- isRscRequest: false,
160
- revalidateSeconds: currentRevalidateSeconds,
161
- scriptNonce: options.scriptNonce
162
- })) return { kind: "skip-cache-disabled" };
163
- return {
164
- kind: "probe-fallback-shells",
165
- fallbackShells
166
- };
167
- }
168
- async function probePprFallbackShellCache(options, route, fallbackShells, currentRevalidateSeconds) {
169
- const { readAppPageFallbackShellCacheResponse } = await import("./app-page-cache.js");
170
- const { rewriteAppPprFallbackShellHtmlNavigation } = await import("./app-ppr-fallback-shell.js");
171
- for (const fallbackShell of fallbackShells) {
172
- const fallbackShellResponse = await readAppPageFallbackShellCacheResponse({
173
- clearRequestContext: options.clearRequestContext,
174
- expireSeconds: options.expireSeconds,
175
- fallbackPathname: fallbackShell.pathname,
176
- isEdgeRuntime: options.isEdgeRuntime,
177
- isrDebug: options.isrDebug,
178
- isrGet: options.isrGet,
179
- isrHtmlKey: options.isrHtmlKey,
180
- middlewareHeaders: options.middlewareContext.headers,
181
- middlewareStatus: options.middlewareContext.status,
182
- revalidateSeconds: currentRevalidateSeconds ?? 0,
183
- rewriteHtml(html) {
184
- return rewriteAppPprFallbackShellHtmlNavigation({
185
- html,
186
- params: options.params,
187
- pathname: options.cleanPathname,
188
- searchParams: options.searchParams
189
- });
190
- }
191
- });
192
- if (fallbackShellResponse) return fallbackShellResponse;
193
- }
194
- return null;
195
- }
196
- async function tryServePprFallbackShell(options, route, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
197
- const decision = classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic);
198
- switch (decision.kind) {
199
- case "skip-known-pregenerated-route":
200
- case "skip-no-fallback-shells":
201
- case "skip-rsc-request":
202
- case "skip-non-get":
203
- case "skip-search-params":
204
- case "skip-cache-disabled": return null;
205
- case "probe-fallback-shells": return await probePprFallbackShellCache(options, route, decision.fallbackShells, currentRevalidateSeconds);
206
- }
207
- }
208
145
  async function dispatchAppPage(options) {
209
146
  const dispatch = () => runWithFetchDedupe(() => dispatchAppPageInner(options));
210
- if (!options.pprFallbackShell) return await dispatch();
211
- return await runWithPprFallbackShellState(createPprFallbackShellState(options.pprFallbackShell), dispatch);
147
+ if (!options.pprFallbackShell || !options.pprRuntime) return await dispatch();
148
+ return await options.pprRuntime.run(options.pprFallbackShell, dispatch);
212
149
  }
213
150
  async function dispatchAppPageInner(options) {
214
151
  const route = options.route;
@@ -218,7 +155,11 @@ async function dispatchAppPageInner(options) {
218
155
  const isDynamicError = dynamicConfig === "error";
219
156
  const isForceDynamic = dynamicConfig === "force-dynamic";
220
157
  const isDraftMode = isDraftModeRequest(options.request, options.draftModeSecret);
158
+ const requestHeadersContext = getHeadersContext();
159
+ const hasRequestSearchParams = !isForceStatic && hasSearchParams(options.searchParams);
160
+ const pageSearchParams = isForceStatic ? new URLSearchParams() : options.searchParams;
221
161
  const layoutParamAccess = createAppLayoutParamAccessTracker();
162
+ const hasActiveLoadingBoundary = shouldSuppressLoadingBoundaries(options.renderMode ?? "navigation") ? false : Boolean(route.loading?.default);
222
163
  setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], route.routeSegments));
223
164
  setCurrentFetchCacheMode(options.fetchCache ?? null);
224
165
  setCurrentForceDynamicFetchDefault(isForceDynamic);
@@ -238,9 +179,10 @@ async function dispatchAppPageInner(options) {
238
179
  options.clearRequestContext();
239
180
  return methodResponse;
240
181
  }
241
- if ((isForceStatic || isDynamicError) && !isDraftMode) {
182
+ if (isForceStatic || isDynamicError) {
242
183
  const { createStaticGenerationHeadersContext } = await import("./app-static-generation.js");
243
184
  setHeadersContext(createStaticGenerationHeadersContext({
185
+ draftModeEnabled: isDraftMode,
244
186
  draftModeSecret: options.draftModeSecret,
245
187
  dynamicConfig,
246
188
  routeKind: "page",
@@ -266,7 +208,7 @@ async function dispatchAppPageInner(options) {
266
208
  const cachedPageResponse = await readAppPageCacheResponse({
267
209
  cleanPathname: options.cleanPathname,
268
210
  clearRequestContext: options.clearRequestContext,
269
- hasRequestSearchParams: !isForceStatic && hasSearchParams(options.searchParams),
211
+ hasRequestSearchParams,
270
212
  isEdgeRuntime: options.isEdgeRuntime,
271
213
  isRscRequest: options.isRscRequest,
272
214
  isrDebug: options.isrDebug,
@@ -300,19 +242,23 @@ async function dispatchAppPageInner(options) {
300
242
  });
301
243
  revalidationTarget.navigationParams = resolveAppPageNavigationParams(revalidationTarget.route, revalidationTarget.navigationParams, options.cleanPathname, revalidationTarget.interceptOpts);
302
244
  await options.ensureRouteLoaded?.(revalidationTarget.route);
245
+ const revalidationDynamicConfig = options.resolveRouteDynamicConfig?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? dynamicConfig : void 0);
303
246
  return runAppPageRevalidationContext({
304
247
  cleanPathname: options.cleanPathname,
305
248
  displayPathname: options.displayPathname,
306
249
  currentFetchCacheMode: options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
307
250
  draftModeSecret: options.draftModeSecret,
308
- dynamicConfig: options.resolveRouteDynamicConfig?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? dynamicConfig : void 0),
251
+ dynamicConfig: revalidationDynamicConfig,
309
252
  params: revalidationTarget.navigationParams,
310
253
  routePattern: revalidationTarget.route.pattern,
311
254
  routeSegments: revalidationTarget.route.routeSegments,
312
255
  setNavigationContext: options.setNavigationContext
313
256
  }, async () => {
314
257
  const { renderAppPageCacheArtifacts } = await import("./app-page-cache-render.js");
315
- const revalidatedElement = await options.buildPageElement(revalidationTarget.route, revalidationTarget.params, revalidationTarget.interceptOpts, new URLSearchParams());
258
+ const revalidatedElement = await options.buildPageElement(revalidationTarget.route, revalidationTarget.params, revalidationTarget.interceptOpts, new URLSearchParams(), void 0, {
259
+ observeMetadataSearchParamsAccess: revalidationDynamicConfig !== "force-static",
260
+ observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static"
261
+ });
316
262
  const revalidatedOnError = options.createRscOnErrorHandler(options.cleanPathname, revalidationTarget.route.pattern);
317
263
  const rendered = await renderAppPageCacheArtifacts({
318
264
  basePath: options.basePath,
@@ -338,6 +284,7 @@ async function dispatchAppPageInner(options) {
338
284
  return {
339
285
  html: rendered.html,
340
286
  htmlRenderObservation: rendered.htmlRenderObservation,
287
+ linkHeader: rendered.linkHeader,
341
288
  rscData: rendered.rscData,
342
289
  rscRenderObservation: rendered.rscRenderObservation,
343
290
  tags: rendered.tags,
@@ -365,14 +312,29 @@ async function dispatchAppPageInner(options) {
365
312
  });
366
313
  if (dynamicParamsResponse) return dynamicParamsResponse;
367
314
  }
368
- const fallbackShellResponse = await tryServePprFallbackShell(options, route, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic);
315
+ const fallbackShellResponse = options.pprRuntime ? await options.pprRuntime.tryServe(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) : null;
369
316
  if (fallbackShellResponse) return fallbackShellResponse;
317
+ let interceptDynamicConfig;
318
+ let interceptDynamicConfigResolved = false;
370
319
  const interceptResult = await resolveAppPageIntercept({
371
320
  async buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, interceptLayoutParamAccess) {
372
- await options.ensureRouteLoaded?.(interceptRoute);
321
+ const sourceDynamicConfig = interceptDynamicConfigResolved ? interceptDynamicConfig : options.resolveRouteDynamicConfig?.(interceptRoute);
322
+ if (sourceDynamicConfig === "force-static" || sourceDynamicConfig === "error") {
323
+ const { createStaticGenerationHeadersContext } = await import("./app-static-generation.js");
324
+ setHeadersContext(createStaticGenerationHeadersContext({
325
+ draftModeEnabled: isDraftMode,
326
+ draftModeSecret: options.draftModeSecret,
327
+ dynamicConfig: sourceDynamicConfig,
328
+ routeKind: "page",
329
+ routePattern: interceptRoute.pattern
330
+ }));
331
+ } else setHeadersContext(requestHeadersContext);
373
332
  setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(interceptRoute) ?? null);
374
- setCurrentForceDynamicFetchDefault(options.resolveRouteDynamicConfig?.(interceptRoute) === "force-dynamic");
375
- return options.buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, interceptLayoutParamAccess);
333
+ setCurrentForceDynamicFetchDefault(sourceDynamicConfig === "force-dynamic");
334
+ return options.buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, interceptLayoutParamAccess, {
335
+ observeMetadataSearchParamsAccess: sourceDynamicConfig !== "force-static",
336
+ observePageSearchParamsAccess: sourceDynamicConfig !== "force-static"
337
+ });
376
338
  },
377
339
  cleanPathname: options.cleanPathname,
378
340
  currentRoute: route,
@@ -404,6 +366,12 @@ async function dispatchAppPageInner(options) {
404
366
  headers: interceptHeaders
405
367
  });
406
368
  },
369
+ async resolveSearchParams(sourceRoute, searchParams) {
370
+ await options.ensureRouteLoaded?.(sourceRoute);
371
+ interceptDynamicConfig = options.resolveRouteDynamicConfig?.(sourceRoute);
372
+ interceptDynamicConfigResolved = true;
373
+ return interceptDynamicConfig === "force-static" ? new URLSearchParams() : searchParams;
374
+ },
407
375
  searchParams: options.searchParams,
408
376
  setNavigationContext: options.setNavigationContext,
409
377
  toInterceptOpts(intercept) {
@@ -414,12 +382,15 @@ async function dispatchAppPageInner(options) {
414
382
  const buildCurrentPageElement = () => buildAppPageElement({
415
383
  buildPageElement() {
416
384
  if (options.actionFailed) throw options.actionError;
417
- return options.buildPageElement(route, options.params, interceptResult.interceptOpts, options.searchParams, layoutParamAccess);
385
+ return options.buildPageElement(route, options.params, interceptResult.interceptOpts, pageSearchParams, layoutParamAccess, {
386
+ observeMetadataSearchParamsAccess: !isForceStatic,
387
+ observePageSearchParamsAccess: !isForceStatic
388
+ });
418
389
  },
419
390
  async probePageSpecialError() {
420
391
  if (!shouldSuppressLoadingBoundaries(options.renderMode ?? "navigation") && route.loading?.default) return null;
421
392
  return resolveAppPageSpecialError(await probeAppPageThrownError({
422
- probePage: options.probePage,
393
+ probePage: () => options.probePage(pageSearchParams),
423
394
  runWithSuppressedHookWarning(probe) {
424
395
  return options.runWithSuppressedHookWarning(probe);
425
396
  }
@@ -433,12 +404,11 @@ async function dispatchAppPageInner(options) {
433
404
  },
434
405
  resolveSpecialError: resolveAppPageSpecialError
435
406
  });
436
- const fallbackShellState = getPprFallbackShellState();
407
+ const fallbackShellState = options.pprRuntime?.getState() ?? null;
437
408
  if (fallbackShellState && process.env.VINEXT_PRERENDER === "1" && !options.isRscRequest) {
438
409
  const warmupBuildResult = await buildCurrentPageElement();
439
410
  if (warmupBuildResult.response) return warmupBuildResult.response;
440
- const { warmPprFallbackShellCaches } = await import("./app-ppr-fallback-shell-render.js");
441
- await warmPprFallbackShellCaches({
411
+ await options.pprRuntime.warm({
442
412
  element: warmupBuildResult.element,
443
413
  onError: options.createRscOnErrorHandler(options.cleanPathname, route.pattern),
444
414
  renderToReadableStream: options.renderToReadableStream,
@@ -451,11 +421,11 @@ async function dispatchAppPageInner(options) {
451
421
  const navigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, interceptResult.interceptOpts);
452
422
  options.setNavigationContext({
453
423
  pathname: options.displayPathname ?? options.cleanPathname,
454
- searchParams: options.searchParams,
424
+ searchParams: pageSearchParams,
455
425
  params: navigationParams
456
426
  });
457
427
  const layoutClassifications = getEffectiveLayoutClassifications(route, options.debugClassification);
458
- const activeFallbackShellState = getPprFallbackShellState();
428
+ const activeFallbackShellState = options.pprRuntime?.getState() ?? null;
459
429
  const pprFallbackShellSignal = activeFallbackShellState?.abortController.signal;
460
430
  const pprFallbackShellReactSignal = activeFallbackShellState?.reactAbortController.signal;
461
431
  return renderAppPageLifecycle({
@@ -465,6 +435,7 @@ async function dispatchAppPageInner(options) {
465
435
  cleanPathname: options.cleanPathname,
466
436
  clearRequestContext: options.clearRequestContext,
467
437
  consumeDynamicUsage,
438
+ peekDynamicUsage,
468
439
  consumeInvalidDynamicUsageError,
469
440
  consumeRenderObservationState: consumeAppPageRenderObservationState,
470
441
  createRscOnErrorHandler(pathname, routePath) {
@@ -487,7 +458,8 @@ async function dispatchAppPageInner(options) {
487
458
  return _peekRequestScopedCacheLife();
488
459
  },
489
460
  handlerStart: options.handlerStart,
490
- hasLoadingBoundary: shouldSuppressLoadingBoundaries(options.renderMode ?? "navigation") ? false : Boolean(route.loading?.default),
461
+ hasLoadingBoundary: hasActiveLoadingBoundary,
462
+ omitPendingDynamicCacheState: !options.isRscRequest && hasRequestSearchParams,
491
463
  formState: options.formState ?? null,
492
464
  isProgressiveActionRender: options.isProgressiveActionRender === true,
493
465
  isDynamicError,
@@ -512,7 +484,7 @@ async function dispatchAppPageInner(options) {
512
484
  pprFallbackShellSignal,
513
485
  pprFallbackShellReactSignal,
514
486
  abortPprFallbackShell: activeFallbackShellState ? () => {
515
- beginPprFallbackShellFinalRender(activeFallbackShellState);
487
+ options.pprRuntime.beginFinalRender(activeFallbackShellState);
516
488
  } : void 0,
517
489
  layoutParamAccess,
518
490
  rootParams: options.rootParams,
@@ -526,8 +498,9 @@ async function dispatchAppPageInner(options) {
526
498
  return options.probeLayoutAt(layoutIndex, layoutParamAccess);
527
499
  },
528
500
  probePage() {
529
- return options.probePage();
501
+ return options.probePage(pageSearchParams);
530
502
  },
503
+ probePageBeforeRender: options.isRscRequest,
531
504
  classification: {
532
505
  getLayoutId(index) {
533
506
  const treePosition = route.layoutTreePositions?.[index] ?? 0;
@@ -556,8 +529,8 @@ async function dispatchAppPageInner(options) {
556
529
  revalidateSeconds: currentRevalidateSeconds,
557
530
  mountedSlotsHeader: options.mountedSlotsHeader,
558
531
  renderMode: options.renderMode ?? "navigation",
559
- renderErrorBoundaryResponse(renderError) {
560
- return options.renderErrorBoundaryPage(renderError);
532
+ renderErrorBoundaryResponse(renderError, errorOrigin) {
533
+ return options.renderErrorBoundaryPage(renderError, errorOrigin);
561
534
  },
562
535
  renderLayoutSpecialError(specialError, layoutIndex) {
563
536
  return renderLayoutSpecialError(options, specialError, layoutIndex);
@@ -674,4 +647,4 @@ async function renderPageSpecialError(options, specialError) {
674
647
  });
675
648
  }
676
649
  //#endregion
677
- export { dispatchAppPage };
650
+ export { dispatchAppPage, hasSearchParams, shouldReadAppPageCache };
@@ -1,6 +1,7 @@
1
1
  import { MetadataFileRoute } from "./metadata-routes.js";
2
2
  import { AppElements } from "./app-elements-wire.js";
3
3
  import { AppPageParams } from "./app-page-boundary.js";
4
+ import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
4
5
  import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
5
6
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
6
7
  import { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute } from "./app-page-route-wiring.js";
@@ -19,6 +20,8 @@ type AppPageBuildRoute<TModule extends AppPageModule = AppPageModule, TErrorModu
19
20
  type AppPageInterceptOptions<TModule extends AppPageModule = AppPageModule> = {
20
21
  interceptionContext?: string | null;
21
22
  interceptLayouts?: readonly (TModule | null | undefined)[] | null;
23
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
24
+ interceptBranchSegments?: readonly string[] | null;
22
25
  interceptPage?: TModule | null;
23
26
  interceptParams?: AppPageParams | null;
24
27
  interceptSlotId?: string | null;
@@ -32,9 +35,12 @@ type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {
32
35
  isRscRequest: boolean; /** The incoming HTTP request (available but unused by this module). */
33
36
  request: Request; /** Normalized x-vinext-mounted-slots header value. */
34
37
  mountedSlotsHeader: string | null; /** Semantic RSC payload mode for this page render. */
35
- renderMode?: AppRscRenderMode;
38
+ renderMode?: AppRscRenderMode; /** Observe page `searchParams` access for cache-safety classification. */
39
+ observePageSearchParamsAccess?: boolean; /** Observe page metadata `searchParams` access for cache-safety classification. */
40
+ observeMetadataSearchParamsAccess?: boolean;
36
41
  };
37
42
  type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {
43
+ applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
38
44
  route: AppPageBuildRoute<TModule, TErrorModule>;
39
45
  params: AppPageParams;
40
46
  routePath: string;
@@ -89,6 +95,7 @@ type AppPageNavigationParamInterceptOptions = {
89
95
  * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
90
96
  */
91
97
  declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
98
+ declare function resolveInterceptedSlotSegments(sourcePageSegments: readonly string[] | null | undefined, slotKey: string): readonly string[] | null;
92
99
  declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
93
100
  //#endregion
94
- export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements, resolveAppPageNavigationParams };
101
+ export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements, resolveAppPageNavigationParams, resolveInterceptedSlotSegments };