vinext 1.0.0-beta.1 → 1.0.0-beta.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 (175) hide show
  1. package/README.md +4 -1
  2. package/dist/build/client-build-config.js +1 -0
  3. package/dist/build/report.d.ts +8 -1
  4. package/dist/build/report.js +12 -2
  5. package/dist/check.js +15 -2
  6. package/dist/cli.js +3 -2
  7. package/dist/config/config-matchers.d.ts +13 -37
  8. package/dist/config/config-matchers.js +31 -121
  9. package/dist/config/next-config.d.ts +3 -2
  10. package/dist/config/next-config.js +3 -1
  11. package/dist/config/request-context.d.ts +14 -0
  12. package/dist/config/request-context.js +26 -0
  13. package/dist/entries/app-rsc-entry.js +27 -9
  14. package/dist/entries/app-rsc-manifest.js +17 -0
  15. package/dist/entries/pages-server-entry.js +3 -2
  16. package/dist/index.js +82 -58
  17. package/dist/init.d.ts +6 -4
  18. package/dist/init.js +20 -22
  19. package/dist/plugins/og-assets.js +1 -1
  20. package/dist/routing/app-route-graph.d.ts +13 -5
  21. package/dist/routing/app-route-graph.js +59 -13
  22. package/dist/routing/app-router.js +12 -6
  23. package/dist/routing/file-matcher.d.ts +11 -22
  24. package/dist/routing/file-matcher.js +21 -33
  25. package/dist/routing/pages-router.js +23 -29
  26. package/dist/routing/route-matching.d.ts +14 -1
  27. package/dist/routing/route-matching.js +13 -1
  28. package/dist/routing/route-pattern.d.ts +2 -1
  29. package/dist/routing/route-pattern.js +7 -4
  30. package/dist/routing/route-trie.d.ts +5 -1
  31. package/dist/routing/route-trie.js +5 -2
  32. package/dist/server/app-browser-entry.js +7 -6
  33. package/dist/server/app-browser-history-controller.d.ts +1 -1
  34. package/dist/server/app-browser-history-controller.js +3 -3
  35. package/dist/server/app-browser-navigation-controller.js +1 -1
  36. package/dist/server/app-browser-state.js +1 -1
  37. package/dist/server/app-browser-visible-commit.js +1 -1
  38. package/dist/server/app-fallback-renderer.d.ts +3 -0
  39. package/dist/server/app-fallback-renderer.js +4 -2
  40. package/dist/server/app-middleware.js +2 -1
  41. package/dist/server/app-page-boundary-render.d.ts +12 -1
  42. package/dist/server/app-page-boundary-render.js +84 -2
  43. package/dist/server/app-page-cache-finalizer.d.ts +1 -1
  44. package/dist/server/app-page-cache.d.ts +1 -1
  45. package/dist/server/app-page-dispatch.d.ts +11 -2
  46. package/dist/server/app-page-dispatch.js +14 -17
  47. package/dist/server/app-page-element-builder.d.ts +7 -2
  48. package/dist/server/app-page-element-builder.js +112 -27
  49. package/dist/server/app-page-head.d.ts +54 -2
  50. package/dist/server/app-page-head.js +164 -78
  51. package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
  52. package/dist/server/app-page-http-access-fallback-metadata.js +106 -0
  53. package/dist/server/app-page-render.d.ts +2 -2
  54. package/dist/server/app-page-render.js +1 -1
  55. package/dist/server/app-page-request.d.ts +12 -0
  56. package/dist/server/app-page-request.js +133 -13
  57. package/dist/server/app-page-route-wiring.d.ts +9 -0
  58. package/dist/server/app-page-route-wiring.js +43 -3
  59. package/dist/server/app-post-middleware-context.d.ts +1 -1
  60. package/dist/server/app-post-middleware-context.js +1 -1
  61. package/dist/server/app-route-handler-dispatch.js +31 -17
  62. package/dist/server/app-route-handler-execution.d.ts +6 -1
  63. package/dist/server/app-route-handler-execution.js +42 -16
  64. package/dist/server/app-route-handler-policy.d.ts +2 -0
  65. package/dist/server/app-route-handler-policy.js +3 -3
  66. package/dist/server/app-route-module-loader.d.ts +3 -1
  67. package/dist/server/app-route-module-loader.js +1 -0
  68. package/dist/server/app-rsc-cache-busting.d.ts +1 -1
  69. package/dist/server/app-rsc-errors.d.ts +1 -1
  70. package/dist/server/app-rsc-errors.js +12 -2
  71. package/dist/server/app-rsc-handler.d.ts +10 -5
  72. package/dist/server/app-rsc-handler.js +52 -24
  73. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  74. package/dist/server/app-rsc-request-normalization.js +8 -2
  75. package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
  76. package/dist/server/app-rsc-response-finalizer.js +5 -11
  77. package/dist/server/app-rsc-route-matching.d.ts +20 -0
  78. package/dist/server/app-rsc-route-matching.js +87 -11
  79. package/dist/server/app-segment-config.js +13 -3
  80. package/dist/server/app-server-action-execution.d.ts +3 -1
  81. package/dist/server/app-server-action-execution.js +9 -7
  82. package/dist/server/app-ssr-entry.js +2 -2
  83. package/dist/server/app-ssr-stream.d.ts +1 -7
  84. package/dist/server/app-ssr-stream.js +2 -10
  85. package/dist/server/config-headers.d.ts +24 -0
  86. package/dist/server/config-headers.js +52 -0
  87. package/dist/server/dev-initial-server-error.d.ts +1 -1
  88. package/dist/server/dev-server.js +29 -13
  89. package/dist/server/isr-cache.d.ts +1 -1
  90. package/dist/server/middleware-matcher-pattern.d.ts +22 -0
  91. package/dist/server/middleware-matcher-pattern.js +219 -0
  92. package/dist/server/middleware-matcher.d.ts +2 -7
  93. package/dist/server/middleware-matcher.js +13 -60
  94. package/dist/server/middleware-path-to-regexp.d.ts +14 -0
  95. package/dist/server/middleware-path-to-regexp.js +228 -0
  96. package/dist/server/middleware-runtime.js +4 -3
  97. package/dist/server/middleware.d.ts +1 -1
  98. package/dist/server/middleware.js +2 -1
  99. package/dist/server/pages-data-route.d.ts +11 -1
  100. package/dist/server/pages-data-route.js +16 -1
  101. package/dist/server/pages-get-initial-props.d.ts +15 -2
  102. package/dist/server/pages-get-initial-props.js +16 -6
  103. package/dist/server/pages-page-data.d.ts +3 -1
  104. package/dist/server/pages-page-data.js +16 -7
  105. package/dist/server/pages-page-handler.d.ts +4 -2
  106. package/dist/server/pages-page-handler.js +16 -17
  107. package/dist/server/pages-page-response.js +1 -1
  108. package/dist/server/pages-readiness.d.ts +3 -3
  109. package/dist/server/pages-request-pipeline.d.ts +1 -0
  110. package/dist/server/pages-request-pipeline.js +25 -11
  111. package/dist/server/pages-router-entry.js +6 -0
  112. package/dist/server/prerender-route-params.js +2 -2
  113. package/dist/server/prod-server.d.ts +1 -4
  114. package/dist/server/prod-server.js +36 -23
  115. package/dist/server/request-pipeline.d.ts +15 -29
  116. package/dist/server/request-pipeline.js +24 -59
  117. package/dist/server/rsc-stream-hints.js +122 -18
  118. package/dist/shims/app.d.ts +1 -1
  119. package/dist/shims/cache-request-state.d.ts +27 -1
  120. package/dist/shims/cache-request-state.js +60 -1
  121. package/dist/shims/cache-runtime.d.ts +12 -1
  122. package/dist/shims/cache-runtime.js +22 -7
  123. package/dist/shims/cache.d.ts +5 -5
  124. package/dist/shims/cache.js +26 -10
  125. package/dist/shims/document.d.ts +42 -83
  126. package/dist/shims/document.js +62 -53
  127. package/dist/shims/dynamic.d.ts +5 -25
  128. package/dist/shims/dynamic.js +29 -8
  129. package/dist/shims/error.d.ts +1 -1
  130. package/dist/shims/error.js +1 -1
  131. package/dist/shims/fetch-cache.js +12 -3
  132. package/dist/shims/font-google-base.d.ts +11 -4
  133. package/dist/shims/font-local.d.ts +10 -3
  134. package/dist/shims/head.d.ts +13 -2
  135. package/dist/shims/head.js +3 -3
  136. package/dist/shims/headers.d.ts +28 -31
  137. package/dist/shims/headers.js +109 -49
  138. package/dist/shims/image.d.ts +27 -37
  139. package/dist/shims/image.js +21 -14
  140. package/dist/shims/internal/cookie-serialize.d.ts +3 -1
  141. package/dist/shims/internal/cookie-serialize.js +3 -1
  142. package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
  143. package/dist/shims/internal/utils.d.ts +3 -3
  144. package/dist/shims/legacy-image.d.ts +3 -37
  145. package/dist/shims/legacy-image.js +6 -16
  146. package/dist/shims/link.d.ts +15 -22
  147. package/dist/shims/link.js +20 -11
  148. package/dist/shims/navigation-context-state.d.ts +1 -1
  149. package/dist/shims/navigation.d.ts +7 -3
  150. package/dist/shims/navigation.js +24 -13
  151. package/dist/shims/navigation.react-server.js +1 -1
  152. package/dist/shims/next-shims-augmentations.d.ts +1 -0
  153. package/dist/shims/next-shims-public.d.ts +1 -0
  154. package/dist/shims/public-shim-map.json.js +103 -0
  155. package/dist/shims/readonly-url-search-params.d.ts +3 -3
  156. package/dist/shims/readonly-url-search-params.js +3 -3
  157. package/dist/shims/request-state-types.d.ts +1 -1
  158. package/dist/shims/router.d.ts +55 -21
  159. package/dist/shims/router.js +162 -37
  160. package/dist/shims/script.d.ts +6 -10
  161. package/dist/shims/script.js +6 -3
  162. package/dist/shims/server.d.ts +45 -22
  163. package/dist/shims/server.js +44 -5
  164. package/dist/shims/unified-request-context.d.ts +1 -1
  165. package/dist/shims/unified-request-context.js +2 -0
  166. package/dist/shims/url-safety.d.ts +1 -1
  167. package/dist/shims/url-safety.js +2 -2
  168. package/dist/typegen.d.ts +8 -2
  169. package/dist/typegen.js +76 -15
  170. package/dist/utils/domain-locale.d.ts +2 -2
  171. package/dist/utils/external-url.d.ts +5 -0
  172. package/dist/utils/external-url.js +7 -0
  173. package/dist/utils/regex-safety.d.ts +8 -0
  174. package/dist/utils/regex-safety.js +737 -0
  175. package/package.json +13 -2
@@ -16,16 +16,15 @@ import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscR
16
16
  import { getNavigationRuntime, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
17
17
  import { notifyAppRouterTransitionStart } from "../client/instrumentation-client-state.js";
18
18
  import "../client/instrumentation-client.js";
19
+ import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
20
+ import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, resolveServerActionOperationLane } from "./app-browser-action-result.js";
21
+ import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
19
22
  import { resolveManifestNavigationInterceptionContext, resolveMiddlewareRewriteNavigationInterceptionContext } from "./app-browser-interception-context.js";
20
23
  import { readHistoryStatePreviousNextUrl } from "./app-history-state.js";
21
24
  import { AppBrowserMpaNavigationScheduler } from "./app-browser-mpa-navigation.js";
22
25
  import { blockDangerousStreamedRscRedirect } from "./app-browser-rsc-redirect.js";
23
26
  import { navigationPlanner } from "./navigation-planner.js";
24
- import { resolveHybridClientRewriteHref } from "../shims/internal/hybrid-client-route-owner.js";
25
- import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
26
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
27
- import { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, resolveServerActionOperationLane } from "./app-browser-action-result.js";
28
- import { createClientReuseManifestHeaderFromVisibleAppState } from "./app-browser-client-reuse-manifest.js";
27
+ import { DYNAMIC_NAVIGATION_CACHE_TTL, PREFETCH_CACHE_TTL, __basePath, appRouterInstance, commitClientNavigationState, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, deletePrefetchResponseSnapshot, getClientNavigationRenderContext, getMountedSlotsHeader, getPrefetchCache, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, preloadHybridClientRouteOwner, pushHistoryStateWithoutNotify, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveLoadedHybridClientRewriteHref, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setPendingPathname, useRouter } from "../shims/navigation.js";
29
28
  import { chunksToReadableStream, createProgressiveRscStream, getVinextBrowserGlobal } from "./app-browser-stream.js";
30
29
  import { COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, VISITED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, isCacheRestorableAppPayloadMetadata, isCompleteAppPayloadMetadata, resolveInterceptionContextFromPreviousNextUrl } from "./app-browser-state.js";
31
30
  import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch } from "./app-browser-navigation-controller.js";
@@ -43,6 +42,7 @@ import { createRoot, hydrateRoot } from "react-dom/client";
43
42
  import { createFromFetch, createFromReadableStream, setServerCallback } from "@vitejs/plugin-rsc/browser";
44
43
  import { hasServerActions, loadServerActionClient } from "virtual:vinext-app-capabilities";
45
44
  //#region src/server/app-browser-entry.ts
45
+ const HAS_CLIENT_REWRITES = process.env.__VINEXT_HAS_CLIENT_REWRITES !== "false";
46
46
  function toActionType(kind) {
47
47
  return kind === "traverse" ? "traverse" : "navigate";
48
48
  }
@@ -738,6 +738,7 @@ async function main() {
738
738
  if (!claimInitialAppRouterBootstrap()) return;
739
739
  if (hasServerActions) registerServerActionCallback();
740
740
  installAppNavigationFailureListeners();
741
+ if (HAS_CLIENT_REWRITES) await preloadHybridClientRouteOwner();
741
742
  let devErrorOverlay = null;
742
743
  if (import.meta.env.DEV) {
743
744
  devErrorOverlay = await import("../client/dev-error-overlay.js");
@@ -892,7 +893,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
892
893
  mountedSlotsHeader
893
894
  });
894
895
  const rscUrl = await createRscRequestUrl(url.pathname + url.search, requestHeaders);
895
- const rewrittenNavigationHref = navigationKind === "navigate" ? resolveHybridClientRewriteHref(currentHref, __basePath) : null;
896
+ const rewrittenNavigationHref = navigationKind === "navigate" && HAS_CLIENT_REWRITES ? resolveLoadedHybridClientRewriteHref(currentHref, __basePath) : null;
896
897
  const additionalPrefetchRscUrls = rewrittenNavigationHref && rewrittenNavigationHref !== currentHref ? [await createRscRequestUrl(rewrittenNavigationHref, requestHeaders)] : [];
897
898
  const visitedResponseCandidate = shouldBypassNavigationCache ? {
898
899
  cacheKey: AppElementsWire.encodeCacheKey(rscUrl, requestInterceptionContext),
@@ -18,7 +18,7 @@ type AppBrowserHistoryControllerDeps = {
18
18
  readHistoryState: () => unknown; /** Reads `window.location.href`. Injected so the controller stays unit-testable. */
19
19
  readCurrentHref: () => string; /** Wraps `pushHistoryStateWithoutNotify(state, "", href)`. */
20
20
  pushHistoryState: (state: unknown, href: string) => void; /** Wraps `replaceHistoryStateWithoutNotify(state, "", href)`. */
21
- replaceHistoryState: (state: unknown, href: string) => void;
21
+ replaceHistoryState: (state: unknown, href?: string) => void;
22
22
  readVisibleNavigationMetadata: () => VisibleNavigationMetadata | null;
23
23
  };
24
24
  /**
@@ -158,9 +158,9 @@ var AppBrowserHistoryController = class {
158
158
  bfcacheVersion: bfcacheIds === void 0 ? void 0 : this.#restorableClientState.currentBfcacheVersion,
159
159
  previousNextUrl
160
160
  });
161
- this.#replaceHistoryState(nextHistoryState, this.#readCurrentHref());
161
+ this.#replaceHistoryState(nextHistoryState);
162
162
  if (this.#isHistoryStateNavigationMetadataInSync(this.#readHistoryState(), previousNextUrl, bfcacheIds)) return;
163
- this.#replaceHistoryState(nextHistoryState, this.#readCurrentHref());
163
+ this.#replaceHistoryState(nextHistoryState);
164
164
  }
165
165
  #isHistoryStateNavigationMetadataInSync(state, previousNextUrl, bfcacheIds) {
166
166
  return readHistoryStatePreviousNextUrl(state) === previousNextUrl && (bfcacheIds === void 0 || areBfcacheIdMapsEqual(readHistoryStateBfcacheIds(state), bfcacheIds) && this.#restorableClientState.isCurrentBfcacheVersion(state));
@@ -179,7 +179,7 @@ var AppBrowserHistoryController = class {
179
179
  bfcacheVersion: this.#restorableClientState.currentBfcacheVersion,
180
180
  previousNextUrl: options.previousNextUrl,
181
181
  traversalIndex: this.#currentHistoryTraversalIndex
182
- }), this.#readCurrentHref());
182
+ }));
183
183
  }
184
184
  /**
185
185
  * Resolves a restorable snapshot candidate for the given history entry and
@@ -1,8 +1,8 @@
1
1
  import { stripBasePath } from "../utils/base-path.js";
2
2
  import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
3
3
  import { claimAppRouterScrollIntentForCommit, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
4
- import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
5
4
  import { resolveServerActionOperationLane, shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
5
+ import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
6
6
  import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit } from "./app-browser-state.js";
7
7
  import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
8
8
  import { startTransition, useInsertionEffect, useLayoutEffect } from "react";
@@ -6,12 +6,12 @@ import { AppElementsWire } from "./app-elements-wire.js";
6
6
  import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
7
7
  import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
8
8
  import { createCacheEntryReuseProof } from "./cache-proof.js";
9
+ import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
9
10
  import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
10
11
  import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
11
12
  import { verifyOperationTokenForCommit } from "./operation-token.js";
12
13
  import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
13
14
  import { createSnapshotPathAndSearch } from "../shims/navigation.js";
14
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
15
15
  //#region src/server/app-browser-state.ts
16
16
  const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "committed-cache" };
17
17
  const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
@@ -1,8 +1,8 @@
1
1
  import { normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
2
2
  import "./app-elements.js";
3
3
  import { mergeElements } from "../shims/slot.js";
4
- import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
5
4
  import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
5
+ import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
6
6
  import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
7
7
  //#region src/server/app-browser-visible-commit.ts
8
8
  const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
@@ -5,6 +5,7 @@ import { AppPageParams } from "./app-page-boundary.js";
5
5
  import { AppPageFontPreload } from "./app-page-execution.js";
6
6
  import { AppPageMiddlewareContext } from "./app-page-response.js";
7
7
  import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
8
+ import { AppPageInterceptOptions } from "./app-page-element-builder.js";
8
9
  import { AppPageSsrHandler } from "./app-page-stream.js";
9
10
  import { AppPageBoundaryRoute } from "./app-page-boundary-render.js";
10
11
  import { ReactNode } from "react";
@@ -81,6 +82,7 @@ type AppFallbackRendererCallContext = {
81
82
  * render path. Defaults to `false` when no route is matched.
82
83
  */
83
84
  isEdgeRuntime?: boolean;
85
+ routePathname?: string;
84
86
  sourcePageSegments?: readonly string[] | null;
85
87
  };
