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
@@ -2,6 +2,7 @@ import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders }
2
2
  import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
3
3
  import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
4
4
  import "./app-elements.js";
5
+ import { peekDynamicUsage } from "../shims/headers.js";
5
6
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
6
7
  import { buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy } from "./app-page-response.js";
7
8
  import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageSpecialError, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
@@ -248,8 +249,11 @@ function wrapRscResponseForDevErrorReporting(response, consumeInvalidDynamicUsag
248
249
  });
249
250
  }
250
251
  async function renderAppPageLifecycle(options) {
252
+ const configuredProbePageBeforeRender = options.probePageBeforeRender ?? options.isRscRequest;
253
+ const probePageBeforeRender = options.isRscRequest || configuredProbePageBeforeRender && !(options.peekDynamicUsage?.() ?? false);
251
254
  const preRenderResult = await probeAppPageBeforeRender({
252
255
  hasLoadingBoundary: options.hasLoadingBoundary,
256
+ probePageBeforeRender,
253
257
  skipProbes: options.pprFallbackShellSignal !== void 0,
254
258
  layoutCount: options.layoutCount,
255
259
  probeLayoutAt(layoutIndex) {
@@ -311,6 +315,7 @@ async function renderAppPageLifecycle(options) {
311
315
  const outgoingElement = AppElementsWire.encodeOutgoingPayload({
312
316
  element: options.element,
313
317
  layoutFlags,
318
+ ...options.dynamicStaleTimeSeconds !== void 0 && options.isPrerender !== true && !options.isForceStatic ? { dynamicStaleTimeSeconds: options.dynamicStaleTimeSeconds } : {},
314
319
  ...artifactCompatibility ? { artifactCompatibility } : {},
315
320
  renderObservation: payloadRenderObservation,
316
321
  skipDisposition: options.isRscRequest ? skipDisposition : void 0
@@ -424,18 +429,33 @@ async function renderAppPageLifecycle(options) {
424
429
  getStyles: options.getFontStyles
425
430
  });
426
431
  const fontLinkHeader = buildAppPageFontLinkHeader(fontData.preloads);
432
+ let dynamicUsedDuringHtmlRender = false;
427
433
  let renderEnd;
428
434
  const htmlRender = await renderAppPageHtmlStreamWithRecovery({
429
435
  onShellRendered() {
430
436
  if (!options.isProduction) renderEnd = performance.now();
431
437
  },
432
438
  renderErrorBoundaryResponse(error) {
433
- return options.renderErrorBoundaryResponse(rscErrorTracker.getCapturedError() ?? error);
439
+ const capturedRscError = rscErrorTracker.getCapturedError();
440
+ return options.renderErrorBoundaryResponse(capturedRscError ?? error, capturedRscError === null ? "ssr" : "rsc");
434
441
  },
435
442
  async renderHtmlStream() {
436
443
  const ssrHandler = await options.loadSsrHandler();
437
444
  return renderAppPageHtmlStream({
438
445
  capturedRscDataRef,
446
+ getInitialNavigationCacheMetadata: () => {
447
+ let kind;
448
+ if (options.isForceStatic) kind = "static";
449
+ else if (options.isForceDynamic || dynamicUsedDuringHtmlRender || peekDynamicUsage()) kind = "dynamic";
450
+ else {
451
+ const observation = options.peekRenderObservationState?.();
452
+ kind = observation && (observation.dynamicFetches.length > 0 || observation.requestApis.length > 0) ? "dynamic" : "static";
453
+ }
454
+ return {
455
+ kind,
456
+ ...kind === "dynamic" && options.dynamicStaleTimeSeconds !== void 0 && options.isPrerender !== true && !shouldCaptureRscForCacheMetadata ? { dynamicStaleTimeSeconds: options.dynamicStaleTimeSeconds } : {}
457
+ };
458
+ },
439
459
  fontData,
440
460
  hasCustomGlobalError: options.hasCustomGlobalError,
441
461
  navigationContext: options.getNavigationContext(),
@@ -462,7 +482,7 @@ async function renderAppPageLifecycle(options) {
462
482
  if (!htmlStream) throw new Error("[vinext] Expected an HTML stream when no fallback response was returned");
463
483
  const linkHeader = buildAppPageLinkHeader(htmlRender.linkHeader, fontLinkHeader, options.reactMaxHeadersLength);
464
484
  if (options.isPrerender === true) await htmlRender.metadataReady;
465
- if (options.hasLoadingBoundary) {
485
+ if (options.hasLoadingBoundary || !probePageBeforeRender) {
466
486
  const captured = rscErrorTracker.getCapturedSpecialError();
467
487
  if (captured) {
468
488
  const specialError = resolveAppPageSpecialError(captured);
@@ -480,11 +500,13 @@ async function renderAppPageLifecycle(options) {
480
500
  revalidateSeconds
481
501
  }));
482
502
  }
503
+ let dynamicUsedDuringRender = options.consumeDynamicUsage();
504
+ dynamicUsedDuringHtmlRender = dynamicUsedDuringRender;
483
505
  const draftCookie = options.getDraftModeCookieHeader();
484
- const dynamicUsedDuringRender = options.consumeDynamicUsage();
485
506
  let dynamicUsedBeforeContextCleanup = dynamicUsedDuringRender;
486
507
  const safeHtmlStream = deferUntilStreamConsumed(htmlStream, () => {
487
508
  dynamicUsedBeforeContextCleanup = dynamicUsedBeforeContextCleanup || options.consumeDynamicUsage();
509
+ dynamicUsedDuringHtmlRender = dynamicUsedBeforeContextCleanup;
488
510
  options.clearRequestContext();
489
511
  });
490
512
  const htmlResponsePolicy = resolveAppPageHtmlResponsePolicy({
@@ -575,6 +597,7 @@ async function renderAppPageLifecycle(options) {
575
597
  isrRscKey: options.isrRscKey,
576
598
  isrSet: options.isrSet,
577
599
  interceptionContext: options.interceptionContext,
600
+ omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
578
601
  preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,
579
602
  expireSeconds,
580
603
  revalidateSeconds,
@@ -12,8 +12,20 @@ type GenerateStaticParamsModule = {
12
12
  };
13
13
  type GenerateStaticParamsSource = {
14
14
  generateStaticParams: GenerateStaticParams;
15
+ paramAliases?: Readonly<Record<string, string>>;
16
+ paramPatternParts?: readonly string[];
17
+ routePatternParts?: readonly string[];
15
18
  parentParamNames: readonly string[];
16
19
  };
20
+ type ParallelGenerateStaticParamsBranch = {
21
+ configLayouts?: readonly (GenerateStaticParamsModule | null | undefined)[] | null;
22
+ configLayoutTreePositions?: readonly number[] | null;
23
+ layout?: GenerateStaticParamsModule | null;
24
+ page?: GenerateStaticParamsModule | null;
25
+ paramNames?: readonly string[] | null;
26
+ patternParts?: readonly string[] | null;
27
+ routeSegments?: readonly string[] | null;
28
+ };
17
29
  type ValidateAppPageDynamicParamsOptions = {
18
30
  clearRequestContext: () => void;
19
31
  enforceStaticParamsOnly: boolean;
@@ -25,6 +37,8 @@ type ResolveAppPageGenerateStaticParamsSourcesOptions = {
25
37
  layouts?: readonly (GenerateStaticParamsModule | null | undefined)[];
26
38
  layoutTreePositions?: readonly number[];
27
39
  page?: GenerateStaticParamsModule | null;
40
+ parallelBranches?: readonly (ParallelGenerateStaticParamsBranch | null | undefined)[];
41
+ routePatternParts?: readonly string[];
28
42
  routeSegments: readonly string[];
29
43
  };
30
44
  type BuildAppPageElementOptions<TElement> = {
@@ -40,8 +54,11 @@ type BuildAppPageElementResult<TElement> = {
40
54
  };
41
55
  type AppPageInterceptMatch<TPage = unknown> = {
42
56
  interceptLayouts?: readonly unknown[] | null;
57
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
58
+ interceptBranchSegments?: readonly string[] | null;
43
59
  __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
44
60
  matchedParams: AppPageParams;
61
+ sourceMatchedParams?: AppPageParams;
45
62
  page: TPage;
46
63
  __pageLoader?: (() => Promise<TPage>) | null;
47
64
  __loadState?: {
@@ -88,7 +105,10 @@ type ResolveAppPageInterceptionRerenderTargetResult<TRoute, TInterceptOpts> = {
88
105
  type ResolveAppPageActionRerenderTargetOptions<TRoute, TPage, TInterceptOpts> = ResolveAppPageInterceptionRerenderTargetOptions<TRoute, TPage, TInterceptOpts>;
89
106
  type ResolveAppPageActionRerenderTargetResult<TRoute, TInterceptOpts> = ResolveAppPageInterceptionRerenderTargetResult<TRoute, TInterceptOpts>;
90
107
  type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
91
- buildPageElement: (route: TRoute, params: AppPageParams, interceptOpts: TInterceptOpts | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<TElement>;
108
+ buildPageElement: (route: TRoute, params: AppPageParams, interceptOpts: TInterceptOpts | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker, buildOptions?: {
109
+ observeMetadataSearchParamsAccess?: boolean;
110
+ observePageSearchParamsAccess?: boolean;
111
+ }) => Promise<TElement>;
92
112
  cleanPathname: string;
93
113
  currentRoute: TRoute;
94
114
  findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;
@@ -98,6 +118,7 @@ type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
98
118
  layoutParamAccess?: AppLayoutParamAccessTracker;
99
119
  resolveNavigationParams: (route: TRoute, params: AppPageParams, pathname: string, interceptOpts: TInterceptOpts) => AppPageParams;
100
120
  renderInterceptResponse: (route: TRoute, element: TElement) => Promise<Response> | Response;
121
+ resolveSearchParams?: (route: TRoute, searchParams: URLSearchParams) => Awaitable<URLSearchParams>;
101
122
  searchParams: URLSearchParams;
102
123
  setNavigationContext: (context: {
103
124
  params: AppPageParams;
@@ -1,5 +1,6 @@
1
1
  import { notFoundResponse } from "./http-error-responses.js";
2
2
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
3
+ import { matchRoutePattern } from "../routing/route-pattern.js";
3
4
  import { getAppPageSegmentParamName } from "./app-page-params.js";
4
5
  import { loadAppInterceptLayouts } from "./app-route-module-loader.js";
5
6
  //#region src/server/app-page-request.ts
@@ -11,6 +12,31 @@ function pickRouteParams(matchedParams, routeParamNames) {
11
12
  }
12
13
  return params;
13
14
  }
15
+ function remapRouteParams(matchedParams, source) {
16
+ if (source.paramPatternParts && source.routePatternParts) {
17
+ const urlParts = [];
18
+ for (const part of source.routePatternParts) {
19
+ if (!part.startsWith(":")) {
20
+ urlParts.push(part);
21
+ continue;
22
+ }
23
+ const value = matchedParams[part.slice(1).replace(/[+*]$/, "")];
24
+ if (Array.isArray(value)) urlParts.push(...value.map(encodeURIComponent));
25
+ else if (value !== void 0) urlParts.push(encodeURIComponent(value));
26
+ }
27
+ const slotParams = matchRoutePattern(urlParts, source.paramPatternParts);
28
+ if (slotParams) return slotParams;
29
+ }
30
+ if (!source.paramAliases) return matchedParams;
31
+ const params = { ...matchedParams };
32
+ for (const [routeParamName, sourceParamName] of Object.entries(source.paramAliases)) {
33
+ const value = matchedParams[routeParamName];
34
+ if (value === void 0) continue;
35
+ delete params[routeParamName];
36
+ params[sourceParamName] = value;
37
+ }
38
+ return params;
39
+ }
14
40
  function collectParentParamNames(routeSegments, boundaryPosition) {
15
41
  const limit = Math.max(0, Math.min(boundaryPosition, routeSegments.length));
16
42
  const names = [];
@@ -23,6 +49,16 @@ function collectParentParamNames(routeSegments, boundaryPosition) {
23
49
  function getLayoutGenerateStaticParamsBoundary(layoutTreePosition) {
24
50
  return (layoutTreePosition ?? 0) - 1;
25
51
  }
52
+ function getParallelParentParamNames(routeParamNames, branch, boundaryPosition) {
53
+ const slotParamNames = branch.paramNames ?? routeParamNames;
54
+ const branchParamNames = collectParentParamNames(branch.routeSegments ?? [], boundaryPosition);
55
+ const branchParamNameSet = new Set((branch.routeSegments ?? []).flatMap((segment) => {
56
+ const name = getAppPageSegmentParamName(segment);
57
+ return name ? [name] : [];
58
+ }));
59
+ const ownerParamNames = slotParamNames.filter((name) => !branchParamNameSet.has(name));
60
+ return [...new Set([...ownerParamNames, ...branchParamNames])];
61
+ }
26
62
  function resolveAppPageGenerateStaticParamsSources(options) {
27
63
  const sources = [];
28
64
  options.layouts?.forEach((layout, index) => {
@@ -36,6 +72,33 @@ function resolveAppPageGenerateStaticParamsSources(options) {
36
72
  generateStaticParams: options.page.generateStaticParams,
37
73
  parentParamNames: collectParentParamNames(options.routeSegments, Math.max(0, options.routeSegments.length - 1))
38
74
  });
75
+ const routeParamNames = options.routeSegments.flatMap((segment) => {
76
+ const name = getAppPageSegmentParamName(segment);
77
+ return name ? [name] : [];
78
+ });
79
+ for (const parallelBranch of options.parallelBranches ?? []) {
80
+ if (!parallelBranch) continue;
81
+ const slotParamNames = parallelBranch.paramNames ?? routeParamNames;
82
+ const paramAliases = Object.fromEntries(routeParamNames.flatMap((routeParamName, index) => {
83
+ const slotParamName = slotParamNames[index];
84
+ return slotParamName && slotParamName !== routeParamName ? [[routeParamName, slotParamName]] : [];
85
+ }));
86
+ const addParallelSource = (module, boundaryPosition) => {
87
+ if (typeof module?.generateStaticParams !== "function") return;
88
+ sources.push({
89
+ generateStaticParams: module.generateStaticParams,
90
+ ...Object.keys(paramAliases).length > 0 ? { paramAliases } : {},
91
+ ...parallelBranch.patternParts ? { paramPatternParts: parallelBranch.patternParts } : {},
92
+ ...options.routePatternParts ? { routePatternParts: options.routePatternParts } : {},
93
+ parentParamNames: getParallelParentParamNames(routeParamNames, parallelBranch, boundaryPosition)
94
+ });
95
+ };
96
+ addParallelSource(parallelBranch.layout, -1);
97
+ parallelBranch.configLayouts?.forEach((layout, index) => {
98
+ addParallelSource(layout, getLayoutGenerateStaticParamsBoundary(parallelBranch.configLayoutTreePositions?.[index]));
99
+ });
100
+ addParallelSource(parallelBranch.page, Math.max(0, (parallelBranch.routeSegments?.length ?? 0) - 1));
101
+ }
39
102
  return sources;
40
103
  }
41
104
  function areStaticParamsAllowed(params, staticParams) {
@@ -44,8 +107,9 @@ function areStaticParamsAllowed(params, staticParams) {
44
107
  const value = params[key];
45
108
  const staticValue = staticParamSet[key];
46
109
  if (staticValue === void 0) return true;
47
- if (Array.isArray(value)) return JSON.stringify(value) === JSON.stringify(staticValue);
48
- if (typeof staticValue === "string" || typeof staticValue === "number" || typeof staticValue === "boolean") return String(value) === String(staticValue);
110
+ if (Array.isArray(value)) return Array.isArray(staticValue) && value.length === staticValue.length && value.every((part, index) => typeof staticValue[index] === "string" ? part.toLowerCase() === staticValue[index].toLowerCase() : part === staticValue[index]);
111
+ if (typeof staticValue === "string") return value.toLowerCase() === staticValue.toLowerCase();
112
+ if (typeof staticValue === "number" || typeof staticValue === "boolean") return String(value) === String(staticValue);
49
113
  return JSON.stringify(value) === JSON.stringify(staticValue);
50
114
  }));
51
115
  }
@@ -67,8 +131,9 @@ async function validateAppPageDynamicParams(options) {
67
131
  return notFoundResponse();
68
132
  }
69
133
  for (const source of generateStaticParamsSources) {
70
- const staticParams = await runWithFetchDedupe(() => source.generateStaticParams({ params: pickRouteParams(options.params, source.parentParamNames) }));
71
- if (Array.isArray(staticParams) && !areStaticParamsAllowed(options.params, staticParams)) {
134
+ const sourceParams = remapRouteParams(options.params, source);
135
+ const staticParams = await runWithFetchDedupe(() => source.generateStaticParams({ params: pickRouteParams(sourceParams, source.parentParamNames) }));
136
+ if (Array.isArray(staticParams) && !areStaticParamsAllowed(sourceParams, staticParams)) {
72
137
  options.clearRequestContext();
73
138
  return notFoundResponse();
74
139
  }
@@ -97,7 +162,7 @@ async function resolveAppPageInterceptMatch(options) {
97
162
  return {
98
163
  interceptOpts: options.toInterceptOpts(interceptState.intercept),
99
164
  matchedParams: interceptState.intercept.matchedParams,
100
- sourceParams: pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
165
+ sourceParams: pickRouteParams(interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
101
166
  sourceRoute: interceptState.sourceRoute
102
167
  };
103
168
  }
@@ -145,12 +210,18 @@ async function resolveAppPageInterceptionRerenderTarget(options) {
145
210
  isRscRequest: options.isRscRequest,
146
211
  toInterceptOpts: options.toInterceptOpts
147
212
  });
148
- if (interceptState.kind === "source-route") return {
149
- interceptOpts: options.toInterceptOpts(interceptState.intercept),
150
- navigationParams: interceptState.intercept.matchedParams,
151
- params: pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
152
- route: interceptState.sourceRoute
153
- };
213
+ if (interceptState.kind === "source-route") {
214
+ const sourceMatchedParams = interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams;
215
+ return {
216
+ interceptOpts: options.toInterceptOpts(interceptState.intercept),
217
+ navigationParams: {
218
+ ...sourceMatchedParams,
219
+ ...interceptState.intercept.matchedParams
220
+ },
221
+ params: pickRouteParams(sourceMatchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
222
+ route: interceptState.sourceRoute
223
+ };
224
+ }
154
225
  return {
155
226
  interceptOpts: interceptState.kind === "current-route" ? options.toInterceptOpts(interceptState.intercept) : void 0,
156
227
  navigationParams: options.currentParams,
@@ -174,13 +245,19 @@ async function resolveAppPageIntercept(options) {
174
245
  if (interceptState.kind === "source-route") {
175
246
  const renderRoute = interceptState.sourceRoute;
176
247
  const interceptOpts = options.toInterceptOpts(interceptState.intercept);
177
- const renderParams = pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute));
248
+ const sourceMatchedParams = interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams;
249
+ const navigationParams = {
250
+ ...sourceMatchedParams,
251
+ ...interceptState.intercept.matchedParams
252
+ };
253
+ const renderSearchParams = options.resolveSearchParams ? await options.resolveSearchParams(renderRoute, options.searchParams) : options.searchParams;
254
+ const renderParams = pickRouteParams(sourceMatchedParams, options.getRouteParamNames(interceptState.sourceRoute));
178
255
  options.setNavigationContext({
179
- params: options.resolveNavigationParams(renderRoute, interceptState.intercept.matchedParams, options.cleanPathname, interceptOpts),
256
+ params: options.resolveNavigationParams(renderRoute, navigationParams, options.cleanPathname, interceptOpts),
180
257
  pathname: options.cleanPathname,
181
- searchParams: options.searchParams
258
+ searchParams: renderSearchParams
182
259
  });
183
- const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, options.searchParams, options.layoutParamAccess);
260
+ const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, renderSearchParams, options.layoutParamAccess);
184
261
  return {
185
262
  interceptOpts: void 0,
186
263
  response: await options.renderInterceptResponse(renderRoute, interceptElement)
@@ -1,10 +1,10 @@
1
1
  import { AppRouteSemanticIds } from "../routing/app-route-graph.js";
2
- import { AppElements, AppElementsInterception } from "./app-elements-wire.js";
2
+ import { AppElements, AppElementsInterception, AppElementsSlotBinding } from "./app-elements-wire.js";
3
3
  import { AppPageParams } from "./app-page-boundary.js";
4
4
  import { ThenableParamsObserver } from "../shims/thenable-params.js";
5
+ import { Metadata, Viewport } from "../shims/metadata.js";
5
6
  import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
6
7
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
7
- import { Metadata, Viewport } from "../shims/metadata.js";
8
8
  import { AppPageRenderIdentity } from "./app-page-render-identity.js";
9
9
  import { resolveAppPageChildSegments } from "./app-page-segment-state.js";
10
10
  import { ComponentType, ReactNode } from "react";
@@ -31,6 +31,8 @@ type AppPageRouteWiringSlot<TModule extends AppPageModule = AppPageModule, TErro
31
31
  /** Graph-owned semantic slot identity. */id?: string | null; /** Slot prop name passed to the owning layout (e.g. "modal" from @modal). */
32
32
  name: string;
33
33
  default?: TModule | null;
34
+ configLayouts?: readonly (TModule | null | undefined)[] | null;
35
+ configLayoutTreePositions?: readonly number[] | null;
34
36
  error?: TErrorModule | null;
35
37
  layout?: TModule | null;
36
38
  layoutIndex: number;
@@ -62,10 +64,16 @@ type AppPageRouteWiringRoute<TModule extends AppPageModule = AppPageModule, TErr
62
64
  unauthorized?: TModule | null;
63
65
  unauthorizeds?: readonly (TModule | null | undefined)[] | null;
64
66
  routeSegments?: readonly string[];
67
+ childrenRouteSegments?: readonly string[] | null;
65
68
  /**
66
69
  * Keyed by stable slot id (name + owner path), not necessarily the slot prop name.
67
70
  */
68
71
  slots?: Readonly<Record<string, AppPageRouteWiringSlot<TModule, TErrorModule>>> | null;
72
+ childrenSlot?: {
73
+ id: string;
74
+ ownerTreePath: string;
75
+ state: AppElementsSlotBinding["state"];
76
+ } | null;
69
77
  /**
70
78
  * Static sibling segment names at each dynamic URL level for this route. Used
71
79
  * by the client router to determine if a cached prefetch of the dynamic
@@ -83,6 +91,8 @@ type AppPageRouteWiringRoute<TModule extends AppPageModule = AppPageModule, TErr
83
91
  templates?: readonly (TModule | null | undefined)[] | null;
84
92
  };
85
93
  type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {
94
+ branchSegments?: readonly string[] | null;
95
+ layoutSegments?: readonly (readonly string[])[] | null;
86
96
  layoutModules?: readonly (TModule | null | undefined)[] | null;
87
97
  /**
88
98
  * The page module to render for this slot. Optional — when omitted, the
@@ -92,6 +102,7 @@ type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {
92
102
  pageModule?: TModule | null;
93
103
  params?: AppPageParams;
94
104
  props?: Readonly<Record<string, unknown>>;
105
+ routeSegments?: readonly string[] | null;
95
106
  };
96
107
  type AppPageLayoutEntry<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {
97
108
  errorModule?: TErrorModule | null | undefined;
@@ -118,6 +129,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
118
129
  rootNotFoundModule?: TModule | null;
119
130
  rootUnauthorizedModule?: TModule | null;
120
131
  route: AppPageRouteWiringRoute<TModule, TErrorModule>;
132
+ createPageElement?: (component: AppPageComponent, props: Readonly<Record<string, unknown>>) => ReactNode;
121
133
  searchParams?: unknown;
122
134
  slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;
123
135
  };
@@ -8,14 +8,17 @@ import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
8
8
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
9
9
  import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
10
10
  import { Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
11
- import { resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
11
+ import { resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
12
12
  import { probeReactServerSubtree } from "./app-page-probe.js";
13
- import { resolveAppPageChildSegments, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey } from "./app-page-segment-state.js";
13
+ import { APP_PAGE_SEGMENT_KEY, resolveAppPageChildSegments, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey } from "./app-page-segment-state.js";
14
14
  import { Fragment, Suspense } from "react";
15
15
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
16
  //#region src/server/app-page-route-wiring.tsx
17
17
  const APP_PAGE_LAYOUT_PROBE_CHILD = /* @__PURE__ */ jsx(Fragment, {});
18
18
  const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
19
+ function resolveSlotLayoutParams(routeSegments, treePosition, params) {
20
+ return resolveAppPageBranchParams(routeSegments, treePosition, params);
21
+ }
19
22
  function getDefaultExport(module) {
20
23
  return module?.default ?? null;
21
24
  }
@@ -90,6 +93,10 @@ function createAppPageTemplateEntries(route) {
90
93
  function createAppPageSourcePage(routeSegments) {
91
94
  return `/${[...routeSegments ?? [], "page"].join("/")}`;
92
95
  }
96
+ function resolveAppPageLayoutSegmentProviderSegments(routeSegments, treePosition, params) {
97
+ const segments = resolveAppPageChildSegments(routeSegments, treePosition, params);
98
+ return segments.at(-1) === "__PAGE__" ? segments.slice(0, -1) : segments;
99
+ }
93
100
  function createAppPageErrorEntries(route) {
94
101
  return (route.errorPaths ?? route.errors ?? []).flatMap((errorModule, index) => {
95
102
  if (!errorModule) return [];
@@ -101,7 +108,7 @@ function createAppPageErrorEntries(route) {
101
108
  }];
102
109
  });
103
110
  }
104
- function createAppPageParallelSlotEntries(layoutIndex, layoutEntries, route, getEffectiveSlotParams) {
111
+ function createAppPageParallelSlotEntries(layoutIndex, layoutEntries, route, getEffectiveSlotParams, resolveSlotOverride) {
105
112
  const parallelSlots = {};
106
113
  for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
107
114
  const slotName = slot.name;
@@ -109,8 +116,10 @@ function createAppPageParallelSlotEntries(layoutIndex, layoutEntries, route, get
109
116
  if (targetIndex !== layoutIndex) continue;
110
117
  const slotId = resolveAppPageSlotId(slot, layoutEntries[targetIndex]?.treePath ?? "/");
111
118
  const slotParams = getEffectiveSlotParams(slotKey, slotName);
119
+ const routeSegments = resolveSlotOverride(slotKey, slotName)?.routeSegments ?? slot.routeSegments;
112
120
  parallelSlots[slotName] = /* @__PURE__ */ jsx(LayoutSegmentProvider, {
113
- segmentMap: { children: slot.routeSegments ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams) : [] },
121
+ providerId: slotId,
122
+ segmentMap: { children: routeSegments ? resolveAppPageLayoutSegmentProviderSegments(routeSegments, 0, slotParams) : [] },
114
123
  children: /* @__PURE__ */ jsx(Slot, { id: slotId })
115
124
  });
116
125
  }
@@ -128,6 +137,14 @@ function resolveAppPageSlotBindingState(slot, override) {
128
137
  }
129
138
  function createAppPageSlotBindings(route, layoutEntries, resolveSlotOverride, options) {
130
139
  const bindings = [];
140
+ if (route.childrenSlot) {
141
+ const ownerLayoutId = layoutEntries.find((layoutEntry) => layoutEntry.treePath === route.childrenSlot?.ownerTreePath)?.id;
142
+ bindings.push({
143
+ ownerLayoutId: ownerLayoutId ?? null,
144
+ slotId: route.childrenSlot.id,
145
+ state: route.childrenSlot.state
146
+ });
147
+ }
131
148
  for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
132
149
  const layoutEntry = layoutEntries[slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1] ?? null;
133
150
  const ownerLayoutId = layoutEntry?.id ?? null;
@@ -170,6 +187,7 @@ function buildAppPageElements(options) {
170
187
  const routeResetKey = resolveAppPageRouteStateKey(routeSegments, options.matchedParams);
171
188
  const routeId = renderIdentity?.routeId ?? AppElementsWire.encodeRouteId(options.routePath, interceptionContext);
172
189
  const pageId = renderIdentity?.pageId ?? AppElementsWire.encodePageId(options.routePath, interceptionContext);
190
+ const pageElementId = options.route.childrenSlot?.id ?? pageId;
173
191
  const layoutEntries = createAppPageLayoutEntries(options.route);
174
192
  const templateEntries = createAppPageTemplateEntries(options.route);
175
193
  const errorEntries = createAppPageErrorEntries(options.route);
@@ -243,19 +261,13 @@ function buildAppPageElements(options) {
243
261
  const routeLoadingComponent = getDefaultExport(options.route.loading);
244
262
  const isPrefetchLoadingShell = renderMode === APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;
245
263
  if (isPrefetchLoadingShell && routeLoadingComponent !== null) elements[APP_PREFETCH_LOADING_SHELL_MARKER_KEY] = "LoadingBoundary";
246
- elements[pageId] = isPrefetchLoadingShell ? null : renderAfterAppDependencies(options.element, pageDependencies);
264
+ elements[pageElementId] = isPrefetchLoadingShell ? null : renderAfterAppDependencies(options.element, pageDependencies);
247
265
  for (const templateEntry of templateEntries) {
248
266
  const templateComponent = getDefaultExport(templateEntry.templateModule);
249
267
  if (!templateComponent) continue;
250
268
  const TemplateComponent = templateComponent;
251
269
  const templateDependency = templateDependenciesById.get(templateEntry.id);
252
- const templateElement = templateDependency ? renderWithAppDependencyBarrier(/* @__PURE__ */ jsx(TemplateComponent, {
253
- params: options.matchedParams,
254
- children: /* @__PURE__ */ jsx(Children$1, {})
255
- }), templateDependency) : /* @__PURE__ */ jsx(TemplateComponent, {
256
- params: options.matchedParams,
257
- children: /* @__PURE__ */ jsx(Children$1, {})
258
- });
270
+ const templateElement = templateDependency ? renderWithAppDependencyBarrier(/* @__PURE__ */ jsx(TemplateComponent, { children: /* @__PURE__ */ jsx(Children$1, {}) }), templateDependency) : /* @__PURE__ */ jsx(TemplateComponent, { children: /* @__PURE__ */ jsx(Children$1, {}) });
259
271
  elements[templateEntry.id] = renderAfterAppDependencies(templateElement, templateDependenciesBeforeById.get(templateEntry.id) ?? []);
260
272
  }
261
273
  for (let index = 0; index < layoutEntries.length; index++) {
@@ -293,7 +305,9 @@ function buildAppPageElements(options) {
293
305
  const slotId = resolveAppPageSlotId(slot, layoutEntries[targetIndex]?.treePath ?? "/");
294
306
  const slotOverride = resolveSlotOverride(slotKey, slotName);
295
307
  const slotParams = getEffectiveSlotParams(slotKey, slotName);
296
- const slotResetKey = resolveAppPageRouteStateKey(slot.routeSegments ?? [], slotParams);
308
+ const slotRouteSegments = slotOverride?.routeSegments ?? slot.routeSegments ?? [];
309
+ const slotOwnerParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntries[targetIndex]?.treePosition ?? 0, options.matchedParams);
310
+ const slotResetKey = resolveAppPageRouteStateKey(slotRouteSegments, slotParams);
297
311
  const overrideOrPageComponent = getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);
298
312
  const defaultComponent = getDefaultExport(slot.default);
299
313
  if (!overrideOrPageComponent && defaultComponent && options.isRscRequest && options.mountedSlotIds?.has(slotId)) continue;
@@ -302,23 +316,40 @@ function buildAppPageElements(options) {
302
316
  elements[slotId] = AppElementsWire.unmatchedSlotValue;
303
317
  continue;
304
318
  }
305
- const slotThenableParams = options.makeThenableParams(slotParams);
306
- const slotProps = { params: slotThenableParams };
319
+ const slotProps = { params: options.makeThenableParams(slotParams) };
307
320
  if (options.searchParams !== void 0) slotProps.searchParams = options.searchParams;
308
321
  if (slotOverride?.props) Object.assign(slotProps, slotOverride.props);
309
- let slotElement = /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
322
+ let slotElement = options.createPageElement ? options.createPageElement(slotComponent, slotProps) : (() => {
323
+ return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
324
+ })();
325
+ const hasSlotTreeOverride = slotOverride?.pageModule != null || slotOverride?.layoutModules !== void 0;
310
326
  const interceptLayouts = slotOverride?.layoutModules ?? [];
311
327
  for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {
312
328
  const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);
313
329
  if (!interceptLayoutComponent) continue;
314
- slotElement = /* @__PURE__ */ jsx(interceptLayoutComponent, {
315
- params: slotThenableParams,
330
+ const InterceptLayoutComponent = interceptLayoutComponent;
331
+ const interceptLayoutParams = resolveSlotLayoutParams(slotOverride?.branchSegments ?? slotRouteSegments, slotOverride?.layoutSegments?.[layoutIndex]?.length ?? slotRouteSegments.length, slotParams);
332
+ slotElement = /* @__PURE__ */ jsx(InterceptLayoutComponent, {
333
+ params: options.makeThenableParams(interceptLayoutParams),
334
+ children: slotElement
335
+ });
336
+ }
337
+ if (!hasSlotTreeOverride) for (let layoutIndex = (slot.configLayouts?.length ?? 0) - 1; layoutIndex >= 0; layoutIndex--) {
338
+ const nestedLayoutComponent = getDefaultExport(slot.configLayouts?.[layoutIndex]);
339
+ if (!nestedLayoutComponent) continue;
340
+ const NestedLayoutComponent = nestedLayoutComponent;
341
+ const nestedLayoutParams = resolveSlotLayoutParams(slotRouteSegments, slot.configLayoutTreePositions?.[layoutIndex] ?? 0, slotParams);
342
+ slotElement = /* @__PURE__ */ jsx(NestedLayoutComponent, {
343
+ params: options.makeThenableParams({
344
+ ...slotOwnerParams,
345
+ ...nestedLayoutParams
346
+ }),
316
347
  children: slotElement
317
348
  });
318
349
  }
319
- const slotLayoutComponent = getDefaultExport(slot.layout);
350
+ const slotLayoutComponent = overrideOrPageComponent ? getDefaultExport(slot.layout) : null;
320
351
  if (slotLayoutComponent) slotElement = /* @__PURE__ */ jsx(slotLayoutComponent, {
321
- params: slotThenableParams,
352
+ params: options.makeThenableParams(slotOwnerParams),
322
353
  children: slotElement
323
354
  });
324
355
  const slotLoadingComponent = getDefaultExport(slot.loading);
@@ -335,8 +366,9 @@ function buildAppPageElements(options) {
335
366
  elements[slotId] = renderAfterAppDependencies(slotElement, targetIndex >= 0 ? slotDependenciesByLayoutIndex[targetIndex] ?? [] : []);
336
367
  }
337
368
  let routeChildren = /* @__PURE__ */ jsx(LayoutSegmentProvider, {
338
- segmentMap: { children: [] },
339
- children: /* @__PURE__ */ jsx(Slot, { id: pageId })
369
+ providerId: pageElementId,
370
+ segmentMap: { children: [APP_PAGE_SEGMENT_KEY] },
371
+ children: /* @__PURE__ */ jsx(Slot, { id: pageElementId })
340
372
  });
341
373
  if (isPrefetchLoadingShell) if (routeLoadingComponent === null) routeChildren = null;
342
374
  else routeChildren = /* @__PURE__ */ jsx(routeLoadingComponent, {});
@@ -416,18 +448,22 @@ function buildAppPageElements(options) {
416
448
  }
417
449
  const layoutHasElement = getDefaultExport(layoutEntry.layoutModule) !== null;
418
450
  const layoutIndex = layoutIndicesByTreePosition.get(treePosition) ?? -1;
419
- const segmentMap = { children: resolveAppPageChildSegments(routeSegments, layoutEntry.treePosition, options.matchedParams) };
451
+ const segmentMap = { children: resolveAppPageLayoutSegmentProviderSegments(options.route.childrenRouteSegments ?? routeSegments, layoutEntry.treePosition, options.matchedParams) };
420
452
  for (const [slotKey, slot] of Object.entries(options.route.slots ?? {})) {
421
453
  const slotName = slot.name;
422
454
  if ((slot.layoutIndex >= 0 ? slot.layoutIndex : layoutEntries.length - 1) !== layoutIndex) continue;
423
455
  const slotParams = getEffectiveSlotParams(slotKey, slotName);
424
- segmentMap[slotName] = slot.routeSegments ? resolveAppPageChildSegments(slot.routeSegments, 0, slotParams) : [];
456
+ const slotOverride = resolveSlotOverride(slotKey, slotName);
457
+ if (!(getDefaultExport(slotOverride?.pageModule) !== null || getDefaultExport(slot.page) !== null) && options.isRscRequest && options.mountedSlotIds?.has(resolveAppPageSlotId(slot, layoutEntry.treePath))) continue;
458
+ const slotRouteSegments = slotOverride?.routeSegments ?? slot.routeSegments;
459
+ segmentMap[slotName] = slotRouteSegments ? resolveAppPageLayoutSegmentProviderSegments(slotRouteSegments, 0, slotParams) : [];
425
460
  }
426
461
  routeChildren = /* @__PURE__ */ jsx(LayoutSegmentProvider, {
462
+ providerId: layoutEntry.id,
427
463
  segmentMap,
428
464
  children: layoutHasElement ? /* @__PURE__ */ jsx(Slot, {
429
465
  id: layoutEntry.id,
430
- parallelSlots: createAppPageParallelSlotEntries(layoutIndex, layoutEntries, options.route, getEffectiveSlotParams),
466
+ parallelSlots: createAppPageParallelSlotEntries(layoutIndex, layoutEntries, options.route, getEffectiveSlotParams, resolveSlotOverride),
431
467
  children: segmentChildren
432
468
  }) : segmentChildren
433
469
  });
@@ -1,10 +1,12 @@
1
- import { ThenableParams } from "../shims/thenable-params.js";
1
+ import { ThenableParams, ThenableParamsObserver } from "../shims/thenable-params.js";
2
2
  import { AppPageSearchParams } from "./app-page-head.js";
3
3
 
4
4
  //#region src/server/app-page-search-params-observation.d.ts
5
5
  type AppPageSearchParamsObservationOptions = {
6
+ markDynamic?: boolean;
6
7
  observeReactPromiseStatus?: boolean;
7
8
  };
9
+ declare function createAppPageSearchParamsObserver(options?: AppPageSearchParamsObservationOptions): ThenableParamsObserver;
8
10
  declare function makeObservedAppPageSearchParamsThenable(pageSearchParams: AppPageSearchParams, options?: AppPageSearchParamsObservationOptions): ThenableParams<AppPageSearchParams>;
9
11
  //#endregion
10
- export { makeObservedAppPageSearchParamsThenable };
12
+ export { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable };
@@ -1,15 +1,19 @@
1
- import { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope } from "../shims/headers.js";
1
+ import { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "../shims/headers.js";
2
2
  import { makeThenableParams } from "../shims/thenable-params.js";
3
3
  //#region src/server/app-page-search-params-observation.ts
4
- function markAppPageSearchParamsAccess() {
4
+ function markAppPageSearchParamsAccess(markDynamic) {
5
+ throwIfStaticGenerationAccessError();
5
6
  throwIfInsideCacheScope("searchParams");
6
- markDynamicUsage();
7
+ if (markDynamic) markDynamicUsage();
7
8
  markRenderRequestApiUsage("searchParams");
8
9
  }
9
- function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {}) {
10
- const observer = { observeParamAccess() {
11
- markAppPageSearchParamsAccess();
10
+ function createAppPageSearchParamsObserver(options = {}) {
11
+ return { observeParamAccess() {
12
+ markAppPageSearchParamsAccess(options.markDynamic !== false);
12
13
  } };
14
+ }
15
+ function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {}) {
16
+ const observer = createAppPageSearchParamsObserver(options);
13
17
  if (options.observeReactPromiseStatus === true) return makeThenableParams(pageSearchParams, {
14
18
  ...observer,
15
19
  observeReactPromiseStatus: true
@@ -17,4 +21,4 @@ function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {})
17
21
  return makeThenableParams(pageSearchParams, observer);
18
22
  }
19
23
  //#endregion
20
- export { makeObservedAppPageSearchParamsThenable };
24
+ export { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable };
@@ -1,9 +1,10 @@
1
1
  import { AppPageParams } from "./app-page-boundary.js";
2
2
 
3
3
  //#region src/server/app-page-segment-state.d.ts
4
+ declare const APP_PAGE_SEGMENT_KEY = "__PAGE__";
4
5
  declare function resolveAppPageChildSegments(routeSegments: readonly string[], treePosition: number, params: AppPageParams): string[];
5
6
  declare function resolveAppPageSegmentStateKey(routeSegments: readonly string[], treePosition: number, params: AppPageParams): string;
6
7
  declare function resolveAppPageRouteStateKey(routeSegments: readonly string[], params: AppPageParams): string;
7
8
  declare function resolveAppPageLeafSegmentStateKey(routeSegments: readonly string[], params: AppPageParams): string;
8
9
  //#endregion
9
- export { resolveAppPageChildSegments, resolveAppPageLeafSegmentStateKey, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey };
10
+ export { APP_PAGE_SEGMENT_KEY, resolveAppPageChildSegments, resolveAppPageLeafSegmentStateKey, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey };