vinext 1.4.0 → 1.4.2

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 (156) hide show
  1. package/README.md +21 -21
  2. package/dist/build/action-owner-manifest.js +1 -0
  3. package/dist/build/prerender.js +3 -2
  4. package/dist/check.js +4 -7
  5. package/dist/client/dev-error-overlay-store.d.ts +1 -0
  6. package/dist/client/dev-error-overlay.d.ts +2 -0
  7. package/dist/client/dev-error-overlay.js +19 -3
  8. package/dist/config/config-matchers.js +4 -2
  9. package/dist/config/destination-params.d.ts +2 -1
  10. package/dist/config/destination-params.js +55 -2
  11. package/dist/config/next-config.d.ts +22 -1
  12. package/dist/config/next-config.js +49 -4
  13. package/dist/entries/app-rsc-entry.js +41 -19
  14. package/dist/entries/app-rsc-manifest.js +4 -0
  15. package/dist/entries/pages-server-entry.js +5 -1
  16. package/dist/index.js +44 -32
  17. package/dist/init-cloudflare.js +18 -2
  18. package/dist/plugins/css-target.d.ts +18 -0
  19. package/dist/plugins/css-target.js +93 -0
  20. package/dist/plugins/strip-server-exports.js +2 -1
  21. package/dist/routing/app-route-graph.d.ts +10 -0
  22. package/dist/routing/app-route-graph.js +15 -1
  23. package/dist/server/api-handler.d.ts +2 -0
  24. package/dist/server/api-handler.js +5 -6
  25. package/dist/server/app-action-forwarding.js +3 -1
  26. package/dist/server/app-browser-entry.js +28 -7
  27. package/dist/server/app-browser-rsc-redirect.js +3 -3
  28. package/dist/server/app-browser-server-action-client.js +2 -2
  29. package/dist/server/app-browser-visible-commit.js +2 -2
  30. package/dist/server/app-elements.d.ts +3 -0
  31. package/dist/server/app-elements.js +14 -1
  32. package/dist/server/app-fallback-renderer.js +2 -2
  33. package/dist/server/app-optimistic-routing.d.ts +12 -1
  34. package/dist/server/app-optimistic-routing.js +40 -19
  35. package/dist/server/app-page-boundary-render.js +7 -12
  36. package/dist/server/app-page-cache-render.js +1 -1
  37. package/dist/server/app-page-dispatch.d.ts +10 -2
  38. package/dist/server/app-page-dispatch.js +73 -31
  39. package/dist/server/app-page-element-builder.d.ts +9 -20
  40. package/dist/server/app-page-element-builder.js +40 -52
  41. package/dist/server/app-page-execution.js +9 -6
  42. package/dist/server/app-page-intercept-segment-config.d.ts +56 -0
  43. package/dist/server/app-page-intercept-segment-config.js +90 -0
  44. package/dist/server/app-page-navigation-params.d.ts +23 -0
  45. package/dist/server/app-page-navigation-params.js +49 -0
  46. package/dist/server/app-page-render.d.ts +5 -3
  47. package/dist/server/app-page-render.js +31 -17
  48. package/dist/server/app-page-request.d.ts +24 -2
  49. package/dist/server/app-page-request.js +10 -10
  50. package/dist/server/app-page-response.js +1 -1
  51. package/dist/server/app-page-route-wiring.d.ts +10 -0
  52. package/dist/server/app-page-route-wiring.js +34 -13
  53. package/dist/server/app-page-segment-plan.js +9 -1
  54. package/dist/server/app-page-segment-state.d.ts +9 -0
  55. package/dist/server/app-page-segment-state.js +54 -1
  56. package/dist/server/app-page-stream.d.ts +10 -8
  57. package/dist/server/app-page-stream.js +2 -1
  58. package/dist/server/app-request-stage-independent-entry.js +1 -1
  59. package/dist/server/app-response-stage-entry.js +1 -0
  60. package/dist/server/app-route-handler-execution.js +3 -2
  61. package/dist/server/app-route-handler-runtime.d.ts +1 -1
  62. package/dist/server/app-route-handler-runtime.js +11 -7
  63. package/dist/server/app-route-module-loader.d.ts +2 -0
  64. package/dist/server/app-route-module-loader.js +1 -0
  65. package/dist/server/app-router-entry.js +1 -1
  66. package/dist/server/app-rsc-cache-busting.d.ts +10 -10
  67. package/dist/server/app-rsc-cache-busting.js +27 -68
  68. package/dist/server/app-rsc-error-handler.js +1 -1
  69. package/dist/server/app-rsc-errors.js +4 -1
  70. package/dist/server/app-rsc-handler.d.ts +10 -1
  71. package/dist/server/app-rsc-handler.js +126 -103
  72. package/dist/server/app-rsc-request-normalization.d.ts +10 -12
  73. package/dist/server/app-rsc-request-normalization.js +11 -14
  74. package/dist/server/app-rsc-response-finalizer.d.ts +3 -0
  75. package/dist/server/app-rsc-response-finalizer.js +11 -1
  76. package/dist/server/app-rsc-response-stage.js +4 -12
  77. package/dist/server/app-rsc-route-matching.d.ts +14 -0
  78. package/dist/server/app-rsc-route-matching.js +42 -18
  79. package/dist/server/app-server-action-execution.js +24 -14
  80. package/dist/server/app-ssr-entry.d.ts +6 -0
  81. package/dist/server/app-ssr-entry.js +13 -8
  82. package/dist/server/app-worker-stages.d.ts +12 -3
  83. package/dist/server/app-worker-stages.js +37 -4
  84. package/dist/server/bfcache-identity.d.ts +7 -0
  85. package/dist/server/bfcache-identity.js +10 -1
  86. package/dist/server/cache-control.d.ts +2 -0
  87. package/dist/server/cache-control.js +3 -1
  88. package/dist/server/cacheability-manifest.js +1 -2
  89. package/dist/server/dev-origin-check.d.ts +2 -1
  90. package/dist/server/dev-origin-check.js +2 -1
  91. package/dist/server/dev-server.js +2 -1
  92. package/dist/server/image-local-patterns.d.ts +21 -0
  93. package/dist/server/image-local-patterns.js +59 -0
  94. package/dist/server/image-optimization.d.ts +28 -22
  95. package/dist/server/image-optimization.js +17 -2
  96. package/dist/server/isr-cache.js +4 -1
  97. package/dist/server/metadata-route-response.js +25 -7
  98. package/dist/server/middleware-matcher.js +19 -6
  99. package/dist/server/middleware-runtime.js +6 -2
  100. package/dist/server/multi-stage.d.ts +7 -3
  101. package/dist/server/nitro-public-files-plugin.js +20 -8
  102. package/dist/server/pages-data-route.d.ts +5 -1
  103. package/dist/server/pages-data-route.js +14 -6
  104. package/dist/server/pages-node-compat.d.ts +1 -1
  105. package/dist/server/pages-node-compat.js +2 -0
  106. package/dist/server/pages-page-data.js +2 -1
  107. package/dist/server/pages-page-handler.js +17 -6
  108. package/dist/server/pages-page-response.d.ts +9 -0
  109. package/dist/server/pages-page-response.js +18 -4
  110. package/dist/server/pages-request-pipeline.js +6 -5
  111. package/dist/server/pages-request-stage-entry.js +25 -4
  112. package/dist/server/pages-router-entry.js +3 -2
  113. package/dist/server/prod-server.d.ts +2 -2
  114. package/dist/server/prod-server.js +59 -17
  115. package/dist/server/request-error-log.d.ts +9 -0
  116. package/dist/server/request-error-log.js +13 -0
  117. package/dist/server/request-pipeline.d.ts +14 -4
  118. package/dist/server/request-pipeline.js +33 -15
  119. package/dist/server/response-stage-cacheability.d.ts +7 -0
  120. package/dist/server/response-stage-cacheability.js +6 -5
  121. package/dist/server/rsc-completion-metadata.js +3 -0
  122. package/dist/server/static-file-cache.d.ts +9 -0
  123. package/dist/server/static-file-cache.js +13 -2
  124. package/dist/server/worker-image-optimization.d.ts +2 -2
  125. package/dist/server/worker-image-optimization.js +18 -3
  126. package/dist/server/worker-utils.d.ts +8 -0
  127. package/dist/server/worker-utils.js +19 -2
  128. package/dist/shims/cache-request-state.d.ts +6 -6
  129. package/dist/shims/cache-request-state.js +6 -36
  130. package/dist/shims/cache-runtime.d.ts +3 -1
  131. package/dist/shims/cache-runtime.js +77 -47
  132. package/dist/shims/cache.d.ts +10 -5
  133. package/dist/shims/cache.js +35 -22
  134. package/dist/shims/client-hook-error.d.ts +2 -0
  135. package/dist/shims/client-hook-error.js +16 -1
  136. package/dist/shims/fetch-cache.js +6 -2
  137. package/dist/shims/headers.d.ts +2 -1
  138. package/dist/shims/headers.js +5 -3
  139. package/dist/shims/image-props.d.ts +6 -0
  140. package/dist/shims/image-props.js +39 -3
  141. package/dist/shims/image.js +3 -3
  142. package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
  143. package/dist/shims/link.js +5 -10
  144. package/dist/shims/navigation.js +2 -3
  145. package/dist/shims/request-state-types.d.ts +2 -1
  146. package/dist/shims/slot.d.ts +9 -2
  147. package/dist/shims/slot.js +76 -11
  148. package/dist/shims/unified-request-context.d.ts +6 -0
  149. package/dist/shims/unified-request-context.js +1 -0
  150. package/dist/utils/base-path.d.ts +7 -0
  151. package/dist/utils/base-path.js +11 -1
  152. package/dist/utils/cache-life-profiles.d.ts +33 -0
  153. package/dist/utils/cache-life-profiles.js +111 -0
  154. package/dist/utils/middleware-request-headers.d.ts +14 -3
  155. package/dist/utils/middleware-request-headers.js +54 -7
  156. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import "../utils/protocol-headers.js";
3
3
  import { VINEXT_INTERCEPTION_ID_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
4
- import { VINEXT_MOUNTED_LAYOUTS_HEADER } from "./headers.js";
4
+ import { VINEXT_MOUNTED_LAYOUTS_HEADER, VINEXT_PARAMS_HEADER } from "./headers.js";
5
5
  import { getRequestExecutionContext } from "../shims/request-context.js";
6
6
  import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
7
7
  import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityPatternDynamic, readRouteCacheabilityState } from "../shims/cacheability-classification.js";
@@ -21,16 +21,17 @@ import { resolveUncacheableCacheControl } from "./app-page-response.js";
21
21
  import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
22
22
  import { buildAppPageSpecialErrorResponse, resolveAppPageCaughtNotFoundBoundaries, resolveAppPageShellSpecialError, resolveAppPageSpecialError, resolveAppPageSpecialErrorStoredHeaders } from "./app-page-execution.js";
23
23
  import { resolveAppPageLayoutHttpAccessBoundary, resolveAppPageParentHttpAccessBoundary, resolveAppPageRootHttpAccessBoundaryTreePosition } from "./app-page-boundary.js";
24
+ import { resolveAppPageNavigationParams } from "./app-page-navigation-params.js";
25
+ import { createAppPageRscErrorTracker } from "./app-page-stream.js";
24
26
  import { isAppClientReference } from "./app-render-dependency.js";
25
27
  import { resolveAppPageTraceOperation } from "./app-page-tracing.js";
26
- import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
27
- import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
28
- import { createAppPageRscErrorTracker } from "./app-page-stream.js";
29
28
  import { getDefaultHttpAccessFallbackModule } from "./default-http-access-fallback-modules.js";
29
+ import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
30
30
  import { consumeAppPageRenderObservationState, discardAppPageRenderState } from "./app-page-render-observation.js";
31
31
  import { buildAppPageTags } from "./implicit-tags.js";
32
32
  import { resolveAppPageMethodResponse } from "./app-page-method.js";
33
- import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
33
+ import { resolveAppPageInterceptSegmentConfig } from "./app-page-intercept-segment-config.js";
34
+ import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptState, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
34
35
  import { applyIneligibleRouteCachePolicy, renderAppPageLifecycle } from "./app-page-render.js";
35
36
  //#region src/server/app-page-dispatch.ts
36
37
  function getActiveLoadingTreePositions(route) {
@@ -146,12 +147,48 @@ function hasNoManifestAdmissionState(routePattern) {
146
147
  }, admission.representation, admission.routePathname) === null;
147
148
  }
148
149
  async function dispatchAppPage(options) {
149
- const dispatch = () => runWithFetchDedupe(() => dispatchAppPageInner(options));
150
+ const dispatch = () => runWithFetchDedupe(async () => dispatchAppPageInner(await withResolvedIntercept(options)));
150
151
  let response;
151
152
  if (!options.pprFallbackShell || !options.pprRuntime) response = await dispatch();
152
153
  else response = await options.pprRuntime.run(options.pprFallbackShell, dispatch);
153
154
  return options.isRscRequest ? response : traceResponseStart(response);
154
155
  }
156
+ /**
157
+ * Resolves the request's intercept once, for the render and its cache reads.
158
+ *
159
+ * Next.js renders an interception as its own route even when its source is the
160
+ * matched route (`app/shots/[id]` beside `app/shots/@modal/(.)[id]`, from
161
+ * `/shots/1` to `/shots/2`). vinext renders that through the matched route's
162
+ * own page render, so the interception's segment config replaces the route's
163
+ * before that render reads it.
164
+ */
165
+ async function withResolvedIntercept(options) {
166
+ const interceptState = await resolveAppPageInterceptState({
167
+ cleanPathname: options.cleanPathname,
168
+ currentRoute: options.route,
169
+ findIntercept: options.findIntercept,
170
+ getSourceRoute: options.getSourceRoute,
171
+ interceptState: options.interceptState,
172
+ isRscRequest: options.isRscRequest
173
+ });
174
+ if (interceptState.kind !== "current-route") return {
175
+ ...options,
176
+ interceptState
177
+ };
178
+ const config = resolveAppPageInterceptSegmentConfig(options.route, toInterceptOptions(options.interceptionContext, interceptState.intercept));
179
+ return {
180
+ ...options,
181
+ interceptState,
182
+ dynamicConfig: config.dynamicConfig,
183
+ dynamicStaleTimeSeconds: config.dynamicStaleTimeSeconds,
184
+ fetchCache: config.fetchCacheMode,
185
+ hasAnyGenerateStaticParams: config.hasAnyGenerateStaticParams,
186
+ hasGenerateStaticParams: config.hasGenerateStaticParams,
187
+ isEdgeRuntime: config.isEdgeRuntime,
188
+ isStaticGenerationEdgeRuntime: config.isStaticGenerationEdgeRuntime,
189
+ revalidateSeconds: config.revalidateSeconds
190
+ };
191
+ }
155
192
  async function dispatchAppPageInner(options) {
156
193
  const route = options.route;
157
194
  beginRouteCacheability("app-page", route.pattern);
@@ -206,6 +243,7 @@ async function dispatchAppPageInner(options) {
206
243
  isDynamicError,
207
244
  isForceDynamic,
208
245
  isForceStatic,
246
+ isPrerender,
209
247
  isProduction: options.isProduction,
210
248
  isProgressiveActionRender: options.isProgressiveActionRender === true,
211
249
  isRscRequest: options.isRscRequest,
@@ -280,6 +318,7 @@ async function dispatchAppPageInner(options) {
280
318
  getSourceRoute(sourceRouteIndex) {
281
319
  return options.getSourceRoute(sourceRouteIndex);
282
320
  },
321
+ interceptState: options.interceptState,
283
322
  isRscRequest: options.isRscRequest,
284
323
  toInterceptOpts(intercept) {
285
324
  return toInterceptOptions(options.interceptionContext, intercept);
@@ -320,9 +359,10 @@ async function dispatchAppPageInner(options) {
320
359
  isDynamicRscRequest: options.pprRuntime !== void 0 && options.isRscRequest && options.request.headers.get("Next-Router-Prefetch") !== "1" && options.renderedConcreteUrlPaths?.has(options.cleanPathname) !== true,
321
360
  renderFreshPageForCache: async ({ renderDocument }) => {
322
361
  const revalidationTarget = await resolveCacheRenderTarget();
323
- const revalidationDynamicConfig = options.resolveRouteDynamicConfig?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? dynamicConfig : void 0);
324
- const revalidationConfigRevalidateSeconds = options.resolveRouteRevalidateSeconds?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? currentRevalidateSeconds : null);
325
- const revalidationRouteRevalidateSeconds = revalidationTarget.route === route ? void 0 : revalidationConfigRevalidateSeconds ?? (revalidationDynamicConfig === "force-static" || revalidationDynamicConfig === "error" || options.isProduction && options.pprRuntime === void 0 && options.resolveRouteStaticEligible(revalidationTarget.route) ? Infinity : null);
362
+ const revalidationInterceptConfig = revalidationTarget.interceptOpts ? resolveAppPageInterceptSegmentConfig(revalidationTarget.route, revalidationTarget.interceptOpts) : null;
363
+ const revalidationDynamicConfig = revalidationInterceptConfig ? revalidationInterceptConfig.dynamicConfig : options.resolveRouteDynamicConfig?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? dynamicConfig : void 0);
364
+ const revalidationConfigRevalidateSeconds = revalidationInterceptConfig ? revalidationTarget.route === route ? currentRevalidateSeconds : revalidationInterceptConfig.revalidateSeconds : options.resolveRouteRevalidateSeconds?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? currentRevalidateSeconds : null);
365
+ const revalidationRouteRevalidateSeconds = revalidationTarget.route === route ? void 0 : revalidationConfigRevalidateSeconds ?? (revalidationDynamicConfig === "force-static" || revalidationDynamicConfig === "error" || options.isProduction && options.pprRuntime === void 0 && (revalidationInterceptConfig?.isStaticEligible ?? options.resolveRouteStaticEligible(revalidationTarget.route)) ? Infinity : null);
326
366
  const revalidationRouteHead = {
327
367
  observeSearchParams: revalidationDynamicConfig !== "force-static",
328
368
  searchParams: new URLSearchParams(),
@@ -332,7 +372,7 @@ async function dispatchAppPageInner(options) {
332
372
  return runAppPageRevalidationContext({
333
373
  cleanPathname: options.cleanPathname,
334
374
  displayPathname: options.displayPathname,
335
- currentFetchCacheMode: options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
375
+ currentFetchCacheMode: revalidationInterceptConfig ? revalidationInterceptConfig.fetchCacheMode : options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
336
376
  currentFetchRevalidate: revalidationConfigRevalidateSeconds,
337
377
  draftModeSecret: options.draftModeSecret,
338
378
  dynamicConfig: revalidationDynamicConfig,
@@ -459,6 +499,7 @@ async function dispatchAppPageInner(options) {
459
499
  isDynamicError,
460
500
  isForceDynamic,
461
501
  isForceStatic,
502
+ isPrerender,
462
503
  isProduction: options.isProduction,
463
504
  isProgressiveActionRender: options.isProgressiveActionRender === true,
464
505
  isRscRequest: options.isRscRequest,
@@ -475,9 +516,9 @@ async function dispatchAppPageInner(options) {
475
516
  }
476
517
  const fallbackShellResponse = options.pprRuntime ? await options.pprRuntime.tryServe(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) : null;
477
518
  if (fallbackShellResponse) return fallbackShellResponse;
478
- let interceptDynamicConfig;
479
- let interceptDynamicConfigResolved = false;
480
- let isInterceptSourceKnownDynamic = false;
519
+ let interceptConfig = null;
520
+ let isInterceptKnownDynamic = false;
521
+ let isInterceptRequestIndependent = false;
481
522
  const renderedRouteHead = {
482
523
  observeSearchParams: !isForceStatic,
483
524
  searchParams: pageSearchParams,
@@ -489,26 +530,27 @@ async function dispatchAppPageInner(options) {
489
530
  };
490
531
  const interceptResult = await resolveAppPageIntercept({
491
532
  async buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams) {
492
- const sourceDynamicConfig = interceptDynamicConfigResolved ? interceptDynamicConfig : options.resolveRouteDynamicConfig?.(interceptRoute);
493
- if (sourceDynamicConfig === "force-static" || sourceDynamicConfig === "error") {
533
+ interceptConfig ??= resolveAppPageInterceptSegmentConfig(interceptRoute, interceptOpts);
534
+ const interceptDynamicConfig = interceptConfig.dynamicConfig;
535
+ if (interceptDynamicConfig === "force-static" || interceptDynamicConfig === "error") {
494
536
  const { createStaticGenerationHeadersContext } = await import("./app-static-generation.js");
495
537
  setHeadersContext(createStaticGenerationHeadersContext({
496
538
  draftModeEnabled: isDraftMode,
497
539
  draftModeSecret: options.draftModeSecret,
498
- dynamicConfig: sourceDynamicConfig,
540
+ dynamicConfig: interceptDynamicConfig,
499
541
  routeKind: "page",
500
542
  routePattern: interceptRoute.pattern
501
543
  }));
502
544
  } else setHeadersContext(requestHeadersContext);
503
- const sourceRevalidateSeconds = options.resolveRouteRevalidateSeconds?.(interceptRoute) ?? null;
504
- isInterceptSourceKnownDynamic = sourceDynamicConfig === "force-dynamic" || sourceRevalidateSeconds === 0;
505
- setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(interceptRoute) ?? null);
506
- setCurrentFetchRevalidate(sourceRevalidateSeconds);
507
- setCurrentForceDynamicFetchDefault(sourceDynamicConfig === "force-dynamic");
545
+ isInterceptKnownDynamic = interceptDynamicConfig === "force-dynamic" || interceptConfig.revalidateSeconds === 0;
546
+ isInterceptRequestIndependent = interceptDynamicConfig === "force-static" || interceptDynamicConfig === "error";
547
+ setCurrentFetchCacheMode(interceptConfig.fetchCacheMode);
548
+ setCurrentFetchRevalidate(interceptConfig.revalidateSeconds);
549
+ setCurrentForceDynamicFetchDefault(interceptDynamicConfig === "force-dynamic");
508
550
  return options.buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, {
509
- isForceStatic: sourceDynamicConfig === "force-static",
510
- observeMetadataSearchParamsAccess: sourceDynamicConfig !== "force-static",
511
- observePageSearchParamsAccess: sourceDynamicConfig !== "force-static",
551
+ isForceStatic: interceptDynamicConfig === "force-static",
552
+ observeMetadataSearchParamsAccess: interceptDynamicConfig !== "force-static",
553
+ observePageSearchParamsAccess: interceptDynamicConfig !== "force-static",
512
554
  isUncacheableRender,
513
555
  serveStreamingMetadata: placeGeneratedMetadataInBody,
514
556
  placeStreamedMetadataInHead: options.renderWholeDocument === true,
@@ -526,18 +568,20 @@ async function dispatchAppPageInner(options) {
526
568
  getSourceRoute(sourceRouteIndex) {
527
569
  return options.getSourceRoute(sourceRouteIndex);
528
570
  },
571
+ interceptState: options.interceptState,
529
572
  isRscRequest: options.isRscRequest,
530
573
  resolveNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts) {
531
574
  return resolveAppPageNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts);
532
575
  },
533
- renderInterceptResponse(sourceRoute, interceptElement) {
576
+ renderInterceptResponse(sourceRoute, interceptElement, navigationParams) {
534
577
  const interceptOnError = options.createRscOnErrorHandler(options.cleanPathname, sourceRoute.pattern);
535
578
  const interceptStream = options.renderToReadableStream(interceptElement, { onError: interceptOnError });
536
579
  const interceptHeaders = new Headers({
537
580
  "Content-Type": VINEXT_RSC_CONTENT_TYPE,
538
581
  Vary: VINEXT_RSC_VARY_HEADER
539
582
  });
540
- if (!(options.pprRuntime !== void 0 || options.resolveRouteStaticEligible(sourceRoute)) || isDraftMode || isInterceptSourceKnownDynamic) interceptHeaders.set("Cache-Control", resolveUncacheableCacheControl(options.isProduction));
583
+ if (Object.keys(navigationParams).length > 0) interceptHeaders.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(navigationParams)));
584
+ if (!(options.pprRuntime !== void 0 || interceptConfig?.isStaticEligible === true) || isDraftMode || isInterceptKnownDynamic || options.isProduction && !isInterceptRequestIndependent) interceptHeaders.set("Cache-Control", resolveUncacheableCacheControl(options.isProduction));
541
585
  mergeMiddlewareResponseHeaders(interceptHeaders, options.middlewareContext.headers);
542
586
  applyRscCompatibilityIdHeader(interceptHeaders);
543
587
  applyRscDeploymentIdHeader(interceptHeaders);
@@ -546,11 +590,10 @@ async function dispatchAppPageInner(options) {
546
590
  headers: interceptHeaders
547
591
  });
548
592
  },
549
- async resolveSearchParams(sourceRoute, searchParams) {
593
+ async resolveSearchParams(sourceRoute, searchParams, interceptOpts) {
550
594
  await options.ensureRouteLoaded?.(sourceRoute);
551
- interceptDynamicConfig = options.resolveRouteDynamicConfig?.(sourceRoute);
552
- interceptDynamicConfigResolved = true;
553
- return interceptDynamicConfig === "force-static" ? new URLSearchParams() : searchParams;
595
+ interceptConfig = resolveAppPageInterceptSegmentConfig(sourceRoute, interceptOpts);
596
+ return interceptConfig.dynamicConfig === "force-static" ? new URLSearchParams() : searchParams;
554
597
  },
555
598
  searchParams: options.searchParams,
556
599
  setNavigationContext: options.setNavigationContext,
@@ -692,7 +735,6 @@ async function dispatchAppPageInner(options) {
692
735
  return renderPageSpecialError(options, specialError, serveStreamingMetadata, interceptResult.interceptOpts, renderOptions?.isCacheCandidate === true, renderOptions?.caughtDocument, renderedRouteHead);
693
736
  },
694
737
  renderToReadableStream: options.renderToReadableStream,
695
- hasCustomGlobalError: options.hasCustomGlobalError,
696
738
  prerenderToReadableStream: options.prerenderToReadableStream,
697
739
  routePattern: route.pattern,
698
740
  scriptNonce: options.scriptNonce,
@@ -116,24 +116,6 @@ export type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModu
116
116
  htmlLimitedBots?: string;
117
117
  scriptNonce?: string;
118
118
  };
119
- type AppPageNavigationParamModule = {
120
- default?: unknown;
121
- };
122
- type AppPageNavigationParamSlot = {
123
- default?: AppPageNavigationParamModule | null;
124
- page?: AppPageNavigationParamModule | null;
125
- slotPatternParts?: readonly string[] | null;
126
- slotParamNames?: readonly string[] | null;
127
- };
128
- type AppPageNavigationParamRoute = {
129
- params?: readonly string[] | null;
130
- slots?: Readonly<Record<string, AppPageNavigationParamSlot>> | null;
131
- };
132
- type AppPageNavigationParamInterceptOptions = {
133
- interceptPage?: unknown;
134
- interceptParams?: AppPageParams | null;
135
- interceptSlotKey?: string | null;
136
- };
137
119
  /**
138
120
  * Build the App Router element tree for a matched route.
139
121
  *
@@ -151,6 +133,15 @@ type AppPageNavigationParamInterceptOptions = {
151
133
  * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
152
134
  */
153
135
  export declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
136
+ /**
137
+ * The state key of each segment a sibling intercept's levels retain, from the
138
+ * app root down to the segment its element renders, so its Activity lists key
139
+ * like Next.js's for the intercepting route: the marker segment carries its
140
+ * marker, and a dynamic marker segment keys per value. The intercepting
141
+ * route's own layouts and boundaries render inside its page element, so the
142
+ * levels stop above the first of them.
143
+ */
144
+ export declare function resolveSiblingInterceptSegmentKeys(sourcePageSegments: readonly string[] | null | undefined, routeSegments: readonly string[] | null | undefined, opts: AppPageInterceptOptions | null | undefined, routeParams: AppPageParams, interceptParams: AppPageParams): readonly string[] | null;
154
145
  export declare const APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS: readonly [{
155
146
  readonly prefix: "(...)";
156
147
  readonly levels: number;
@@ -172,7 +163,5 @@ export declare const APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS: readonly [{
172
163
  */
173
164
  export declare function resolveInterceptedSlotIdentitySegments(sourcePageSegments: readonly string[] | null | undefined, slotKey: string): readonly AppPageSemanticSegment[] | null;
174
165
  export declare function resolveInterceptedSlotSegments(sourcePageSegments: readonly string[] | null | undefined, slotKey: string): readonly string[] | null;
175
- export declare function resolveSlotParamOverrides(route: AppPageNavigationParamRoute, routePath: string): Readonly<Record<string, AppPageParams>> | null;
176
- export declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
177
166
  //#endregion
178
167
  export type { AppPageErrorModule, AppPageRouteWiringRoute };
@@ -1,9 +1,8 @@
1
1
  import { isPromiseLike } from "../utils/promise.js";
2
2
  import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
3
- import { matchRoutePattern } from "../routing/route-pattern.js";
4
3
  import { AppElementsWire } from "./app-elements-wire.js";
5
4
  import "./app-elements.js";
6
- import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPagePatternStateKey, resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
5
+ import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPagePatternStateKey, resolveAppPageRouteStateKey, resolveAppPageSemanticSegmentStateKey } from "./app-page-segment-state.js";
7
6
  import { ErrorBoundary, ForbiddenBoundary, NotFoundBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
8
7
  import { withUseCacheLayoutMarker, withUseCachePageMarker } from "../shims/internal/app-page-props-cache-key.js";
9
8
  import { makeThenableParams } from "../shims/thenable-params.js";
@@ -12,15 +11,16 @@ import { createAppPageMetadataSearchParamsObserver, makeObservedAppPageSearchPar
12
11
  import { resolveAppPageBranchParams } from "./app-page-params.js";
13
12
  import { collectAppPageSearchParams, hasAppPageDynamicMetadata, prepareAppPageHead, resolveActiveParallelRouteHeadInputs, resolveInterceptLayoutsBesidePage, slotInterceptKeepsSourceHead } from "./app-page-head.js";
14
13
  import { createRouteNotFoundHeadPlanOptions, recoverAppPageRouteHead } from "./app-page-http-access-fallback-metadata.js";
15
- import { ClientPageRoot } from "../shims/client-page-root.js";
16
14
  import "./app-rsc-route-matching.js";
15
+ import { resolveSlotParamOverrides } from "./app-page-navigation-params.js";
17
16
  import { createAppPageRenderDependency, invokeAppComponent, isAppClientReference, isAppRenderSuspension, isReactOwnedAppComponent, renderAfterAppDependencies } from "./app-render-dependency.js";
18
17
  import { sanitizeErrorForClient } from "./app-rsc-errors.js";
19
18
  import { resolveAppPageModuleTraceSegment, traceCreateComponentTree, traceGetLayoutOrPageModule } from "./app-page-tracing.js";
20
19
  import { buildAppPageElements, createAppPageSourcePage, createAppPageTreePath, resolveAppPageLoadingModuleAtOrAbove } from "./app-page-route-wiring.js";
21
20
  import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
22
- import { createAppPageRenderIdentity } from "./app-page-render-identity.js";
23
21
  import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
22
+ import { ClientPageRoot } from "../shims/client-page-root.js";
23
+ import { createAppPageRenderIdentity } from "./app-page-render-identity.js";
24
24
  import { Fragment, Suspense, cache, createElement } from "react";
25
25
  //#region src/server/app-page-element-builder.ts
26
26
  /**
@@ -429,6 +429,7 @@ async function buildPageElements(options) {
429
429
  routePath,
430
430
  semanticPageIdentity,
431
431
  semanticInterceptionTargetRouteId: opts?.interceptTargetRouteGraphId ?? null,
432
+ siblingInterceptSegmentKeys: isSiblingIntercept ? resolveSiblingInterceptSegmentKeys(sourcePageSegments, route.routeSegments, opts, params, effectiveParams) : null,
432
433
  sourcePageSegments,
433
434
  rootNotFoundModule: rootNotFoundModule ?? null,
434
435
  rootForbiddenModule: rootForbiddenModule ?? null,
@@ -451,9 +452,9 @@ async function buildPageElements(options) {
451
452
  * slot-scoped params, which `app-page-route-wiring` then hands to the
452
453
  * slot page instead of the route's matched params.
453
454
  *
454
- * `routePath` is the already-normalized request pathname (basePath stripped,
455
- * RSC suffix removed). Re-parsing `request.url` here would re-introduce the
456
- * basePath and silently break the match for any app that configures one.
455
+ * `routePath` is the already-normalized request pathname (basePath stripped).
456
+ * Re-parsing `request.url` here would re-introduce the basePath and silently
457
+ * break the match for any app that configures one.
457
458
  */
458
459
  function buildSlotOverrides(route, routeParams, routePath, opts, interceptMetadataOutlet) {
459
460
  const overrides = {};
@@ -487,6 +488,37 @@ function buildSlotOverrides(route, routeParams, routePath, opts, interceptMetada
487
488
  }
488
489
  return Object.keys(overrides).length > 0 ? overrides : null;
489
490
  }
491
+ /**
492
+ * The state key of each segment a sibling intercept's levels retain, from the
493
+ * app root down to the segment its element renders, so its Activity lists key
494
+ * like Next.js's for the intercepting route: the marker segment carries its
495
+ * marker, and a dynamic marker segment keys per value. The intercepting
496
+ * route's own layouts and boundaries render inside its page element, so the
497
+ * levels stop above the first of them.
498
+ */
499
+ function resolveSiblingInterceptSegmentKeys(sourcePageSegments, routeSegments, opts, routeParams, interceptParams) {
500
+ if (!sourcePageSegments || !routeSegments) return null;
501
+ const markerIndex = sourcePageSegments.findIndex((segment) => APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS.some(({ prefix }) => segment.startsWith(prefix)));
502
+ if (markerIndex < 0) return null;
503
+ if (routeSegments.length !== markerIndex || routeSegments.some((segment, index) => segment !== sourcePageSegments[index])) return null;
504
+ const branchTreePositions = [
505
+ ...(opts?.interceptLayouts ?? []).flatMap((layoutModule, index) => layoutModule?.default ? [opts?.interceptLayoutSegments?.[index]?.length ?? 0] : []),
506
+ ...opts?.interceptLoadingTreePositions ?? [],
507
+ ...opts?.interceptNotFoundTreePositions ?? [],
508
+ ...opts?.interceptForbiddenTreePositions ?? [],
509
+ ...opts?.interceptUnauthorizedTreePositions ?? [],
510
+ ...opts?.interceptErrorTreePositions ?? []
511
+ ];
512
+ const segmentCount = Math.max(markerIndex, Math.min(sourcePageSegments.length, markerIndex + Math.min(...branchTreePositions) - 1));
513
+ return sourcePageSegments.slice(0, segmentCount).map((segment, index) => {
514
+ const marker = index === markerIndex ? APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS.find(({ prefix }) => segment.startsWith(prefix)) : void 0;
515
+ return resolveAppPageSemanticSegmentStateKey({
516
+ marker: marker?.prefix ?? null,
517
+ paramSource: "route",
518
+ segment: marker ? segment.slice(marker.prefix.length) : segment
519
+ }, index < markerIndex ? routeParams : interceptParams);
520
+ });
521
+ }
490
522
  const APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS = [
491
523
  {
492
524
  prefix: "(...)",
@@ -581,49 +613,5 @@ function resolveInterceptedSlotSegments(sourcePageSegments, slotKey) {
581
613
  routeSegments.push(...sourcePageSegments.slice(markerIndex + 1).filter(isVisibleInterceptedSlotSegment));
582
614
  return routeSegments;
583
615
  }
584
- function resolveSlotParamOverrides(route, routePath) {
585
- const overrides = {};
586
- const slots = route.slots;
587
- if (slots) {
588
- let urlParts = null;
589
- const routeParamSet = collectParamNameSet(route.params);
590
- for (const [slotKey, slot] of Object.entries(slots)) {
591
- const patternParts = slot.slotPatternParts;
592
- const paramNames = slot.slotParamNames;
593
- if (!patternParts || patternParts.length === 0) continue;
594
- if (paramNames && paramNames.every((name) => routeParamSet.has(name))) continue;
595
- if (urlParts === null) urlParts = routePath.split("/").filter(Boolean);
596
- const matched = matchRoutePattern(urlParts, patternParts);
597
- if (!matched) continue;
598
- overrides[slotKey] = matched;
599
- }
600
- }
601
- return Object.keys(overrides).length > 0 ? overrides : null;
602
- }
603
- function mergeAppPageParams(target, source) {
604
- for (const [key, value] of Object.entries(source)) target[key] = value;
605
- }
606
- function isDefaultExportModule(module) {
607
- return typeof module === "object" && module !== null;
608
- }
609
- function hasDefaultExport(module) {
610
- if (!isDefaultExportModule(module)) return false;
611
- return module?.default !== null && module?.default !== void 0;
612
- }
613
- function resolveAppPageNavigationParams(route, routeParams, routePath, opts) {
614
- const navigationParams = { ...routeParams };
615
- const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
616
- for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
617
- const isInterceptedSlot = opts?.interceptSlotKey === slotKey && opts.interceptSlotKey !== "__vinext_page_intercept" && hasDefaultExport(opts.interceptPage);
618
- if (!isInterceptedSlot && !hasDefaultExport(slot.page) && !hasDefaultExport(slot.default)) continue;
619
- mergeAppPageParams(navigationParams, isInterceptedSlot ? opts?.interceptParams ?? routeParams : slotParamOverrides?.[slotKey] ?? routeParams);
620
- }
621
- return navigationParams;
622
- }
623
- function collectParamNameSet(params) {
624
- const set = /* @__PURE__ */ new Set();
625
- if (params) for (const name of params) set.add(name);
626
- return set;
627
- }
628
616
  //#endregion
629
- export { APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS, buildPageElements, resolveAppPageNavigationParams, resolveInterceptedSlotIdentitySegments, resolveInterceptedSlotSegments, resolveSlotParamOverrides };
617
+ export { APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS, buildPageElements, resolveInterceptedSlotIdentitySegments, resolveInterceptedSlotSegments, resolveSiblingInterceptSegmentKeys };
@@ -1,7 +1,7 @@
1
1
  import { VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER } from "./headers.js";
2
2
  import { copyLinkHeaderProvenance, getFrameworkLinkHeader, markFrameworkLinkHeaders } from "./app-response-header-provenance.js";
3
3
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
4
- import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, createRscRedirectLocation } from "./app-rsc-cache-busting.js";
4
+ import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, createRscRedirectLocation, toPathAbsolutePathname } from "./app-rsc-cache-busting.js";
5
5
  import { isHTTPAccessFallbackError, isThrownNavigationError } from "../shims/navigation-errors.js";
6
6
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
7
7
  import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
@@ -298,9 +298,11 @@ function toHeaderSafeUrlReference(location) {
298
298
  * header-safe, so a protocol-relative or scheme-relative target still resolves
299
299
  * against the page each client fetched. A relative target resolves against the
300
300
  * request's path to a path-only form, which the client resolves against its
301
- * own origin. Resolving against two placeholder origins tells these apart the
302
- * way the URL parser does, never depends on the request's origin, and cannot
303
- * mistake an absolute target naming one placeholder for a relative one.
301
+ * own origin; a resolved pathname that begins with "//" keeps a "/." prefix
302
+ * so that form stays a path rather than naming another host. Resolving
303
+ * against two placeholder origins tells these apart the way the URL parser
304
+ * does, never depends on the request's origin, and cannot mistake an absolute
305
+ * target naming one placeholder for a relative one.
304
306
  */
305
307
  function resolveRedirectTargets(location, requestUrl) {
306
308
  try {
@@ -310,9 +312,10 @@ function resolveRedirectTargets(location, requestUrl) {
310
312
  headerUrl: toHeaderSafeUrlReference(location)
311
313
  };
312
314
  const { pathname, search, hash } = first.resolved;
315
+ const target = `${toPathAbsolutePathname(pathname)}${search}${hash}`;
313
316
  return {
314
- digestUrl: `${pathname}${search}${hash}`,
315
- headerUrl: `${pathname}${search}${hash}`
317
+ digestUrl: target,
318
+ headerUrl: target
316
319
  };
317
320
  } catch {
318
321
  return {
@@ -0,0 +1,56 @@
1
+ import { FetchCacheMode } from "../shims/fetch-cache-state.js";
2
+ import "../shims/fetch-cache.js";
3
+ //#region src/server/app-page-intercept-segment-config.d.ts
4
+ type SegmentModule = Record<string, unknown>;
5
+ type AppPageInterceptSegmentConfigSlot = {
6
+ configLayouts?: readonly (SegmentModule | null | undefined)[] | null;
7
+ configLayoutTreePositions?: readonly number[] | null;
8
+ default?: SegmentModule | null;
9
+ layout?: SegmentModule | null;
10
+ layoutIndex?: number;
11
+ name?: string;
12
+ ownerTreePosition?: number | null;
13
+ page?: SegmentModule | null;
14
+ routeSegments?: readonly string[] | null;
15
+ };
16
+ /** The parts of the route an interception renders under that its config reads. */
17
+ export type AppPageInterceptSegmentConfigRoute = {
18
+ layouts?: readonly (SegmentModule | null | undefined)[];
19
+ layoutTreePositions?: readonly number[];
20
+ routeSegments?: readonly string[];
21
+ slots?: Readonly<Record<string, AppPageInterceptSegmentConfigSlot>> | null;
22
+ };
23
+ /** The parts of the interception's options its config reads. */
24
+ export type AppPageInterceptSegmentConfigOptions = {
25
+ interceptBranchSegments?: readonly string[] | null;
26
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
27
+ interceptLayouts?: readonly unknown[] | null;
28
+ interceptPage?: unknown;
29
+ interceptSlotKey: string;
30
+ interceptSourcePageSegments?: readonly string[] | null;
31
+ };
32
+ export type AppPageInterceptSegmentConfig = {
33
+ dynamicConfig: string | undefined;
34
+ dynamicStaleTimeSeconds: number | undefined;
35
+ fetchCacheMode: FetchCacheMode | null;
36
+ /** Whether any segment of the interception exports `generateStaticParams`. */
37
+ hasAnyGenerateStaticParams: boolean;
38
+ /** Whether one sits at or below the interception's last dynamic segment. */
39
+ hasGenerateStaticParams: boolean;
40
+ /** Whether the interception's own segments choose the edge runtime. */
41
+ isEdgeRuntime: boolean;
42
+ isStaticEligible: boolean;
43
+ isStaticGenerationEdgeRuntime: boolean;
44
+ revalidateSeconds: number | null;
45
+ };
46
+ /**
47
+ * Next.js renders an interception as its own route, whose loader tree holds
48
+ * the owner's layouts and the intercepting page, never the source's page, so
49
+ * its segment config comes from those modules alone. A sibling intercept's
50
+ * branch takes the children position below its owner folder; a slot
51
+ * intercept's branch takes its slot, beside the other slots of the owner's
52
+ * layouts, and children renders the owner's default.
53
+ */
54
+ export declare function resolveAppPageInterceptSegmentConfig(route: AppPageInterceptSegmentConfigRoute, interceptOpts: AppPageInterceptSegmentConfigOptions): AppPageInterceptSegmentConfig;
55
+ //#endregion
56
+ export {};
@@ -0,0 +1,90 @@
1
+ import { collectAppPageStaticGenerationRuntimes, collectAppPageStaticParamsWalkSegments, hasAppPageGenerateStaticParamsAtLastDynamicSegment, isAppPageStaticEligible, isEdgeRuntime, resolveAppPageSegmentConfig, resolveAppPageStaticGenerationRuntime } from "./app-segment-config.js";
2
+ import { SIBLING_PAGE_INTERCEPT_SLOT_KEY } from "./app-rsc-route-matching.js";
3
+ //#region src/server/app-page-intercept-segment-config.ts
4
+ /**
5
+ * Next.js renders an interception as its own route, whose loader tree holds
6
+ * the owner's layouts and the intercepting page, never the source's page, so
7
+ * its segment config comes from those modules alone. A sibling intercept's
8
+ * branch takes the children position below its owner folder; a slot
9
+ * intercept's branch takes its slot, beside the other slots of the owner's
10
+ * layouts, and children renders the owner's default.
11
+ */
12
+ function resolveAppPageInterceptSegmentConfig(route, interceptOpts) {
13
+ const routeLayouts = route.layouts ?? [];
14
+ const routeSegments = route.routeSegments ?? [];
15
+ const isSiblingIntercept = interceptOpts.interceptSlotKey === SIBLING_PAGE_INTERCEPT_SLOT_KEY;
16
+ const interceptedSlot = isSiblingIntercept ? void 0 : route.slots?.[interceptOpts.interceptSlotKey];
17
+ const branchSegments = interceptOpts.interceptBranchSegments ?? [];
18
+ const interceptLayouts = interceptOpts.interceptLayouts ?? [];
19
+ const interceptLayoutPositions = (interceptOpts.interceptLayoutSegments ?? []).map((segments) => segments.length);
20
+ const ownerPosition = isSiblingIntercept ? interceptOpts.interceptSourcePageSegments ? interceptOpts.interceptSourcePageSegments.length - branchSegments.length : routeSegments.length : interceptedSlot?.ownerTreePosition ?? route.layoutTreePositions?.[interceptedSlot?.layoutIndex ?? -1] ?? routeSegments.length;
21
+ const ownerLayoutIndexes = routeLayouts.flatMap((_, index) => (route.layoutTreePositions?.[index] ?? 0) <= ownerPosition ? [index] : []);
22
+ const ownerLayouts = ownerLayoutIndexes.map((index) => routeLayouts[index]);
23
+ const ownerLayoutPositions = ownerLayoutIndexes.map((index) => route.layoutTreePositions?.[index] ?? 0);
24
+ const ownerSegments = routeSegments.slice(0, ownerPosition);
25
+ const page = interceptOpts.interceptPage;
26
+ const retainedBranches = Object.entries(route.slots ?? {}).flatMap(([slotKey, slot]) => slotKey !== interceptOpts.interceptSlotKey && (slot.ownerTreePosition ?? route.layoutTreePositions?.[slot.layoutIndex ?? 0] ?? 0) <= ownerPosition ? [{
27
+ configLayouts: slot.page ? slot.configLayouts : null,
28
+ configLayoutTreePositions: slot.page ? slot.configLayoutTreePositions : null,
29
+ isDefault: !slot.page,
30
+ layout: slot.page ? slot.layout : null,
31
+ name: slot.name,
32
+ ownerTreePosition: slot.ownerTreePosition,
33
+ page: slot.page ?? slot.default,
34
+ routeSegments: slot.routeSegments
35
+ }] : []);
36
+ const tree = isSiblingIntercept ? {
37
+ layouts: [...ownerLayouts, ...interceptLayouts],
38
+ layoutTreePositions: [...ownerLayoutPositions, ...interceptLayoutPositions.map((position) => ownerPosition + position)],
39
+ page,
40
+ parallelBranches: retainedBranches,
41
+ routeSegments: [...ownerSegments, ...branchSegments]
42
+ } : {
43
+ layouts: ownerLayouts,
44
+ layoutTreePositions: ownerLayoutPositions,
45
+ page: null,
46
+ parallelBranches: [...retainedBranches, {
47
+ configLayouts: interceptLayouts,
48
+ configLayoutTreePositions: interceptLayoutPositions,
49
+ layout: interceptedSlot?.layout,
50
+ name: interceptedSlot?.name,
51
+ ownerTreePosition: ownerPosition,
52
+ page,
53
+ routeSegments: branchSegments
54
+ }],
55
+ routeSegments: ownerSegments
56
+ };
57
+ const config = resolveAppPageSegmentConfig({
58
+ layouts: [
59
+ ...ownerLayouts,
60
+ ...isSiblingIntercept ? [] : [interceptedSlot?.layout],
61
+ ...interceptLayouts
62
+ ],
63
+ page,
64
+ parallelBranches: retainedBranches,
65
+ parallelPages: retainedBranches.map((branch) => branch.page)
66
+ });
67
+ const walkSegments = collectAppPageStaticParamsWalkSegments(tree);
68
+ const hasGenerateStaticParams = hasAppPageGenerateStaticParamsAtLastDynamicSegment(tree);
69
+ const isDynamicRoute = walkSegments.some((segment) => segment.dynamic);
70
+ const isStaticGenerationEdgeRuntime = isEdgeRuntime(resolveAppPageStaticGenerationRuntime(collectAppPageStaticGenerationRuntimes(tree)));
71
+ return {
72
+ dynamicConfig: config.dynamicConfig,
73
+ dynamicStaleTimeSeconds: config.dynamicStaleTimeSeconds,
74
+ fetchCacheMode: config.fetchCache ?? null,
75
+ hasAnyGenerateStaticParams: walkSegments.some((segment) => segment.generateStaticParams),
76
+ hasGenerateStaticParams,
77
+ isEdgeRuntime: isEdgeRuntime(config.runtime),
78
+ isStaticEligible: isAppPageStaticEligible({
79
+ dynamicConfig: config.dynamicConfig,
80
+ hasGenerateStaticParams,
81
+ isDynamicRoute,
82
+ isStaticGenerationEdgeRuntime,
83
+ revalidateSeconds: config.revalidateSeconds
84
+ }),
85
+ isStaticGenerationEdgeRuntime,
86
+ revalidateSeconds: config.revalidateSeconds
87
+ };
88
+ }
89
+ //#endregion
90
+ export { resolveAppPageInterceptSegmentConfig };
@@ -0,0 +1,23 @@
1
+ import { AppPageParams } from "./app-page-boundary.js";
2
+ //#region src/server/app-page-navigation-params.d.ts
3
+ export type AppPageNavigationParamSlot = {
4
+ __loadDefault?: unknown;
5
+ __loadPage?: unknown;
6
+ default?: unknown;
7
+ page?: unknown;
8
+ slotPatternParts?: readonly string[] | null;
9
+ slotParamNames?: readonly string[] | null;
10
+ };
11
+ type AppPageNavigationParamRoute = {
12
+ params?: readonly string[] | null;
13
+ slots?: Readonly<Record<string, AppPageNavigationParamSlot>> | null;
14
+ };
15
+ type AppPageNavigationParamInterceptOptions = {
16
+ interceptPage?: unknown;
17
+ interceptParams?: AppPageParams | null;
18
+ interceptSlotKey?: string | null;
19
+ };
20
+ export declare function resolveSlotParamOverrides(route: AppPageNavigationParamRoute, routePath: string): Readonly<Record<string, AppPageParams>> | null;
21
+ export declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
22
+ //#endregion
23
+ export {};