@qzsy/vinext 0.1.12 → 0.1.81

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 (231) hide show
  1. package/README.md +19 -5
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/pages-client-assets-module.d.ts +11 -0
  5. package/dist/build/pages-client-assets-module.js +27 -0
  6. package/dist/build/prerender.d.ts +2 -1
  7. package/dist/build/prerender.js +11 -4
  8. package/dist/build/report.d.ts +2 -1
  9. package/dist/build/report.js +2 -1
  10. package/dist/build/run-prerender.d.ts +7 -0
  11. package/dist/build/run-prerender.js +9 -0
  12. package/dist/build/standalone.js +2 -0
  13. package/dist/check.d.ts +18 -0
  14. package/dist/check.js +77 -19
  15. package/dist/cli-dev-config.d.ts +12 -0
  16. package/dist/cli-dev-config.js +23 -0
  17. package/dist/cli.js +64 -28
  18. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  19. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  20. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  21. package/dist/{server → client}/dev-error-overlay.js +2 -2
  22. package/dist/cloudflare/deploy-config.d.ts +51 -0
  23. package/dist/cloudflare/deploy-config.js +153 -0
  24. package/dist/cloudflare/index.d.ts +1 -1
  25. package/dist/cloudflare/index.js +1 -1
  26. package/dist/cloudflare/project.d.ts +41 -0
  27. package/dist/cloudflare/project.js +243 -0
  28. package/dist/cloudflare/tpr.js +1 -1
  29. package/dist/config/config-matchers.js +14 -10
  30. package/dist/config/next-config.d.ts +6 -3
  31. package/dist/config/next-config.js +47 -1
  32. package/dist/config/server-external-packages.d.ts +4 -0
  33. package/dist/config/server-external-packages.js +91 -0
  34. package/dist/deploy.d.ts +2 -122
  35. package/dist/deploy.js +20 -793
  36. package/dist/entries/app-rsc-entry.d.ts +2 -1
  37. package/dist/entries/app-rsc-entry.js +70 -12
  38. package/dist/entries/app-rsc-manifest.js +8 -0
  39. package/dist/entries/pages-client-entry.d.ts +1 -0
  40. package/dist/entries/pages-client-entry.js +2 -1
  41. package/dist/entries/pages-server-entry.js +6 -2
  42. package/dist/image/image-adapters-virtual.d.ts +59 -0
  43. package/dist/image/image-adapters-virtual.js +50 -0
  44. package/dist/index.d.ts +12 -0
  45. package/dist/index.js +160 -160
  46. package/dist/init-cloudflare.d.ts +43 -0
  47. package/dist/init-cloudflare.js +1000 -0
  48. package/dist/init-platform.d.ts +38 -0
  49. package/dist/init-platform.js +150 -0
  50. package/dist/init.d.ts +14 -37
  51. package/dist/init.js +205 -95
  52. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  53. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  54. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  55. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  56. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  57. package/dist/plugins/ast-scope.d.ts +16 -0
  58. package/dist/plugins/ast-scope.js +62 -0
  59. package/dist/plugins/ast-utils.js +3 -0
  60. package/dist/plugins/css-module-imports.d.ts +14 -0
  61. package/dist/plugins/css-module-imports.js +59 -0
  62. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  63. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  64. package/dist/plugins/middleware-server-only.d.ts +8 -6
  65. package/dist/plugins/middleware-server-only.js +8 -7
  66. package/dist/plugins/optimize-imports.js +1 -1
  67. package/dist/plugins/typeof-window.d.ts +1 -1
  68. package/dist/plugins/typeof-window.js +28 -56
  69. package/dist/routing/app-route-graph.d.ts +13 -2
  70. package/dist/routing/app-route-graph.js +116 -32
  71. package/dist/routing/app-router.d.ts +5 -0
  72. package/dist/routing/app-router.js +5 -0
  73. package/dist/routing/file-matcher.d.ts +8 -0
  74. package/dist/routing/file-matcher.js +10 -1
  75. package/dist/routing/pages-router.js +2 -2
  76. package/dist/server/app-browser-action-result.d.ts +2 -1
  77. package/dist/server/app-browser-action-result.js +5 -1
  78. package/dist/server/app-browser-entry.js +17 -12
  79. package/dist/server/app-browser-history-controller.d.ts +2 -1
  80. package/dist/server/app-browser-history-controller.js +6 -2
  81. package/dist/server/app-browser-interception-context.d.ts +1 -0
  82. package/dist/server/app-browser-interception-context.js +4 -2
  83. package/dist/server/app-browser-navigation-controller.js +1 -0
  84. package/dist/server/app-browser-server-action-client.js +2 -3
  85. package/dist/server/app-browser-state.d.ts +1 -0
  86. package/dist/server/app-browser-state.js +3 -2
  87. package/dist/server/app-fallback-renderer.d.ts +3 -2
  88. package/dist/server/app-fallback-renderer.js +12 -7
  89. package/dist/server/app-middleware.d.ts +2 -3
  90. package/dist/server/app-middleware.js +3 -2
  91. package/dist/server/app-optimistic-routing.js +1 -1
  92. package/dist/server/app-page-boundary-render.d.ts +1 -0
  93. package/dist/server/app-page-boundary-render.js +12 -3
  94. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  95. package/dist/server/app-page-cache-finalizer.js +10 -3
  96. package/dist/server/app-page-cache-render.d.ts +1 -0
  97. package/dist/server/app-page-cache-render.js +8 -4
  98. package/dist/server/app-page-cache.d.ts +1 -0
  99. package/dist/server/app-page-cache.js +4 -1
  100. package/dist/server/app-page-dispatch.d.ts +11 -3
  101. package/dist/server/app-page-dispatch.js +55 -15
  102. package/dist/server/app-page-element-builder.d.ts +5 -1
  103. package/dist/server/app-page-element-builder.js +57 -20
  104. package/dist/server/app-page-head.d.ts +12 -0
  105. package/dist/server/app-page-head.js +42 -19
  106. package/dist/server/app-page-params.d.ts +2 -1
  107. package/dist/server/app-page-params.js +8 -1
  108. package/dist/server/app-page-probe.d.ts +1 -0
  109. package/dist/server/app-page-probe.js +6 -1
  110. package/dist/server/app-page-render-identity.d.ts +1 -0
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render.d.ts +4 -1
  113. package/dist/server/app-page-render.js +8 -3
  114. package/dist/server/app-page-request.d.ts +22 -1
  115. package/dist/server/app-page-request.js +89 -13
  116. package/dist/server/app-page-route-wiring.d.ts +6 -1
  117. package/dist/server/app-page-route-wiring.js +31 -15
  118. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  119. package/dist/server/app-page-search-params-observation.js +11 -7
  120. package/dist/server/app-page-segment-state.js +2 -0
  121. package/dist/server/app-route-handler-dispatch.js +1 -0
  122. package/dist/server/app-route-handler-execution.js +7 -2
  123. package/dist/server/app-route-handler-response.js +1 -0
  124. package/dist/server/app-route-handler-runtime.js +1 -1
  125. package/dist/server/app-route-module-loader.d.ts +2 -0
  126. package/dist/server/app-route-module-loader.js +1 -0
  127. package/dist/server/app-router-entry.d.ts +12 -0
  128. package/dist/server/app-router-entry.js +22 -8
  129. package/dist/server/app-router-image-optimization.d.ts +37 -0
  130. package/dist/server/app-router-image-optimization.js +40 -0
  131. package/dist/server/app-rsc-errors.js +7 -1
  132. package/dist/server/app-rsc-handler.js +27 -14
  133. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  134. package/dist/server/app-rsc-route-matching.js +36 -3
  135. package/dist/server/app-segment-config.d.ts +12 -0
  136. package/dist/server/app-segment-config.js +91 -5
  137. package/dist/server/app-server-action-execution.d.ts +5 -0
  138. package/dist/server/app-server-action-execution.js +106 -33
  139. package/dist/server/app-ssr-entry.js +12 -1
  140. package/dist/server/app-static-generation.d.ts +1 -0
  141. package/dist/server/app-static-generation.js +1 -0
  142. package/dist/server/client-trace-metadata.js +26 -0
  143. package/dist/server/default-global-not-found-module.d.ts +14 -0
  144. package/dist/server/default-global-not-found-module.js +14 -0
  145. package/dist/server/dev-response-headers.d.ts +19 -0
  146. package/dist/server/dev-response-headers.js +78 -0
  147. package/dist/server/dev-server.js +8 -15
  148. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  149. package/dist/server/dev-stack-sourcemap.js +1 -1
  150. package/dist/server/headers.d.ts +7 -15
  151. package/dist/server/headers.js +6 -15
  152. package/dist/server/image-optimization.d.ts +51 -1
  153. package/dist/server/image-optimization.js +52 -2
  154. package/dist/server/isr-cache.d.ts +1 -1
  155. package/dist/server/isr-cache.js +2 -2
  156. package/dist/server/middleware-runtime.js +6 -1
  157. package/dist/server/navigation-planner.d.ts +1 -0
  158. package/dist/server/navigation-planner.js +14 -3
  159. package/dist/server/pages-asset-tags.d.ts +4 -6
  160. package/dist/server/pages-asset-tags.js +12 -12
  161. package/dist/server/pages-client-assets.d.ts +12 -0
  162. package/dist/server/pages-client-assets.js +10 -0
  163. package/dist/server/pages-page-data.d.ts +23 -1
  164. package/dist/server/pages-page-data.js +43 -24
  165. package/dist/server/pages-page-handler.d.ts +2 -1
  166. package/dist/server/pages-page-handler.js +10 -4
  167. package/dist/server/pages-request-pipeline.d.ts +2 -0
  168. package/dist/server/pages-request-pipeline.js +25 -1
  169. package/dist/server/prerender-manifest.d.ts +3 -1
  170. package/dist/server/prerender-route-params.js +1 -1
  171. package/dist/server/prod-server.d.ts +1 -1
  172. package/dist/server/prod-server.js +47 -25
  173. package/dist/server/request-log.d.ts +5 -14
  174. package/dist/server/request-log.js +7 -1
  175. package/dist/server/request-pipeline.js +1 -0
  176. package/dist/server/seed-cache.js +4 -4
  177. package/dist/server/server-action-logger.d.ts +39 -0
  178. package/dist/server/server-action-logger.js +104 -0
  179. package/dist/server/worker-utils.d.ts +2 -1
  180. package/dist/server/worker-utils.js +7 -1
  181. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  182. package/dist/shims/app-router-scroll-state.js +1 -0
  183. package/dist/shims/app-router-scroll.js +2 -1
  184. package/dist/shims/cache.js +19 -15
  185. package/dist/shims/cdn-cache.js +1 -1
  186. package/dist/shims/dynamic-preload-chunks.js +2 -1
  187. package/dist/shims/error-boundary.d.ts +19 -1
  188. package/dist/shims/error-boundary.js +11 -1
  189. package/dist/shims/form.d.ts +3 -1
  190. package/dist/shims/form.js +37 -43
  191. package/dist/shims/headers.d.ts +9 -1
  192. package/dist/shims/headers.js +31 -6
  193. package/dist/shims/image-optimization-url.d.ts +4 -0
  194. package/dist/shims/image-optimization-url.js +33 -1
  195. package/dist/shims/image.js +46 -13
  196. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  197. package/dist/shims/internal/app-route-detection.js +4 -17
  198. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  199. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  200. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -5
  201. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  202. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  203. package/dist/shims/internal/pages-router-components.js +13 -0
  204. package/dist/shims/link.js +23 -16
  205. package/dist/shims/metadata.d.ts +3 -2
  206. package/dist/shims/metadata.js +8 -4
  207. package/dist/shims/navigation.js +4 -2
  208. package/dist/shims/root-params.d.ts +15 -1
  209. package/dist/shims/root-params.js +21 -1
  210. package/dist/shims/router.d.ts +2 -5
  211. package/dist/shims/router.js +41 -22
  212. package/dist/shims/server.js +3 -2
  213. package/dist/typegen.js +6 -5
  214. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  215. package/dist/utils/client-runtime-metadata.js +31 -22
  216. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  217. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  218. package/dist/utils/domain-locale.d.ts +6 -3
  219. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  220. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  221. package/dist/utils/path.d.ts +2 -1
  222. package/dist/utils/path.js +1 -1
  223. package/dist/utils/project.d.ts +9 -1
  224. package/dist/utils/project.js +21 -4
  225. package/dist/utils/protocol-headers.d.ts +17 -0
  226. package/dist/utils/protocol-headers.js +17 -0
  227. package/dist/utils/react-version.d.ts +4 -0
  228. package/dist/utils/react-version.js +44 -0
  229. package/package.json +29 -23
  230. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  231. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -41,6 +41,10 @@ function createServerActionHttpFallbackError(status) {
41
41
  function normalizeServerActionThrownValue(data, responseStatus) {
42
42
  return createServerActionHttpFallbackError(responseStatus) ?? data;
43
43
  }
44
+ function shouldSyncServerActionHttpFallbackHead(result) {
45
+ if (!isServerActionResult(result) || result.root !== void 0) return false;
46
+ return result.returnValue?.ok !== false;
47
+ }
44
48
  async function readInvalidServerActionResponseError(response, hasRedirectLocation) {
45
49
  const contentType = response.headers.get("content-type") ?? "";
46
50
  if (contentType.startsWith("text/x-component") || hasRedirectLocation) return null;
@@ -108,4 +112,4 @@ function createDiscardedServerActionRefreshScheduler(options) {
108
112
  };
109
113
  }
110
114
  //#endregion
111
- export { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldScheduleRefreshForDiscardedServerAction };
115
+ export { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldScheduleRefreshForDiscardedServerAction, shouldSyncServerActionHttpFallbackHead };
@@ -34,14 +34,12 @@ import { AppBrowserHistoryController } from "./app-browser-history-controller.js
34
34
  import { createVisitedResponseCacheEntry, isVisitedResponseCacheEntryFresh } from "./app-visited-response-cache.js";
35
35
  import { createPopstateRestoreHandler, restoreSynchronousPopstateScrollPosition } from "./app-browser-popstate.js";
36
36
  import { createDevOnCaughtError, createOnUncaughtError, createProdOnCaughtError, prodOnRecoverableError } from "./app-browser-error.js";
37
- import { dismissOverlay } from "./dev-error-overlay-store.js";
38
- import { devOnCaughtError, installDevErrorOverlay, installViteHmrErrorHandler, reportInitialDevServerErrors } from "./dev-error-overlay.js";
39
37
  import { createOptimisticRouteTemplate, getOptimisticPrefetchSourceKey, getOptimisticRouteTemplateKey, resolveOptimisticNavigationPayload } from "./app-optimistic-routing.js";
40
38
  import { removeStylesheetLinksCoveredByInlineCss } from "./app-inline-css-client.js";
41
39
  import { createElement, startTransition, use, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
42
40
  import { flushSync } from "react-dom";
43
- import { createFromFetch, createFromReadableStream, setServerCallback } from "@vitejs/plugin-rsc/browser";
44
41
  import { createRoot, hydrateRoot } from "react-dom/client";
42
+ import { createFromFetch, createFromReadableStream, setServerCallback } from "@vitejs/plugin-rsc/browser";
45
43
  import { hasServerActions, loadServerActionClient } from "virtual:vinext-app-capabilities";
46
44
  //#region src/server/app-browser-entry.ts
47
45
  function toActionType(kind) {
@@ -375,6 +373,10 @@ function storeVisitedResponseSnapshot(rscUrl, interceptionContext, snapshot, par
375
373
  function clientNavigationSnapshotHref(snapshot) {
376
374
  return `${window.location.origin}${createSnapshotPathAndSearch(snapshot)}`;
377
375
  }
376
+ function getCurrentMatchedRoutePathname() {
377
+ const routeKey = AppElementsWire.parseElementKey(getBrowserRouterState().routeId);
378
+ return routeKey?.kind === "route" ? routeKey.path : null;
379
+ }
378
380
  function getRequestState(navigationKind, targetPathname, previousNextUrlOverride, traverseHistoryState) {
379
381
  if (previousNextUrlOverride !== void 0) return {
380
382
  interceptionContext: resolveInterceptionContextFromPreviousNextUrl(previousNextUrlOverride, __basePath),
@@ -399,6 +401,7 @@ function getRequestState(navigationKind, targetPathname, previousNextUrlOverride
399
401
  };
400
402
  const middlewareRewriteInterceptionContext = resolveMiddlewareRewriteNavigationInterceptionContext({
401
403
  basePath: __basePath,
404
+ currentMatchedPathname: getCurrentMatchedRoutePathname(),
402
405
  currentPathname: window.location.pathname,
403
406
  routeManifest: getBrowserRouteManifest(),
404
407
  targetPathname
@@ -692,24 +695,26 @@ async function main() {
692
695
  if (!claimInitialAppRouterBootstrap()) return;
693
696
  if (hasServerActions) registerServerActionCallback();
694
697
  installAppNavigationFailureListeners();
698
+ let devErrorOverlay = null;
695
699
  if (import.meta.env.DEV) {
696
- installDevErrorOverlay();
697
- installViteHmrErrorHandler(import.meta.hot);
698
- reportInitialDevServerErrors();
700
+ devErrorOverlay = await import("../client/dev-error-overlay.js");
701
+ devErrorOverlay.installDevErrorOverlay();
702
+ devErrorOverlay.installViteHmrErrorHandler(import.meta.hot);
703
+ devErrorOverlay.reportInitialDevServerErrors();
699
704
  }
700
705
  const rscStream = await readInitialRscStream();
701
706
  if (rscStream === null) return;
702
- bootstrapHydration(rscStream);
707
+ bootstrapHydration(rscStream, devErrorOverlay);
703
708
  }
704
- function bootstrapHydration(rscStream) {
709
+ function bootstrapHydration(rscStream, devErrorOverlay) {
705
710
  const root = decodeAppElementsPromise(createFromReadableStream(rscStream));
706
711
  const initialNavigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
707
712
  historyController.writeBootstrapHistoryMetadata();
708
713
  const onUncaughtError = createOnUncaughtError();
709
714
  const formState = consumeInitialFormState(getVinextBrowserGlobal());
710
- const hydrateRootOptions = import.meta.env.DEV ? createVinextHydrateRootOptions({
715
+ const hydrateRootOptions = import.meta.env.DEV && devErrorOverlay ? createVinextHydrateRootOptions({
711
716
  formState,
712
- onCaughtError: createDevOnCaughtError(devOnCaughtError, onUncaughtError),
717
+ onCaughtError: createDevOnCaughtError(devErrorOverlay.devOnCaughtError, onUncaughtError),
713
718
  onUncaughtError
714
719
  }) : createVinextHydrateRootOptions({
715
720
  formState,
@@ -1036,7 +1041,7 @@ function bootstrapHydration(rscStream) {
1036
1041
  restorePopstateScrollPosition
1037
1042
  }, event.state);
1038
1043
  });
1039
- if (import.meta.hot) {
1044
+ if (import.meta.env.DEV && import.meta.hot) {
1040
1045
  const applyRscHmrUpdate = async (updateId) => {
1041
1046
  if (updateId !== latestRscHmrUpdateId) return;
1042
1047
  if (document.documentElement.id === "__next_error__") {
@@ -1052,7 +1057,7 @@ function bootstrapHydration(rscStream) {
1052
1057
  if (!browserNavigationController.hasBrowserRouterState()) return;
1053
1058
  clearClientNavigationCaches();
1054
1059
  const navigationSnapshot = createClientNavigationRenderSnapshot(window.location.href, latestClientParams);
1055
- dismissOverlay();
1060
+ devErrorOverlay?.dismissOverlay();
1056
1061
  const hmrHeaders = createRscRequestHeaders();
1057
1062
  await browserNavigationController.hmrReplaceTree(decodeAppElementsPromise(createFromFetch(fetch(await createRscRequestUrl(window.location.pathname + window.location.search, hmrHeaders), { headers: hmrHeaders }))), navigationSnapshot);
1058
1063
  };
@@ -45,6 +45,7 @@ type CommitNavigationHistoryOptions = {
45
45
  targetHistoryIndex?: number | null;
46
46
  stageClientParams: () => void;
47
47
  };
48
+ declare function createCanonicalBrowserHistoryHref(href: string): string;
48
49
  /**
49
50
  * Owns App Router browser-history metadata and traversal bookkeeping behind a
50
51
  * typed seam: traversal index allocation/commit, push/replace/traverse/hash-only
@@ -101,4 +102,4 @@ declare class AppBrowserHistoryController {
101
102
  restoreHistorySnapshot(options: RestoreHistorySnapshotOptions): boolean;
102
103
  }
103
104
  //#endregion
104
- export { AppBrowserHistoryController, RestorableSnapshotCandidate };
105
+ export { AppBrowserHistoryController, RestorableSnapshotCandidate, createCanonicalBrowserHistoryHref };
@@ -1,5 +1,9 @@
1
1
  import { RestorableClientStateController, createHistoryStateWithNavigationMetadata, readHistoryStateBfcacheIds, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
2
2
  //#region src/server/app-browser-history-controller.ts
3
+ function createCanonicalBrowserHistoryHref(href) {
4
+ const url = new URL(href);
5
+ return `${url.pathname}${url.search}${url.hash}`;
6
+ }
3
7
  function stripVinextScrollState(state) {
4
8
  if (!state || typeof state !== "object") return state;
5
9
  const nextState = {};
@@ -166,7 +170,7 @@ var AppBrowserHistoryController = class {
166
170
  this.#replaceHistoryState(createHistoryStateWithNavigationMetadata(this.#readHistoryState(), {
167
171
  previousNextUrl: null,
168
172
  traversalIndex: this.#currentHistoryTraversalIndex
169
- }), this.#readCurrentHref());
173
+ }), createCanonicalBrowserHistoryHref(this.#readCurrentHref()));
170
174
  }
171
175
  /** History write performed on the first committed (hydrated) render. */
172
176
  writeHydratedHistoryMetadata(options) {
@@ -207,4 +211,4 @@ function areBfcacheIdMapsEqual(a, b) {
207
211
  return aEntries.every(([key, value]) => b[key] === value);
208
212
  }
209
213
  //#endregion
210
- export { AppBrowserHistoryController };
214
+ export { AppBrowserHistoryController, createCanonicalBrowserHistoryHref };
@@ -3,6 +3,7 @@ import { RouteManifest } from "../routing/app-route-graph.js";
3
3
  //#region src/server/app-browser-interception-context.d.ts
4
4
  type ResolveManifestNavigationInterceptionContextOptions = {
5
5
  basePath: string;
6
+ currentMatchedPathname?: string | null;
6
7
  currentPathname: string;
7
8
  routeManifest: RouteManifest | null;
8
9
  targetPathname: string;
@@ -29,13 +29,15 @@ function resolveManifestNavigationInterceptionContext(options) {
29
29
  function resolveMiddlewareRewriteNavigationInterceptionContext(options) {
30
30
  if (options.routeManifest === null) return null;
31
31
  const currentPathname = stripBasePath(options.currentPathname, options.basePath);
32
+ const currentMatchedPathname = options.currentMatchedPathname ? stripBasePath(options.currentMatchedPathname, options.basePath) : null;
32
33
  const targetPathname = stripBasePath(options.targetPathname, options.basePath);
33
34
  const sourceParts = splitPathnameForRouteMatch(currentPathname);
35
+ const matchedSourceParts = currentMatchedPathname ? splitPathnameForRouteMatch(currentMatchedPathname) : null;
34
36
  const targetParts = splitPathnameForRouteMatch(targetPathname);
35
37
  for (const interception of options.routeManifest.segmentGraph.interceptions.values()) {
36
- if (!matchRoutePatternPrefix(sourceParts, interception.sourcePatternParts)) continue;
37
38
  if (!matchRoutePatternWithOptionalDynamicSegments(targetParts, interception.targetPatternParts)) continue;
38
- return currentPathname;
39
+ if (matchRoutePatternPrefix(sourceParts, interception.sourcePatternParts)) return currentPathname;
40
+ if (currentMatchedPathname !== null && matchedSourceParts !== null && matchRoutePatternPrefix(matchedSourceParts, interception.sourcePatternParts)) return currentMatchedPathname;
39
41
  }
40
42
  return null;
41
43
  }
@@ -280,6 +280,7 @@ function createAppBrowserNavigationController(deps = {}) {
280
280
  previousNextUrl: options.restoredState.previousNextUrl,
281
281
  rootLayoutTreePath: options.restoredState.rootLayoutTreePath,
282
282
  routeId: options.restoredState.routeId,
283
+ restoredHistorySnapshot: true,
283
284
  skippedLayoutIds: []
284
285
  };
285
286
  }
@@ -3,7 +3,7 @@ import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-saf
3
3
  import { AppElementsWire } from "./app-elements-wire.js";
4
4
  import "./app-elements.js";
5
5
  import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
6
- import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult } from "./app-browser-action-result.js";
6
+ import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldSyncServerActionHttpFallbackHead } from "./app-browser-action-result.js";
7
7
  import { resolveServerActionRequestState } from "./app-browser-state.js";
8
8
  import { applyServerActionResultDecision } from "./app-browser-server-action-navigation.js";
9
9
  import { throwOnServerActionNotFound } from "./server-action-not-found.js";
@@ -106,8 +106,7 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
106
106
  deps.performHardNavigation(actionRedirectTarget.href);
107
107
  return;
108
108
  }
109
- const hasSameUrlRerenderPayload = isServerActionResult(result) && result.root !== void 0;
110
- deps.syncServerActionHttpFallbackHead(hasSameUrlRerenderPayload ? null : fetchResponse.status);
109
+ deps.syncServerActionHttpFallbackHead(shouldSyncServerActionHttpFallbackHead(result) ? fetchResponse.status : null);
111
110
  if (isServerActionResult(result)) {
112
111
  if (result.root !== void 0) {
113
112
  const returnValue = result.returnValue && !result.returnValue.ok ? {
@@ -64,6 +64,7 @@ type PendingNavigationCommit = {
64
64
  previousNextUrl: string | null;
65
65
  rootLayoutTreePath: string | null;
66
66
  routeId: string;
67
+ restoredHistorySnapshot?: boolean;
67
68
  skippedLayoutIds: readonly string[];
68
69
  };
69
70
  type AppNavigationPayloadOrigin = Readonly<{
@@ -126,7 +126,7 @@ function createMountedParallelSlotSnapshots(elements) {
126
126
  }
127
127
  function createVisibleRouteSnapshot(state) {
128
128
  const displayUrl = createSnapshotPathAndSearch(state.navigationSnapshot);
129
- const matchedUrl = normalizeNavigationSnapshotMatchedUrl(state.navigationSnapshot.pathname);
129
+ const matchedUrl = state.interception?.targetMatchedUrl ?? normalizeNavigationSnapshotMatchedUrl(state.navigationSnapshot.pathname);
130
130
  return {
131
131
  displayUrl,
132
132
  interception: state.interception,
@@ -144,7 +144,7 @@ function createVisibleRouteSnapshot(state) {
144
144
  }
145
145
  function createPendingRouteSnapshot(pending) {
146
146
  const displayUrl = createSnapshotPathAndSearch(pending.action.navigationSnapshot);
147
- const matchedUrl = normalizeNavigationSnapshotMatchedUrl(pending.action.navigationSnapshot.pathname);
147
+ const matchedUrl = pending.action.interception?.targetMatchedUrl ?? normalizeNavigationSnapshotMatchedUrl(pending.action.navigationSnapshot.pathname);
148
148
  return {
149
149
  displayUrl,
150
150
  interception: pending.action.interception,
@@ -188,6 +188,7 @@ function planPendingRootBoundaryFlightResponse(options) {
188
188
  kind: "flightResponseArrived",
189
189
  result: {
190
190
  ...cacheEntryReuseProof ? { cacheEntryReuseProof } : {},
191
+ ...options.pending.restoredHistorySnapshot ? { restoredHistorySnapshot: true } : {},
191
192
  href: options.targetHref ?? options.targetSnapshot.displayUrl,
192
193
  targetSnapshot: options.targetSnapshot
193
194
  },
@@ -33,7 +33,8 @@ type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> =
33
33
  createRscOnErrorHandler: (request: Request, pathname: string, routePath: string) => AppPageBoundaryOnError;
34
34
  fontProviders: AppFallbackRendererFontProviders;
35
35
  getNavigationContext: () => NavigationContext | null;
36
- globalErrorModule?: TModule | null;
36
+ globalErrorModule?: TModule | null; /** Whether experimental.globalNotFound is enabled for route-miss 404s. */
37
+ globalNotFoundEnabled?: boolean;
37
38
  /**
38
39
  * Loader for the user's `app/global-not-found.tsx` module. When provided,
39
40
  * route-miss 404s render this module as a standalone document (skipping the
@@ -75,7 +76,7 @@ type AppFallbackRendererCallContext = {
75
76
  sourcePageSegments?: readonly string[] | null;
76
77
  };
77
78
  type AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {
78
- renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext) => Promise<Response | null>;
79
+ renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
79
80
  renderHttpAccessFallback: (route: AppPageBoundaryRoute<TModule> | null, statusCode: number, isRscRequest: boolean, request: Request, opts: {
80
81
  boundaryComponent?: AppPageComponent | null;
81
82
  boundaryModule?: TModule | null;
@@ -1,5 +1,6 @@
1
1
  import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./app-page-boundary-render.js";
2
2
  import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
3
+ import { DEFAULT_GLOBAL_NOT_FOUND_MODULE } from "./default-global-not-found-module.js";
3
4
  import { DEFAULT_NOT_FOUND_MODULE } from "./default-not-found-module.js";
4
5
  //#region src/server/app-fallback-renderer.ts
5
6
  const EMPTY_MW_CTX = {
@@ -7,7 +8,7 @@ const EMPTY_MW_CTX = {
7
8
  status: null
8
9
  };
9
10
  function createAppFallbackRenderer(options) {
10
- const { applyFileBasedMetadata, basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
11
+ const { applyFileBasedMetadata, basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, globalNotFoundEnabled = false, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
11
12
  const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } = rootBoundaries;
12
13
  const effectiveGlobalErrorModule = globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE;
13
14
  const effectiveRootNotFoundModule = rootNotFoundModule ?? DEFAULT_NOT_FOUND_MODULE;
@@ -19,7 +20,8 @@ function createAppFallbackRenderer(options) {
19
20
  }
20
21
  return {
21
22
  async renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, middlewareContext, callContext) {
22
- if (statusCode === 404 && !!loadGlobalNotFoundModule && !route && !opts?.boundaryComponent) {
23
+ const useGlobalNotFound = statusCode === 404 && globalNotFoundEnabled && !route && !opts?.boundaryComponent;
24
+ if (useGlobalNotFound && loadGlobalNotFoundModule) {
23
25
  const globalNotFoundModule = await resolveGlobalNotFoundModule();
24
26
  const globalNotFoundComponent = globalNotFoundModule?.default ?? null;
25
27
  if (globalNotFoundComponent) return renderAppPageHttpAccessFallback({
@@ -57,6 +59,7 @@ function createAppFallbackRenderer(options) {
57
59
  statusCode
58
60
  });
59
61
  }
62
+ const routeMissRootNotFoundModule = useGlobalNotFound ? DEFAULT_GLOBAL_NOT_FOUND_MODULE : effectiveRootNotFoundModule;
60
63
  return renderAppPageHttpAccessFallback({
61
64
  applyFileBasedMetadata,
62
65
  basePath,
@@ -75,7 +78,7 @@ function createAppFallbackRenderer(options) {
75
78
  globalErrorModule: effectiveGlobalErrorModule,
76
79
  isEdgeRuntime: callContext?.isEdgeRuntime,
77
80
  isRscRequest,
78
- layoutModules: opts?.layouts ?? null,
81
+ layoutModules: useGlobalNotFound ? [] : opts?.layouts ?? null,
79
82
  loadSsrHandler: ssrLoader,
80
83
  makeThenableParams,
81
84
  matchedParams: opts?.matchedParams ?? route?.params ?? {},
@@ -84,12 +87,13 @@ function createAppFallbackRenderer(options) {
84
87
  requestUrl: request.url,
85
88
  resolveChildSegments,
86
89
  rootForbiddenModule,
87
- rootLayouts,
88
- rootNotFoundModule: effectiveRootNotFoundModule,
90
+ rootLayouts: useGlobalNotFound ? [] : rootLayouts,
91
+ rootNotFoundModule: routeMissRootNotFoundModule,
89
92
  rootUnauthorizedModule,
90
- route,
93
+ route: useGlobalNotFound ? null : route,
91
94
  renderToReadableStream: rscRenderer,
92
95
  scriptNonce,
96
+ skipLayoutWrapping: useGlobalNotFound,
93
97
  sourcePageSegments: callContext?.sourcePageSegments,
94
98
  statusCode
95
99
  });
@@ -97,7 +101,7 @@ function createAppFallbackRenderer(options) {
97
101
  renderNotFound(route, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext) {
98
102
  return this.renderHttpAccessFallback(route, 404, isRscRequest, request, { matchedParams }, scriptNonce, middlewareContext, callContext);
99
103
  },
100
- renderErrorBoundary(route, error, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext) {
104
+ renderErrorBoundary(route, error, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext, errorOrigin = "rsc") {
101
105
  return renderAppPageErrorBoundary({
102
106
  applyFileBasedMetadata,
103
107
  basePath,
@@ -108,6 +112,7 @@ function createAppFallbackRenderer(options) {
108
112
  return buildRscOnErrorHandler(request, pathname, routePath);
109
113
  },
110
114
  error,
115
+ errorOrigin,
111
116
  getFontLinks: fontProviders.getFontLinks,
112
117
  getFontPreloads: fontProviders.getFontPreloads,
113
118
  getFontStyles: fontProviders.getFontStyles,
@@ -14,9 +14,8 @@ type ApplyAppMiddlewareOptions = {
14
14
  context: AppMiddlewareContext;
15
15
  i18nConfig?: NextI18nConfig | null;
16
16
  /**
17
- * Whether the inbound request was a `_next/data` fetch. Captured from the
18
- * raw incoming headers by the caller, because `x-nextjs-data` is in
19
- * INTERNAL_HEADERS and is stripped before this function runs.
17
+ * Whether the inbound request was recognized as a `_next/data` fetch from
18
+ * trusted URL normalization before internal headers were stripped.
20
19
  */
21
20
  isDataRequest?: boolean;
22
21
  filePath?: string;
@@ -1,5 +1,6 @@
1
- import { FLIGHT_HEADERS, VINEXT_MW_CTX_HEADER } from "./headers.js";
2
- import { buildRequestHeadersFromMiddlewareResponse } from "./middleware-request-headers.js";
1
+ import { VINEXT_MW_CTX_HEADER } from "../utils/protocol-headers.js";
2
+ import { FLIGHT_HEADERS } from "./headers.js";
3
+ import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
3
4
  import { isExternalUrl, proxyExternalRequest } from "../config/config-matchers.js";
4
5
  import { internalServerErrorResponse } from "./http-error-responses.js";
5
6
  import { cloneRequestWithHeaders, processMiddlewareHeaders } from "./request-pipeline.js";
@@ -1,9 +1,9 @@
1
1
  import { buildParams, decodeMatchedParams, splitPathnameForRouteMatch } from "../routing/utils.js";
2
2
  import { stripBasePath } from "../utils/base-path.js";
3
- import { matchRoutePattern } from "../routing/route-pattern.js";
4
3
  import { isUnknownRecord } from "../utils/record.js";
5
4
  import { AppElementsWire } from "./app-elements-wire.js";
6
5
  import "./app-elements.js";
6
+ import { matchRoutePattern } from "../routing/route-pattern.js";
7
7
  import { stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
8
8
  import { Suspense, createElement, isValidElement } from "react";
9
9
  //#region src/server/app-optimistic-routing.ts
@@ -75,6 +75,7 @@ type RenderAppPageHttpAccessFallbackOptions<TModule extends AppPageModule = AppP
75
75
  } & AppPageBoundaryRenderCommonOptions<TModule>;
76
76
  type RenderAppPageErrorBoundaryOptions<TModule extends AppPageModule = AppPageModule> = {
77
77
  error: unknown;
78
+ errorOrigin?: "rsc" | "ssr";
78
79
  matchedParams?: AppPageParams | null;
79
80
  route?: AppPageBoundaryRoute<TModule> | null;
80
81
  sanitizeErrorForClient: (error: Error) => Error;
@@ -3,7 +3,7 @@ import { AppElementsWire } from "./app-elements-wire.js";
3
3
  import "./app-elements.js";
4
4
  import DefaultGlobalError from "../shims/default-global-error.js";
5
5
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
6
- import { ErrorBoundary, GlobalErrorBoundary } from "../shims/error-boundary.js";
6
+ import { ErrorBoundary, GlobalErrorBoundary, SerializedErrorBoundary } from "../shims/error-boundary.js";
7
7
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
8
8
  import { MetadataHead, ViewportHead } from "../shims/metadata.js";
9
9
  import { resolveAppPageSpecialError } from "./app-page-execution.js";
@@ -215,7 +215,7 @@ async function renderAppPageErrorBoundary(options) {
215
215
  if (!errorBoundary.component) return null;
216
216
  const rawError = options.error instanceof Error ? options.error : new Error(String(options.error));
217
217
  rewriteClientHookError(rawError);
218
- const errorObject = options.sanitizeErrorForClient(rawError);
218
+ const errorObject = options.errorOrigin === "ssr" ? rawError : options.sanitizeErrorForClient(rawError);
219
219
  const matchedParams = options.matchedParams ?? options.route?.params ?? {};
220
220
  const layoutModules = options.route?.layouts ?? options.rootLayouts;
221
221
  const pathname = new URL(options.requestUrl).pathname;
@@ -249,7 +249,16 @@ async function renderAppPageErrorBoundary(options) {
249
249
  console.error(`[vinext] App page error boundary head resolution failed for ${options.route?.pattern ?? pathname}:`, error);
250
250
  }
251
251
  const buildElement = (BoundaryComponent) => {
252
- const boundaryElement = createElement(BoundaryComponent, { error: errorObject });
252
+ const serializedError = {
253
+ digest: "digest" in errorObject ? String(errorObject.digest) : void 0,
254
+ message: errorObject.message,
255
+ name: errorObject.name,
256
+ stack: process.env.NODE_ENV !== "production" ? errorObject.stack : void 0
257
+ };
258
+ const boundaryElement = errorBoundary.isGlobalError && BoundaryComponent !== DEFAULT_GLOBAL_ERROR_COMPONENT ? createElement(SerializedErrorBoundary, {
259
+ error: serializedError,
260
+ fallback: BoundaryComponent
261
+ }) : createElement(BoundaryComponent, { error: errorObject });
253
262
  return wrapRenderedBoundaryElement({
254
263
  element: createElement(Fragment, null, ...headElements, errorBoundary.isGlobalError ? createElement(GlobalErrorBoundary, {
255
264
  fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
@@ -30,6 +30,7 @@ type FinalizeAppPageHtmlCacheResponseOptions = {
30
30
  isrRscKey: AppPageRscCacheKeyBuilder;
31
31
  isrSet: AppPageCacheSetter;
32
32
  interceptionContext?: string | null;
33
+ omitPendingDynamicCacheState?: boolean;
33
34
  preserveClientResponseHeaders?: boolean;
34
35
  expireSeconds?: number;
35
36
  revalidateSeconds: number | null;
@@ -1,15 +1,21 @@
1
+ import { NEXTJS_CACHE_HEADER, VINEXT_CACHE_HEADER } from "./headers.js";
1
2
  import { setCacheStateHeaders } from "./cache-headers.js";
2
3
  import { applyCdnResponseHeaders } from "./cache-control.js";
3
4
  import { buildAppPageCacheValue } from "./isr-cache.js";
4
5
  import { readStreamAsText } from "../utils/text-stream.js";
5
6
  import { createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
6
7
  //#region src/server/app-page-cache-finalizer.ts
7
- function applyPendingDynamicCdnHeaders(headers, tags) {
8
+ function applyPendingDynamicCdnHeaders(headers, tags, options = {}) {
8
9
  applyCdnResponseHeaders(headers, {
9
10
  cacheControl: headers.get("Cache-Control") ?? "",
10
11
  pendingDynamicCheck: true,
11
12
  tags
12
13
  });
14
+ if (options.omitCacheState === true) {
15
+ headers.delete(VINEXT_CACHE_HEADER);
16
+ headers.delete(NEXTJS_CACHE_HEADER);
17
+ return;
18
+ }
13
19
  setCacheStateHeaders(headers, "MISS");
14
20
  }
15
21
  function resolveAppPageCacheWritePolicy(options) {
@@ -30,7 +36,7 @@ function finalizeAppPageHtmlCacheResponse(response, options) {
30
36
  const htmlKey = options.isrHtmlKey(options.cleanPathname);
31
37
  const rscKey = options.isrRscKey(options.cleanPathname, null, void 0, options.interceptionContext);
32
38
  const clientHeaders = new Headers(response.headers);
33
- if (options.preserveClientResponseHeaders !== true) applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags());
39
+ if (options.preserveClientResponseHeaders !== true) applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags(), { omitCacheState: options.omitPendingDynamicCacheState === true });
34
40
  const cachePromise = (async () => {
35
41
  try {
36
42
  const cachedHtml = await readStreamAsText(streamForCache);
@@ -57,7 +63,8 @@ function finalizeAppPageHtmlCacheResponse(response, options) {
57
63
  cacheTags: pageTags,
58
64
  state: observationState
59
65
  });
60
- const writes = [options.isrSet(htmlKey, buildAppPageCacheValue(cachedHtml, void 0, 200, htmlRenderObservation), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)];
66
+ const linkHeader = response.headers.get("link");
67
+ const writes = [options.isrSet(htmlKey, buildAppPageCacheValue(cachedHtml, void 0, 200, htmlRenderObservation, linkHeader ? { link: linkHeader } : void 0), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)];
61
68
  if (options.capturedRscDataPromise) writes.push(options.capturedRscDataPromise.then((rscData) => options.isrSet(rscKey, buildAppPageCacheValue("", rscData, 200, rscRenderObservation), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)));
62
69
  await Promise.all(writes);
63
70
  options.isrDebug?.("HTML cache written", htmlKey);
@@ -38,6 +38,7 @@ type RenderAppPageCacheArtifactsResult = {
38
38
  cacheControl?: CacheControlMetadata;
39
39
  html: string;
40
40
  htmlRenderObservation: ReturnType<typeof createAppPageRenderObservation>;
41
+ linkHeader?: string;
41
42
  rscData?: ArrayBuffer;
42
43
  rscRenderObservation?: ReturnType<typeof createAppPageRenderObservation>;
43
44
  tags: string[];
@@ -2,9 +2,9 @@ import { consumeDynamicUsage, consumeInvalidDynamicUsageError } from "../shims/h
2
2
  import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
3
3
  import { getCollectedFetchTags } from "../shims/fetch-cache.js";
4
4
  import { readStreamAsText } from "../utils/text-stream.js";
5
- import { teeAppPageRscStreamForCapture } from "./app-page-execution.js";
5
+ import { buildAppPageFontLinkHeader, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
6
6
  import { consumeAppPageRenderObservationState, createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
7
- import { isAppSsrRenderResult } from "./app-page-stream.js";
7
+ import { buildAppPageLinkHeader, isAppSsrRenderResult } from "./app-page-stream.js";
8
8
  import { buildAppPageTags } from "./implicit-tags.js";
9
9
  //#region src/server/app-page-cache-render.ts
10
10
  /**
@@ -16,10 +16,11 @@ import { buildAppPageTags } from "./implicit-tags.js";
16
16
  async function renderAppPageCacheArtifacts(options) {
17
17
  const rscCapture = teeAppPageRscStreamForCapture(options.renderToReadableStream(options.element, { onError: options.onError }), options.captureRscData);
18
18
  const capturedRscDataRef = { value: null };
19
+ const fontPreloads = options.getFontPreloads();
19
20
  const htmlResult = await (await options.loadSsrHandler()).handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
20
21
  links: options.getFontLinks(),
21
22
  styles: options.getFontStyles(),
22
- preloads: options.getFontPreloads()
23
+ preloads: fontPreloads
23
24
  }, {
24
25
  basePath: options.basePath,
25
26
  clientTraceMetadata: options.clientTraceMetadata,
@@ -31,7 +32,9 @@ async function renderAppPageCacheArtifacts(options) {
31
32
  capturedRscDataRef
32
33
  } : {}
33
34
  });
34
- const html = await readStreamAsText(isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult);
35
+ const htmlStream = isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult;
36
+ const linkHeader = buildAppPageLinkHeader(isAppSsrRenderResult(htmlResult) ? htmlResult.linkHeader : void 0, buildAppPageFontLinkHeader(fontPreloads), options.reactMaxHeadersLength);
37
+ const html = await readStreamAsText(htmlStream);
35
38
  let rscData;
36
39
  if (options.captureRscData) {
37
40
  const capturedPromise = capturedRscDataRef.value;
@@ -60,6 +63,7 @@ async function renderAppPageCacheArtifacts(options) {
60
63
  params: options.navigationParams,
61
64
  state: observationState
62
65
  }),
66
+ ...linkHeader ? { linkHeader } : {},
63
67
  tags,
64
68
  cacheControl: typeof cacheLife?.revalidate === "number" ? {
65
69
  revalidate: cacheLife.revalidate,
@@ -25,6 +25,7 @@ type AppPageCacheRenderResult = {
25
25
  cacheControl?: CacheControlMetadata;
26
26
  html: string;
27
27
  htmlRenderObservation?: RenderObservation;
28
+ linkHeader?: string;
28
29
  rscData: ArrayBuffer;
29
30
  rscRenderObservation?: RenderObservation;
30
31
  tags: string[];
@@ -43,6 +43,8 @@ function buildAppPageCachedHeaders(options) {
43
43
  applyCdnResponseHeaders(headers, { cacheControl: options.cacheControl });
44
44
  setCacheStateHeaders(headers, options.cacheState);
45
45
  applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
46
+ if (options.linkHeader) if (Array.isArray(options.linkHeader)) for (const value of options.linkHeader) headers.append("Link", value);
47
+ else headers.set("Link", options.linkHeader);
46
48
  if (options.mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
47
49
  mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
48
50
  return headers;
@@ -84,6 +86,7 @@ function buildAppPageCachedResponse(cachedValue, options) {
84
86
  cacheState: options.cacheState,
85
87
  contentType: "text/html; charset=utf-8",
86
88
  isEdgeRuntime: options.isEdgeRuntime,
89
+ linkHeader: cachedValue.headers?.link,
87
90
  middlewareHeaders: options.middlewareHeaders
88
91
  });
89
92
  return new Response(cachedValue.html, {
@@ -177,7 +180,7 @@ async function readAppPageCacheResponse(options) {
177
180
  const revalidateSeconds = revalidatedPage.cacheControl?.revalidate ?? options.revalidateSeconds;
178
181
  const expireSeconds = revalidatedPage.cacheControl?.expire ?? options.expireSeconds;
179
182
  const writes = [options.isrSet(options.isRscRequest ? isrKey : options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode, options.interceptionContext), buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation), revalidateSeconds, revalidatedPage.tags, expireSeconds)];
180
- if (!options.isRscRequest) writes.push(options.isrSet(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation), revalidateSeconds, revalidatedPage.tags, expireSeconds));
183
+ if (!options.isRscRequest) writes.push(options.isrSet(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? { link: revalidatedPage.linkHeader } : void 0), revalidateSeconds, revalidatedPage.tags, expireSeconds));
181
184
  await Promise.all(writes);
182
185
  options.isrDebug?.("regen complete", options.cleanPathname);
183
186
  });
@@ -34,7 +34,10 @@ type AppPageBackgroundRegenerationErrorContext = {
34
34
  type AppPageBackgroundRegenerator = (key: string, renderFn: () => Promise<void>, errorContext?: AppPageBackgroundRegenerationErrorContext) => void;
35
35
  type AppPageDispatchIntercept<TPage = unknown> = {
36
36
  interceptLayouts?: readonly unknown[] | null;
37
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
38
+ interceptBranchSegments?: readonly string[] | null;
37
39
  matchedParams: AppPageParams;
40
+ sourceMatchedParams?: AppPageParams;
38
41
  page: TPage;
39
42
  slotId?: string | null;
40
43
  slotKey: string;
@@ -44,6 +47,8 @@ type AppPageDispatchIntercept<TPage = unknown> = {
44
47
  type AppPageDispatchInterceptOptions<TPage = unknown> = {
45
48
  interceptionContext: string | null;
46
49
  interceptLayouts?: readonly unknown[] | null;
50
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
51
+ interceptBranchSegments?: readonly string[] | null;
47
52
  interceptPage: TPage;
48
53
  interceptParams: AppPageParams;
49
54
  interceptSlotId?: string | null;
@@ -104,7 +109,10 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
104
109
  * `next.config`. Undefined falls back to the React default downstream.
105
110
  */
106
111
  reactMaxHeadersLength?: number;
107
- buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<AppPageElement>;
112
+ buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker, options?: {
113
+ observeMetadataSearchParamsAccess?: boolean;
114
+ observePageSearchParamsAccess?: boolean;
115
+ }) => Promise<AppPageElement>;
108
116
  clientReuseManifest?: ClientReuseManifestParseResult;
109
117
  cleanPathname: string;
110
118
  displayPathname?: string;
@@ -170,9 +178,9 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
170
178
  staticParamsValidationParams?: AppPageParams;
171
179
  rootParams?: RootParams;
172
180
  probeLayoutAt: (layoutIndex: number, layoutParamAccess?: AppLayoutParamAccessTracker) => unknown;
173
- probePage: () => unknown;
181
+ probePage: (searchParams?: URLSearchParams) => unknown;
174
182
  expireSeconds?: number;
175
- renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;
183
+ renderErrorBoundaryPage: (error: unknown, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
176
184
  renderHttpAccessFallbackPage: (statusCode: number, opts: {
177
185
  boundaryComponent?: unknown;
178
186
  boundaryModule?: AppPageModule | null;