86
88
  type AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {
@@ -88,6 +90,7 @@ type AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {
88
90
  renderHttpAccessFallback: (route: AppPageBoundaryRoute<TModule> | null, statusCode: number, isRscRequest: boolean, request: Request, opts: {
89
91
  boundaryComponent?: AppPageComponent | null;
90
92
  boundaryModule?: TModule | null;
93
+ intercept?: AppPageInterceptOptions<TModule> | null;
91
94
  layouts?: readonly (TModule | null | undefined)[] | null;
92
95
  matchedParams?: AppPageParams;
93
96
  }, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext) => Promise<Response | null>;
@@ -1,8 +1,8 @@
1
- import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./app-page-boundary-render.js";
2
1
  import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
2
+ import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
3
+ import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./app-page-boundary-render.js";
3
4
  import { DEFAULT_GLOBAL_NOT_FOUND_MODULE } from "./default-global-not-found-module.js";
4
5
  import { DEFAULT_NOT_FOUND_MODULE } from "./default-not-found-module.js";
5
- import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
6
6
  //#region src/server/app-fallback-renderer.ts
7
7
  const EMPTY_MW_CTX = {
8
8
  headers: null,
@@ -84,6 +84,7 @@ function createAppFallbackRenderer(options) {
84
84
  getAndClearPendingCookies,
85
85
  getNavigationContext,
86
86
  globalErrorModule: effectiveGlobalErrorModule,
87
+ intercept: opts?.intercept ?? null,
87
88
  isEdgeRuntime: callContext?.isEdgeRuntime,
88
89
  isRscRequest,
89
90
  layoutModules: useGlobalNotFound ? [] : opts?.layouts ?? null,
@@ -100,6 +101,7 @@ function createAppFallbackRenderer(options) {
100
101
  rootNotFoundModule: routeMissRootNotFoundModule,
101
102
  rootUnauthorizedModule,
102
103
  route: useGlobalNotFound ? null : route,
104
+ routePathname: callContext?.routePathname,
103
105
  renderToReadableStream: rscRenderer,
104
106
  scriptNonce,
105
107
  serveStreamingMetadata,
@@ -1,7 +1,7 @@
1
1
  import { VINEXT_MW_CTX_HEADER } from "../utils/protocol-headers.js";
2
2
  import { FLIGHT_HEADERS } from "./headers.js";
3
3
  import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
4
- import { isExternalUrl, proxyExternalRequest } from "../config/config-matchers.js";
4
+ import { isExternalUrl } from "../utils/external-url.js";
5
5
  import { internalServerErrorResponse } from "./http-error-responses.js";
6
6
  import { cloneRequestWithHeaders, processMiddlewareHeaders } from "./request-pipeline.js";
7
7
  import { executeMiddleware } from "./middleware-runtime.js";
@@ -58,6 +58,7 @@ async function proxyExternalMiddlewareRewrite(request, rewriteUrl, context) {
58
58
  const proxyRequest = requestWithMiddlewareRequestHeaders(request, context.requestHeaders ?? context.headers);
59
59
  setHeadersContext(null);
60
60
  setNavigationContext(null);
61
+ const { proxyExternalRequest } = await import("../config/config-matchers.js");
61
62
  const proxyResponse = await proxyExternalRequest(proxyRequest, rewriteUrl);
62
63
  const headers = new Headers(proxyResponse.headers);
63
64
  processMiddlewareHeaders(headers);
@@ -5,6 +5,8 @@ import { AppPageParams } from "./app-page-boundary.js";
5
5
  import { AppPageFontPreload } from "./app-page-execution.js";
6
6
  import { AppPageMiddlewareContext } from "./app-page-response.js";
7
7
  import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
8
+ import { AppPageRouteWiringRoute } from "./app-page-route-wiring.js";
9
+ import { AppPageInterceptOptions } from "./app-page-element-builder.js";
8
10
  import { AppPageSsrHandler } from "./app-page-stream.js";
9
11
  import { ComponentType, ReactNode } from "react";
10
12
 
@@ -19,13 +21,20 @@ type AppPageBoundaryRoute<TModule extends AppPageModule = AppPageModule> = {
19
21
  errorPaths?: readonly TModule[] | null;
20
22
  errors?: readonly (TModule | null | undefined)[] | null;
21
23
  forbidden?: TModule | null;
24
+ forbiddenTreePosition?: number | null;
25
+ forbiddens?: readonly (TModule | null | undefined)[] | null;
22
26
  layoutTreePositions?: readonly number[] | null;
23
27
  layouts?: readonly (TModule | null | undefined)[];
24
28
  notFound?: TModule | null;
29
+ notFounds?: readonly (TModule | null | undefined)[] | null;
30
+ notFoundTreePosition?: number | null;
25
31
  params?: AppPageParams;
26
32
  pattern?: string;
27
33
  routeSegments?: readonly string[];
34
+ slots?: AppPageRouteWiringRoute<TModule>["slots"];
28
35
  unauthorized?: TModule | null;
36
+ unauthorizedTreePosition?: number | null;
37
+ unauthorizeds?: readonly (TModule | null | undefined)[] | null;
29
38
  };
30
39
  type AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageModule> = {
31
40
  applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
@@ -70,11 +79,13 @@ type AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageM
70
79
  type RenderAppPageHttpAccessFallbackOptions<TModule extends AppPageModule = AppPageModule> = {
71
80
  boundaryComponent?: AppPageComponent | null;
72
81
  boundaryModule?: TModule | null;
82
+ intercept?: AppPageInterceptOptions<TModule> | null;
73
83
  layoutModules?: readonly (TModule | null | undefined)[] | null;
74
84
  matchedParams: AppPageParams;
75
85
  rootForbiddenModule?: TModule | null;
76
86
  rootNotFoundModule?: TModule | null;
77
- rootUnauthorizedModule?: TModule | null;
87
+ rootUnauthorizedModule?: TModule | null; /** Normalized, basePath-free application pathname used for route matching. */
88
+ routePathname?: string;
78
89
  route?: AppPageBoundaryRoute<TModule> | null;
79
90
  /**
80
91
  * When true, the resolved boundary is rendered without wrapping it in the
@@ -1,3 +1,4 @@
1
+ import { stripBasePath } from "../utils/base-path.js";
1
2
  import { NEVER_CACHE_CONTROL } from "./cache-control.js";
2
3
  import { AppElementsWire } from "./app-elements-wire.js";
3
4
  import "./app-elements.js";
@@ -6,12 +7,17 @@ import { isNavigationSignalError } from "../utils/navigation-signal.js";
6
7
  import { ErrorBoundary, GlobalErrorBoundary, SerializedErrorBoundary } from "../shims/error-boundary.js";
7
8
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
8
9
  import { MetadataHead, ViewportHead } from "../shims/metadata.js";
10
+ import { resolveAppPageBranchParams, resolveAppPageSegmentParams } from "./app-page-params.js";
11
+ import { stripRscSuffix } from "./app-rsc-cache-busting.js";
9
12
  import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
10
13
  import { bufferAppPageBinaryStream, buildAppPageSpecialErrorResponse, resolveAppPageSpecialError } from "./app-page-execution.js";
11
- import { resolveAppPageHead } from "./app-page-head.js";
14
+ import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-page-head.js";
12
15
  import { createAppPageLayoutEntries, createAppPageSourcePage } from "./app-page-route-wiring.js";
13
16
  import { buildClientHookErrorMessage } from "../shims/client-hook-error.js";
17
+ import { resolveHttpAccessFallbackMetadata, resolveHttpAccessFallbackViewport } from "./app-page-http-access-fallback-metadata.js";
18
+ import "./app-rsc-route-matching.js";
14
19
  import { renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryModule, wrapAppPageBoundaryElement } from "./app-page-boundary.js";
20
+ import { resolveSlotParamOverrides } from "./app-page-element-builder.js";
15
21
  import { createAppPageFontData, createAppPageRscErrorTracker, renderAppPageHtmlResponse } from "./app-page-stream.js";
16
22
  import { Fragment, createElement } from "react";
17
23
  //#region src/server/app-page-boundary-render.ts
@@ -19,6 +25,16 @@ const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
19
25
  function getDefaultExport(module) {
20
26
  return module?.default ?? null;
21
27
  }
28
+ function resolveHttpAccessBoundaryTreePosition(route, boundaryModule, statusCode) {
29
+ if (!route || !boundaryModule) return null;
30
+ const routeBoundary = statusCode === 403 ? route.forbidden : statusCode === 401 ? route.unauthorized : route.notFound;
31
+ const layoutBoundaries = statusCode === 403 ? route.forbiddens : statusCode === 401 ? route.unauthorizeds : route.notFounds;
32
+ if (boundaryModule === routeBoundary && statusCode === 404) return route.notFoundTreePosition ?? null;
33
+ if (boundaryModule === routeBoundary && statusCode === 403) return route.forbiddenTreePosition ?? null;
34
+ if (boundaryModule === routeBoundary && statusCode === 401) return route.unauthorizedTreePosition ?? null;
35
+ for (let index = (layoutBoundaries?.length ?? 0) - 1; index >= 0; index--) if (layoutBoundaries?.[index] === boundaryModule) return route.layoutTreePositions?.[index] ?? null;
36
+ return null;
37
+ }
22
38
  function wrapRenderedBoundaryElement(options) {
23
39
  return wrapAppPageBoundaryElement({
24
40
  element: options.element,
@@ -194,10 +210,76 @@ async function renderAppPageHttpAccessFallback(options) {
194
210
  if (!boundaryComponent) return null;
195
211
  const layoutModules = options.layoutModules ?? options.route?.layouts ?? options.rootLayouts;
196
212
  const pathname = new URL(options.requestUrl).pathname;
213
+ const routePathname = options.routePathname ?? stripRscSuffix(stripBasePath(pathname, options.basePath ?? ""));
197
214
  const routeSegments = resolveHttpAccessFallbackHeadRouteSegments(options.route, layoutModules);
215
+ const fallbackRouteSegments = routeSegments ?? [];
198
216
  let head;
199
217
  try {
200
- head = await resolveAppPageHead({
218
+ if ([
219
+ 401,
220
+ 403,
221
+ 404
222
+ ].includes(options.statusCode)) {
223
+ const boundaryTreePosition = resolveHttpAccessBoundaryTreePosition(options.route, boundaryModule, options.statusCode);
224
+ const boundaryParams = boundaryTreePosition == null ? {} : resolveAppPageSegmentParams(fallbackRouteSegments, boundaryTreePosition, options.matchedParams);
225
+ const intercept = options.intercept;
226
+ const isSiblingIntercept = intercept?.interceptSlotKey === "__vinext_page_intercept" && intercept.interceptPage != null;
227
+ const effectiveParams = isSiblingIntercept ? intercept.interceptParams ?? options.matchedParams : options.matchedParams;
228
+ const slotParams = resolveSlotParamOverrides({ slots: options.route?.slots ?? null }, routePathname);
229
+ const parallelBranches = resolveActiveParallelRouteHeadInputs({
230
+ interceptBranchSegments: intercept?.interceptBranchSegments ?? null,
231
+ interceptLayouts: intercept?.interceptLayouts ?? null,
232
+ interceptLayoutSegments: intercept?.interceptLayoutSegments ?? null,
233
+ interceptNotFoundBranchSegments: intercept?.interceptNotFoundBranchSegments ?? null,
234
+ interceptNotFound: intercept?.interceptNotFound ?? null,
235
+ interceptNotFoundTreePosition: intercept?.interceptNotFoundTreePosition ?? null,
236
+ interceptPage: intercept?.interceptPage ?? null,
237
+ interceptParams: intercept?.interceptParams ?? null,
238
+ interceptSlotKey: intercept?.interceptSlotKey ?? null,
239
+ interceptSourcePageSegments: intercept?.interceptSourcePageSegments ?? null,
240
+ layoutTreePositions: options.route?.layoutTreePositions,
241
+ params: options.matchedParams,
242
+ routeSegments: fallbackRouteSegments,
243
+ slotParams,
244
+ slots: options.route?.slots ?? null
245
+ });
246
+ const primaryParallelBranch = isSiblingIntercept ? {
247
+ head: {
248
+ layoutModules: intercept?.interceptLayouts ?? [],
249
+ layoutParams: (intercept?.interceptLayoutSegments ?? []).map((segments) => resolveAppPageBranchParams(intercept?.interceptBranchSegments ?? segments, segments.length, effectiveParams, segments)),
250
+ pageModule: intercept?.interceptPage ?? null,
251
+ params: effectiveParams,
252
+ routeSegments: intercept?.interceptSourcePageSegments ?? fallbackRouteSegments
253
+ },
254
+ ...intercept?.interceptNotFound ? {
255
+ notFoundModule: intercept.interceptNotFound,
256
+ notFoundParams: resolveAppPageBranchParams(intercept.interceptNotFoundBranchSegments ?? intercept.interceptBranchSegments ?? fallbackRouteSegments, intercept.interceptNotFoundTreePosition ?? 0, effectiveParams)
257
+ } : {},
258
+ ownerTreePosition: fallbackRouteSegments.length
259
+ } : null;
260
+ const fallbackHeadOptions = {
261
+ boundaryModule,
262
+ boundaryParams,
263
+ branchNotFoundConventions: options.statusCode === 404,
264
+ layoutModules,
265
+ layoutTreePositions: resolveHttpAccessFallbackHeadLayoutTreePositions(options.route, layoutModules),
266
+ parallelBranches,
267
+ params: options.matchedParams,
268
+ primaryParallelBranch,
269
+ routeSegments
270
+ };
271
+ const [metadata, viewport] = await Promise.all([resolveHttpAccessFallbackMetadata({
272
+ applyFileBasedMetadata: options.applyFileBasedMetadata,
273
+ basePath: options.basePath ?? "",
274
+ ...fallbackHeadOptions,
275
+ metadataRoutes: options.metadataRoutes,
276
+ routePath: options.route?.pattern ?? pathname
277
+ }), resolveHttpAccessFallbackViewport(fallbackHeadOptions)]);
278
+ head = {
279
+ metadata,
280
+ viewport
281
+ };
282
+ } else head = await resolveAppPageHead({
201
283
  applyFileBasedMetadata: options.applyFileBasedMetadata,
202
284
  basePath: options.basePath ?? "",
203
285
  layoutModules,
@@ -1,6 +1,6 @@
1
1
  import { RenderObservation } from "./cache-proof.js";
2
- import { CachedAppPageValue } from "../shims/cache-handler.js";
3
2
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
3
+ import { CachedAppPageValue } from "../shims/cache-handler.js";
4
4
  import { AppPageRenderObservationState } from "./app-page-render-observation.js";
5
5
 
6
6
  //#region src/server/app-page-cache-finalizer.d.ts
@@ -1,6 +1,6 @@
1
1
  import { RenderObservation } from "./cache-proof.js";
2
- import { CacheControlMetadata, CachedAppPageValue } from "../shims/cache-handler.js";
3
2
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
3
+ import { CacheControlMetadata, CachedAppPageValue } from "../shims/cache-handler.js";
4
4
  import { finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse, scheduleAppPageRscCacheWrite } from "./app-page-cache-finalizer.js";
5
5
  import { ISRCacheEntry } from "./isr-cache.js";
6
6
 
@@ -4,11 +4,11 @@ import { AppOutgoingElements } from "./app-elements-wire.js";
4
4
  import { NavigationContext } from "../shims/navigation-context-state.js";
5
5
  import { AppPageFontPreload, LayoutClassificationOptions } from "./app-page-execution.js";
6
6
  import { AppPageMiddlewareContext } from "./app-page-response.js";
7
+ import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
8
+ import { AppRscRenderMode } from "./app-rsc-render-mode.js";
7
9
  import { RootParams } from "../shims/root-params.js";
8
10
  import { AppPageSsrHandler } from "./app-page-stream.js";
9
- import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
10
11
  import { CachedAppPageValue } from "../shims/cache-handler.js";
11
- import { AppRscRenderMode } from "./app-rsc-render-mode.js";
12
12
  import { ISRCacheEntry } from "./isr-cache.js";
13
13
  import { PprFallbackShellState } from "../shims/ppr-fallback-shell.js";
14
14
  import { FetchCacheMode } from "../shims/fetch-cache.js";
@@ -36,6 +36,9 @@ type AppPageDispatchIntercept<TPage = unknown> = {
36
36
  interceptLayouts?: readonly unknown[] | null;
37
37
  interceptLayoutSegments?: readonly (readonly string[])[] | null;
38
38
  interceptBranchSegments?: readonly string[] | null;
39
+ interceptNotFoundBranchSegments?: readonly string[] | null;
40
+ notFound?: unknown;
41
+ notFoundTreePosition?: number | null;
39
42
  matchedParams: AppPageParams;
40
43
  sourceMatchedParams?: AppPageParams;
41
44
  page: TPage;
@@ -49,6 +52,9 @@ type AppPageDispatchInterceptOptions<TPage = unknown> = {
49
52
  interceptLayouts?: readonly unknown[] | null;
50
53
  interceptLayoutSegments?: readonly (readonly string[])[] | null;
51
54
  interceptBranchSegments?: readonly string[] | null;
55
+ interceptNotFoundBranchSegments?: readonly string[] | null;
56
+ interceptNotFound?: unknown;
57
+ interceptNotFoundTreePosition?: number | null;
52
58
  interceptPage: TPage;
53
59
  interceptParams: AppPageParams;
54
60
  interceptSlotId?: string | null;
@@ -73,6 +79,7 @@ type AppPageDispatchRoute = {
73
79
  error?: AppPageModule | null;
74
80
  errors?: readonly (AppPageModule | null | undefined)[];
75
81
  forbidden?: AppPageModule | null;
82
+ forbiddenTreePosition?: number | null;
76
83
  forbiddens?: readonly (AppPageModule | null | undefined)[];
77
84
  isDynamic: boolean;
78
85
  layouts: readonly AppPageModule[];
@@ -85,6 +92,7 @@ type AppPageDispatchRoute = {
85
92
  routeSegments: readonly string[];
86
93
  slots?: Readonly<Record<string, AppPageDispatchSlot>>;
87
94
  unauthorized?: AppPageModule | null;
95
+ unauthorizedTreePosition?: number | null;
88
96
  unauthorizeds?: readonly (AppPageModule | null | undefined)[];
89
97
  };
90
98
  type AppPagePprRuntime<TRoute extends AppPageDispatchRoute> = {
@@ -185,6 +193,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
185
193
  renderHttpAccessFallbackPage: (statusCode: number, opts: {
186
194
  boundaryComponent?: unknown;
187
195
  boundaryModule?: AppPageModule | null;
196
+ intercept?: AppPageDispatchInterceptOptions | null;
188
197
  layouts?: readonly AppPageModule[];
189
198
  matchedParams: AppPageParams;
190
199
  }, middlewareContext: AppPageMiddlewareContext | null) => Promise<Response | null>;
@@ -4,7 +4,7 @@ import "../utils/protocol-headers.js";
4
4
  import { AppElementsWire } from "./app-elements-wire.js";
5
5
  import { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL } from "./app-rsc-render-mode.js";
6
6
  import "./app-elements.js";
7
- import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersContext, isDraftModeRequest, markDynamicUsage, peekDynamicUsage, peekRenderRequestApiUsage, setHeadersContext } from "../shims/headers.js";
7
+ import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersContext, isDraftModeRequest, peekDynamicUsage, peekRenderRequestApiUsage, runWithIsolatedDynamicUsage, setHeadersContext } from "../shims/headers.js";
8
8
  import { _consumeRequestScopedCacheLife, _peekRequestScopedCacheLife } from "../shims/cache-request-state.js";
9
9
  import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground } from "../shims/fetch-cache.js";
10
10
  import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
@@ -16,10 +16,10 @@ import { createAppPageTreePath } from "./app-page-route-wiring.js";
16
16
  import { consumeAppPageRenderObservationState, discardAppPageRenderState } from "./app-page-render-observation.js";
17
17
  import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessBoundaryModule } from "./app-page-boundary.js";
18
18
  import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
19
+ import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
19
20
  import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
20
21
  import { buildAppPageTags } from "./implicit-tags.js";
21
22
  import { resolveAppPageMethodResponse } from "./app-page-method.js";
22
- import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
23
23
  import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
24
24
  import { renderAppPageLifecycle } from "./app-page-render.js";
25
25
  //#region src/server/app-page-dispatch.ts
@@ -140,6 +140,9 @@ function toInterceptOptions(interceptionContext, intercept) {
140
140
  interceptLayouts: intercept.interceptLayouts,
141
141
  interceptLayoutSegments: intercept.interceptLayoutSegments,
142
142
  interceptBranchSegments: intercept.interceptBranchSegments,
143
+ interceptNotFoundBranchSegments: intercept.interceptNotFoundBranchSegments,
144
+ interceptNotFound: intercept.notFound,
145
+ interceptNotFoundTreePosition: intercept.notFoundTreePosition,
143
146
  interceptPage: intercept.page,
144
147
  interceptParams: intercept.matchedParams,
145
148
  interceptSlotId: intercept.slotId ?? null,
@@ -318,7 +321,7 @@ async function dispatchAppPageInner(options) {
318
321
  });
319
322
  if (cachedPageResponse) return cachedPageResponse;
320
323
  }
321
- if (options.skipStaticParamsValidation !== true) {
324
+ if (options.skipStaticParamsValidation !== true && !(options.isProduction && isForceDynamic)) {
322
325
  const dynamicParamsResponse = await validateAppPageDynamicParams({
323
326
  clearRequestContext: options.clearRequestContext,
324
327
  enforceStaticParamsOnly: options.dynamicParamsConfig === false,
@@ -419,7 +422,7 @@ async function dispatchAppPageInner(options) {
419
422
  return options.renderErrorBoundaryPage(buildError);
420
423
  },
421
424
  renderSpecialError(specialError) {
422
- return renderPageSpecialError(options, specialError, serveStreamingMetadata);
425
+ return renderPageSpecialError(options, specialError, serveStreamingMetadata, interceptResult.interceptOpts);
423
426
  },
424
427
  resolveSpecialError: resolveAppPageSpecialError
425
428
  });
@@ -535,16 +538,7 @@ async function dispatchAppPageInner(options) {
535
538
  return isAppLayoutObservationUnsafeForStaticReuse(layoutParamAccess.getLayoutObservation(layoutId));
536
539
  },
537
540
  async runWithIsolatedDynamicScope(fn) {
538
- const priorDynamic = consumeDynamicUsage();
539
- try {
540
- return {
541
- result: await fn(),
542
- dynamicDetected: consumeDynamicUsage()
543
- };
544
- } finally {
545
- consumeDynamicUsage();
546
- if (priorDynamic) markDynamicUsage();
547
- }
541
+ return runWithIsolatedDynamicUsage(fn);
548
542
  }
549
543
  },
550
544
  dynamicStaleTimeSeconds: options.dynamicStaleTimeSeconds,
@@ -558,7 +552,7 @@ async function dispatchAppPageInner(options) {
558
552
  return renderLayoutSpecialError(options, specialError, layoutIndex, serveStreamingMetadata);
559
553
  },
560
554
  renderPageSpecialError(specialError) {
561
- return renderPageSpecialError(options, specialError, serveStreamingMetadata);
555
+ return renderPageSpecialError(options, specialError, serveStreamingMetadata, interceptResult.interceptOpts);
562
556
  },
563
557
  renderToReadableStream: options.renderToReadableStream,
564
558
  hasCustomGlobalError: options.hasCustomGlobalError,
@@ -611,7 +605,7 @@ async function renderLayoutSpecialError(options, specialError, layoutIndex, serv
611
605
  specialError
612
606
  });
613
607
  }
614
- async function renderPageSpecialError(options, specialError, serveStreamingMetadata) {
608
+ async function renderPageSpecialError(options, specialError, serveStreamingMetadata, intercept) {
615
609
  return buildAppPageSpecialErrorResponse({
616
610
  basePath: options.basePath,
617
611
  buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream({
@@ -638,7 +632,10 @@ async function renderPageSpecialError(options, specialError, serveStreamingMetad
638
632
  statusCode
639
633
  });
640
634
  const useLayoutAlignedBoundary = boundaryLayoutIndex !== null && (routeBoundaryModule === null || routeBoundaryModule === parentBoundaryModule);
641
- const fallbackOptions = { matchedParams: options.params };
635
+ const fallbackOptions = {
636
+ intercept,
637
+ matchedParams: options.params
638
+ };
642
639
  if (useLayoutAlignedBoundary && boundaryLayoutIndex !== null) {
643
640
  fallbackOptions.layouts = options.route.layouts.slice(0, boundaryLayoutIndex + 1);
644
641
  if (parentBoundaryModule) {
@@ -22,6 +22,9 @@ type AppPageInterceptOptions<TModule extends AppPageModule = AppPageModule> = {
22
22
  interceptLayouts?: readonly (TModule | null | undefined)[] | null;
23
23
  interceptLayoutSegments?: readonly (readonly string[])[] | null;
24
24
  interceptBranchSegments?: readonly string[] | null;
25
+ interceptNotFoundBranchSegments?: readonly string[] | null;
26
+ interceptNotFound?: TModule | null;
27
+ interceptNotFoundTreePosition?: number | null;
25
28
  interceptPage?: TModule | null;
26
29
  interceptParams?: AppPageParams | null;
27
30
  interceptSlotId?: string | null;
@@ -38,7 +41,8 @@ type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {
38
41
  renderMode?: AppRscRenderMode; /** Observe page `searchParams` access for cache-safety classification. */
39
42
  observePageSearchParamsAccess?: boolean; /** Observe page metadata `searchParams` access for cache-safety classification. */
40
43
  observeMetadataSearchParamsAccess?: boolean; /** Whether generated metadata may stream into the response body. */
41
- serveStreamingMetadata?: boolean;
44
+ serveStreamingMetadata?: boolean; /** Whether streamed render errors must be sanitized for client transport. */
45
+ isProduction?: boolean;
42
46
  };
43
47
  type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {
44
48
  applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
@@ -97,6 +101,7 @@ type AppPageNavigationParamInterceptOptions = {
97
101
  */
98
102
  declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
99
103
  declare function resolveInterceptedSlotSegments(sourcePageSegments: readonly string[] | null | undefined, slotKey: string): readonly string[] | null;
104
+ declare function resolveSlotParamOverrides(route: AppPageNavigationParamRoute, routePath: string): Readonly<Record<string, AppPageParams>> | null;
100
105
  declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
101
106
  //#endregion
102
- export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements, resolveAppPageNavigationParams, resolveInterceptedSlotSegments };
107
+ export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements, resolveAppPageNavigationParams, resolveInterceptedSlotSegments, resolveSlotParamOverrides };