vinext 0.1.2 → 0.1.4

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 (243) hide show
  1. package/dist/build/client-build-config.d.ts +11 -2
  2. package/dist/build/client-build-config.js +17 -6
  3. package/dist/build/prerender.d.ts +9 -1
  4. package/dist/build/prerender.js +42 -12
  5. package/dist/build/run-prerender.d.ts +10 -2
  6. package/dist/build/run-prerender.js +15 -1
  7. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  8. package/dist/client/app-nav-failure-handler.js +44 -0
  9. package/dist/client/pages-router-link-navigation.d.ts +33 -7
  10. package/dist/client/pages-router-link-navigation.js +32 -2
  11. package/dist/client/vinext-next-data.d.ts +18 -1
  12. package/dist/client/vinext-next-data.js +2 -0
  13. package/dist/client/window-next.d.ts +2 -1
  14. package/dist/client/window-next.js +12 -1
  15. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  16. package/dist/config/config-matchers.d.ts +11 -1
  17. package/dist/config/config-matchers.js +87 -16
  18. package/dist/config/next-config.d.ts +46 -4
  19. package/dist/config/next-config.js +147 -48
  20. package/dist/config/tsconfig-paths.js +14 -1
  21. package/dist/deploy.d.ts +30 -11
  22. package/dist/deploy.js +200 -112
  23. package/dist/entries/app-browser-entry.d.ts +9 -3
  24. package/dist/entries/app-browser-entry.js +21 -3
  25. package/dist/entries/app-rsc-entry.d.ts +2 -0
  26. package/dist/entries/app-rsc-entry.js +65 -5
  27. package/dist/entries/app-rsc-manifest.js +2 -0
  28. package/dist/entries/app-ssr-entry.js +1 -1
  29. package/dist/entries/pages-client-entry.js +66 -20
  30. package/dist/entries/pages-server-entry.js +47 -31
  31. package/dist/index.js +417 -102
  32. package/dist/plugins/dynamic-preload-metadata.js +2 -4
  33. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  34. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  35. package/dist/plugins/fonts.js +5 -4
  36. package/dist/plugins/optimize-imports.d.ts +2 -1
  37. package/dist/plugins/optimize-imports.js +11 -9
  38. package/dist/plugins/postcss.js +7 -7
  39. package/dist/plugins/strip-server-exports.d.ts +9 -7
  40. package/dist/plugins/strip-server-exports.js +493 -46
  41. package/dist/plugins/typeof-window.d.ts +14 -0
  42. package/dist/plugins/typeof-window.js +150 -0
  43. package/dist/routing/app-route-graph.d.ts +2 -1
  44. package/dist/routing/app-route-graph.js +46 -16
  45. package/dist/routing/file-matcher.d.ts +10 -1
  46. package/dist/routing/file-matcher.js +22 -1
  47. package/dist/routing/pages-router.js +3 -3
  48. package/dist/routing/utils.d.ts +35 -6
  49. package/dist/routing/utils.js +59 -7
  50. package/dist/server/api-handler.d.ts +6 -1
  51. package/dist/server/api-handler.js +21 -15
  52. package/dist/server/app-browser-action-result.d.ts +19 -6
  53. package/dist/server/app-browser-action-result.js +20 -11
  54. package/dist/server/app-browser-entry.js +175 -91
  55. package/dist/server/app-browser-error.d.ts +10 -6
  56. package/dist/server/app-browser-error.js +43 -8
  57. package/dist/server/app-browser-hydration.d.ts +2 -0
  58. package/dist/server/app-browser-hydration.js +1 -0
  59. package/dist/server/app-browser-navigation-controller.d.ts +5 -3
  60. package/dist/server/app-browser-navigation-controller.js +23 -2
  61. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  62. package/dist/server/app-browser-server-action-navigation.js +9 -0
  63. package/dist/server/app-browser-state.d.ts +1 -1
  64. package/dist/server/app-browser-state.js +19 -11
  65. package/dist/server/app-browser-stream.js +86 -43
  66. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  67. package/dist/server/app-elements-wire.d.ts +6 -1
  68. package/dist/server/app-elements-wire.js +14 -4
  69. package/dist/server/app-elements.d.ts +2 -2
  70. package/dist/server/app-elements.js +2 -2
  71. package/dist/server/app-fallback-renderer.d.ts +1 -0
  72. package/dist/server/app-fallback-renderer.js +3 -1
  73. package/dist/server/app-optimistic-routing.js +2 -2
  74. package/dist/server/app-page-boundary-render.d.ts +1 -0
  75. package/dist/server/app-page-boundary-render.js +27 -14
  76. package/dist/server/app-page-cache-render.d.ts +53 -0
  77. package/dist/server/app-page-cache-render.js +91 -0
  78. package/dist/server/app-page-cache.d.ts +16 -2
  79. package/dist/server/app-page-cache.js +62 -1
  80. package/dist/server/app-page-dispatch.d.ts +26 -0
  81. package/dist/server/app-page-dispatch.js +149 -92
  82. package/dist/server/app-page-element-builder.d.ts +1 -0
  83. package/dist/server/app-page-element-builder.js +5 -2
  84. package/dist/server/app-page-execution.d.ts +6 -1
  85. package/dist/server/app-page-execution.js +21 -1
  86. package/dist/server/app-page-probe.d.ts +1 -0
  87. package/dist/server/app-page-probe.js +4 -0
  88. package/dist/server/app-page-render-observation.d.ts +3 -1
  89. package/dist/server/app-page-render-observation.js +17 -1
  90. package/dist/server/app-page-render.d.ts +12 -1
  91. package/dist/server/app-page-render.js +42 -4
  92. package/dist/server/app-page-request.d.ts +2 -0
  93. package/dist/server/app-page-request.js +2 -1
  94. package/dist/server/app-page-route-wiring.d.ts +3 -1
  95. package/dist/server/app-page-route-wiring.js +14 -5
  96. package/dist/server/app-page-stream.d.ts +15 -3
  97. package/dist/server/app-page-stream.js +11 -5
  98. package/dist/server/app-pages-bridge.d.ts +23 -1
  99. package/dist/server/app-pages-bridge.js +26 -17
  100. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  101. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  102. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  103. package/dist/server/app-ppr-fallback-shell.js +8 -1
  104. package/dist/server/app-route-handler-dispatch.js +9 -2
  105. package/dist/server/app-route-handler-policy.d.ts +1 -0
  106. package/dist/server/app-router-entry.js +5 -0
  107. package/dist/server/app-rsc-cache-busting.js +2 -0
  108. package/dist/server/app-rsc-handler.d.ts +28 -0
  109. package/dist/server/app-rsc-handler.js +195 -59
  110. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  111. package/dist/server/app-rsc-route-matching.js +8 -2
  112. package/dist/server/app-segment-config.d.ts +9 -1
  113. package/dist/server/app-segment-config.js +12 -3
  114. package/dist/server/app-server-action-execution.d.ts +1 -0
  115. package/dist/server/app-server-action-execution.js +47 -15
  116. package/dist/server/app-ssr-entry.d.ts +2 -0
  117. package/dist/server/app-ssr-entry.js +84 -39
  118. package/dist/server/before-interactive-head.d.ts +17 -0
  119. package/dist/server/before-interactive-head.js +35 -0
  120. package/dist/server/cache-control.js +4 -0
  121. package/dist/server/csp.js +1 -4
  122. package/dist/server/dev-server.d.ts +2 -2
  123. package/dist/server/dev-server.js +321 -83
  124. package/dist/server/hybrid-route-priority.d.ts +22 -0
  125. package/dist/server/hybrid-route-priority.js +33 -0
  126. package/dist/server/image-optimization.d.ts +18 -9
  127. package/dist/server/image-optimization.js +37 -23
  128. package/dist/server/implicit-tags.d.ts +2 -1
  129. package/dist/server/implicit-tags.js +4 -1
  130. package/dist/server/middleware-matcher.js +12 -3
  131. package/dist/server/middleware-runtime.d.ts +3 -4
  132. package/dist/server/middleware-runtime.js +2 -0
  133. package/dist/server/navigation-planner.d.ts +135 -41
  134. package/dist/server/navigation-planner.js +138 -0
  135. package/dist/server/navigation-trace.d.ts +9 -1
  136. package/dist/server/navigation-trace.js +9 -1
  137. package/dist/server/operation-token.d.ts +40 -0
  138. package/dist/server/operation-token.js +85 -0
  139. package/dist/server/pages-api-route.d.ts +6 -0
  140. package/dist/server/pages-api-route.js +13 -2
  141. package/dist/server/pages-asset-tags.d.ts +2 -1
  142. package/dist/server/pages-asset-tags.js +6 -2
  143. package/dist/server/pages-data-route.d.ts +9 -2
  144. package/dist/server/pages-data-route.js +18 -6
  145. package/dist/server/pages-dev-module-url.d.ts +4 -0
  146. package/dist/server/pages-dev-module-url.js +15 -0
  147. package/dist/server/pages-document-initial-props.d.ts +4 -15
  148. package/dist/server/pages-document-initial-props.js +27 -56
  149. package/dist/server/pages-get-initial-props.d.ts +54 -4
  150. package/dist/server/pages-get-initial-props.js +43 -1
  151. package/dist/server/pages-i18n.js +2 -2
  152. package/dist/server/pages-node-compat.js +2 -2
  153. package/dist/server/pages-page-data.d.ts +11 -2
  154. package/dist/server/pages-page-data.js +207 -34
  155. package/dist/server/pages-page-handler.d.ts +4 -2
  156. package/dist/server/pages-page-handler.js +62 -23
  157. package/dist/server/pages-page-response.d.ts +4 -1
  158. package/dist/server/pages-page-response.js +11 -8
  159. package/dist/server/pages-readiness.js +1 -1
  160. package/dist/server/pages-request-pipeline.d.ts +8 -7
  161. package/dist/server/pages-request-pipeline.js +126 -47
  162. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  163. package/dist/server/pregenerated-concrete-paths.js +2 -19
  164. package/dist/server/prerender-manifest.d.ts +33 -0
  165. package/dist/server/prerender-manifest.js +54 -0
  166. package/dist/server/prerender-route-params.d.ts +1 -2
  167. package/dist/server/prod-server.d.ts +3 -1
  168. package/dist/server/prod-server.js +50 -13
  169. package/dist/server/request-pipeline.d.ts +3 -15
  170. package/dist/server/request-pipeline.js +58 -47
  171. package/dist/server/rsc-stream-hints.d.ts +5 -1
  172. package/dist/server/rsc-stream-hints.js +6 -1
  173. package/dist/server/seed-cache.js +10 -18
  174. package/dist/server/static-file-cache.js +16 -4
  175. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  176. package/dist/shims/app-router-scroll-state.js +14 -2
  177. package/dist/shims/app-router-scroll.d.ts +3 -0
  178. package/dist/shims/app-router-scroll.js +28 -18
  179. package/dist/shims/before-interactive-context.d.ts +14 -3
  180. package/dist/shims/cache-runtime.js +3 -2
  181. package/dist/shims/cache.d.ts +1 -0
  182. package/dist/shims/cache.js +1 -1
  183. package/dist/shims/cdn-cache.d.ts +5 -5
  184. package/dist/shims/document.d.ts +15 -20
  185. package/dist/shims/document.js +5 -8
  186. package/dist/shims/dynamic-preload-chunks.js +6 -4
  187. package/dist/shims/error-boundary.d.ts +2 -0
  188. package/dist/shims/error-boundary.js +7 -0
  189. package/dist/shims/error.js +3 -2
  190. package/dist/shims/error.react-server.d.ts +9 -0
  191. package/dist/shims/error.react-server.js +6 -0
  192. package/dist/shims/fetch-cache.d.ts +3 -1
  193. package/dist/shims/fetch-cache.js +45 -20
  194. package/dist/shims/hash-scroll.js +6 -1
  195. package/dist/shims/headers.js +29 -4
  196. package/dist/shims/image.js +9 -2
  197. package/dist/shims/internal/als-registry.js +28 -1
  198. package/dist/shims/internal/app-route-detection.js +8 -17
  199. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  200. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  201. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  202. package/dist/shims/internal/navigation-untracked.js +55 -0
  203. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
  204. package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
  205. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  206. package/dist/shims/internal/pages-data-target.js +17 -8
  207. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  208. package/dist/shims/internal/pages-router-accessor.js +13 -0
  209. package/dist/shims/internal/router-context.d.ts +2 -1
  210. package/dist/shims/internal/router-context.js +3 -1
  211. package/dist/shims/link.js +47 -19
  212. package/dist/shims/metadata.js +4 -4
  213. package/dist/shims/navigation.d.ts +8 -2
  214. package/dist/shims/navigation.js +63 -31
  215. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  216. package/dist/shims/ppr-fallback-shell.js +28 -7
  217. package/dist/shims/router.d.ts +18 -3
  218. package/dist/shims/router.js +512 -142
  219. package/dist/shims/script.js +8 -4
  220. package/dist/shims/server.d.ts +16 -1
  221. package/dist/shims/server.js +44 -12
  222. package/dist/shims/unified-request-context.js +1 -0
  223. package/dist/utils/built-asset-url.d.ts +4 -0
  224. package/dist/utils/built-asset-url.js +11 -0
  225. package/dist/utils/commonjs-loader.d.ts +16 -0
  226. package/dist/utils/commonjs-loader.js +100 -0
  227. package/dist/utils/deployment-id.d.ts +8 -0
  228. package/dist/utils/deployment-id.js +22 -0
  229. package/dist/utils/has-trailing-comma.d.ts +24 -0
  230. package/dist/utils/has-trailing-comma.js +62 -0
  231. package/dist/utils/html-limited-bots.d.ts +18 -1
  232. package/dist/utils/html-limited-bots.js +23 -1
  233. package/dist/utils/parse-cookie.d.ts +13 -0
  234. package/dist/utils/parse-cookie.js +52 -0
  235. package/dist/utils/path.d.ts +7 -1
  236. package/dist/utils/path.js +9 -1
  237. package/dist/utils/text-stream.d.ts +1 -1
  238. package/dist/utils/text-stream.js +2 -2
  239. package/dist/utils/vite-version.d.ts +12 -1
  240. package/dist/utils/vite-version.js +9 -1
  241. package/package.json +2 -2
  242. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  243. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -1,4 +1,5 @@
1
1
  import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config/next-config.js";
2
+ import { ImageConfig } from "./image-optimization.js";
2
3
  import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
3
4
  import { RootParams } from "../shims/root-params.js";
4
5
  import { MiddlewareModule } from "./middleware-runtime.js";
@@ -17,6 +18,7 @@ type RootParamNamesMap = Parameters<typeof handleAppPrerenderEndpoint>[1]["rootP
17
18
  type AppRscMiddlewareContext = AppMiddlewareContext;
18
19
  type AppRscHandlerRoute = {
19
20
  isDynamic: boolean;
21
+ params?: readonly string[];
20
22
  page?: unknown;
21
23
  pattern: string;
22
24
  rootParamNames?: readonly string[];
@@ -41,6 +43,17 @@ type DispatchMatchedPageOptions<TRoute> = {
41
43
  middlewareContext: AppRscMiddlewareContext;
42
44
  mountedSlotsHeader: string | null;
43
45
  params: AppPageParams;
46
+ pprFallbackCacheShells?: readonly {
47
+ fallbackParamNames: readonly string[];
48
+ params: AppPageParams;
49
+ pathname: string;
50
+ }[] | null;
51
+ pprFallbackShell?: {
52
+ fallbackParamNames: readonly string[];
53
+ routePattern: string;
54
+ };
55
+ renderedConcreteUrlPaths?: ReadonlySet<string>;
56
+ skipStaticParamsValidation?: boolean;
44
57
  staticParamsValidationParams?: AppPageParams;
45
58
  rootParams?: RootParams;
46
59
  request: Request;
@@ -110,8 +123,19 @@ type RenderNotFoundOptions<TRoute> = {
110
123
  scriptNonce?: string;
111
124
  };
112
125
  type RenderPagesFallbackOptions = {
126
+ allowRscDocumentFallback?: boolean;
127
+ appRouteMatch?: {
128
+ route: {
129
+ isDynamic: boolean;
130
+ pattern: string;
131
+ };
132
+ } | null;
133
+ isDataRequest?: boolean;
113
134
  isRscRequest: boolean;
135
+ matchKind?: "dynamic" | "static";
114
136
  middlewareContext: AppRscMiddlewareContext;
137
+ pathname?: string;
138
+ pagesDataRequest?: Request | null;
115
139
  request: Request;
116
140
  url: URL;
117
141
  };
@@ -122,6 +146,8 @@ type NavigationContextValue = {
122
146
  };
123
147
  type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
124
148
  basePath: string;
149
+ buildId: string | null;
150
+ cacheComponents?: boolean;
125
151
  clearRequestContext: () => void;
126
152
  configHeaders: NextHeader[];
127
153
  configRedirects: NextRedirect[];
@@ -150,6 +176,8 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
150
176
  handleProgressiveActionRequest: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
151
177
  handleServerActionRequest: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
152
178
  i18nConfig: NextI18nConfig | null;
179
+ imageConfig?: ImageConfig;
180
+ isDev: boolean;
153
181
  isMiddlewareProxy: boolean;
154
182
  loadPrerenderPagesRoutes?: () => Promise<unknown>;
155
183
  makeThenableParams: MakeThenableParams;
@@ -1,30 +1,35 @@
1
1
  import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
- import { hasBasePath } from "../utils/base-path.js";
2
+ import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
4
  import { ACTION_REVALIDATED_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "./headers.js";
5
5
  import { isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
6
6
  import { notFoundResponse } from "./http-error-responses.js";
7
- import { applyConfigHeadersToResponse, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute, validateImageUrl } from "./request-pipeline.js";
7
+ import { applyConfigHeadersToResponse, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute } from "./request-pipeline.js";
8
8
  import { headersContextFromRequest } from "../shims/headers.js";
9
9
  import { ensureFetchPatch, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
10
- import { createRscRedirectLocation, hasRscCacheBustingSearchParam, resolveInvalidRscCacheBustingRequest, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
10
+ import { mergeRewriteQuery } from "../utils/query.js";
11
+ import { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, createRscRedirectLocation, hasRscCacheBustingSearchParam, resolveInvalidRscCacheBustingRequest, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
11
12
  import { getScriptNonceFromHeaderSources } from "./csp.js";
12
13
  import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
13
- import { isImageOptimizationPath } from "./image-optimization.js";
14
+ import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, resolveDevImageRedirect } from "./image-optimization.js";
14
15
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
15
16
  import "./app-page-response.js";
16
- import { prerenderRouteParamsPayloadMatchesRoute, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
17
+ import { buildNextDataNotFoundResponse, normalizePagesDataRequest } from "./pages-data-route.js";
18
+ import { createAppPprFallbackShells } from "./app-ppr-fallback-shell.js";
19
+ import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
20
+ import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
21
+ import { pickRootParams, setRootParams } from "../shims/root-params.js";
22
+ import { flattenErrorCauses } from "../utils/error-cause.js";
17
23
  import { applyAppMiddleware } from "./app-middleware.js";
18
24
  import { buildPageCacheTags } from "./implicit-tags.js";
19
25
  import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
20
- import { pickRootParams, setRootParams } from "../shims/root-params.js";
21
26
  import { handleAppPrerenderEndpoint } from "./app-prerender-endpoints.js";
22
- import { flattenErrorCauses } from "../utils/error-cause.js";
23
27
  import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
24
28
  import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
25
29
  import { handleMetadataRouteRequest } from "./metadata-route-response.js";
26
30
  import { runWithPrerenderWorkUnit } from "./prerender-work-unit-setup.js";
27
31
  //#region src/server/app-rsc-handler.ts
32
+ const STATIC_METADATA_CONFIG_HEADER_OVERRIDES = new Set(["cache-control"]);
28
33
  function applyMiddlewareContextToResponse(response, middlewareContext) {
29
34
  if (!middlewareContext.headers && middlewareContext.status == null) return response;
30
35
  const headers = new Headers(response.headers);
@@ -38,6 +43,10 @@ function applyMiddlewareContextToResponse(response, middlewareContext) {
38
43
  function hasProperty(value, key) {
39
44
  return key in value;
40
45
  }
46
+ function isEdgeRouteHandler(handler) {
47
+ if (!handler || typeof handler !== "object" || !hasProperty(handler, "runtime")) return false;
48
+ return handler.runtime === "edge" || handler.runtime === "experimental-edge";
49
+ }
41
50
  function isExecutionContextLike(value) {
42
51
  if (!value || typeof value !== "object") return false;
43
52
  return hasProperty(value, "waitUntil") && typeof value.waitUntil === "function";
@@ -56,6 +65,17 @@ async function applyRewrite(options, cleanPathname) {
56
65
  }
57
66
  return rewritten;
58
67
  }
68
+ function requestContextForResolvedUrl(requestContext, resolvedUrl, baseUrl) {
69
+ return {
70
+ cookies: requestContext.cookies,
71
+ headers: requestContext.headers,
72
+ host: requestContext.host,
73
+ query: new URL(resolvedUrl, baseUrl).searchParams
74
+ };
75
+ }
76
+ function pathnameForResolvedUrl(resolvedUrl) {
77
+ return resolvedUrl.split("#", 1)[0].split("?", 1)[0];
78
+ }
59
79
  function applyConfigHeadersToMiddlewareRedirect(response, options) {
60
80
  if (response.status < 300 || response.status >= 400) return response;
61
81
  if (!options.configHeaders.length) return response;
@@ -82,7 +102,14 @@ function requestWithoutRscCacheBustingSearchParam(request) {
82
102
  stripRscCacheBustingSearchParam(url);
83
103
  return cloneRequestWithUrl(request.body ? request.clone() : request, url.toString());
84
104
  }
85
- async function handleAppRscRequest(options, request, preMiddlewareRequestContext, isDataRequest) {
105
+ function requestWithoutRscSuffix(request) {
106
+ const url = new URL(request.url);
107
+ const pathname = stripRscSuffix(url.pathname);
108
+ if (pathname === url.pathname) return request;
109
+ url.pathname = pathname;
110
+ return cloneRequestWithUrl(request.body ? request.clone() : request, url.toString());
111
+ }
112
+ async function handleAppRscRequest(options, request, preMiddlewareRequestContext, isDataRequest, pagesDataRequest) {
86
113
  const handlerStart = process.env.NODE_ENV !== "production" ? performance.now() : 0;
87
114
  if (process.env.NODE_ENV !== "production") {
88
115
  const originBlock = options.validateDevRequestOrigin?.(request);
@@ -92,6 +119,9 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
92
119
  if (normalized instanceof Response) return normalized;
93
120
  const { url, isRscRequest, interceptionContextHeader, mountedSlotsHeader, renderMode, clientReuseManifest } = normalized;
94
121
  let { pathname, cleanPathname } = normalized;
122
+ let resolvedUrl = cleanPathname + url.search;
123
+ const originalResolvedUrl = resolvedUrl;
124
+ const getResolvedSearchParams = () => new URL(resolvedUrl, url).searchParams;
95
125
  const canonicalPathname = cleanPathname;
96
126
  const basePathState = {
97
127
  basePath: options.basePath,
@@ -114,6 +144,10 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
114
144
  if (redirect) {
115
145
  const destination = sanitizeDestination(redirectDestinationWithBasePath(redirect.destination, options.basePath));
116
146
  const location = isRscRequest && request.headers.get("RSC") === "1" ? await createRscRedirectLocation(destination, request) : preserveRedirectDestinationQuery(destination, url.search);
147
+ if (isDataRequest) return new Response(null, {
148
+ status: 200,
149
+ headers: { "x-nextjs-redirect": location }
150
+ });
117
151
  return new Response(null, {
118
152
  status: redirect.permanent ? 308 : 307,
119
153
  headers: { Location: location }
@@ -124,12 +158,14 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
124
158
  request
125
159
  });
126
160
  if (rscCacheBustingRedirect) return rscCacheBustingRedirect;
127
- const userlandRequest = isRscRequest ? requestWithoutRscCacheBustingSearchParam(request) : request;
161
+ const normalizedUserlandRequest = requestWithoutRscSuffix(request);
162
+ const userlandRequest = requestWithoutRscCacheBustingSearchParam(normalizedUserlandRequest);
128
163
  const middlewareContext = {
129
164
  headers: null,
130
165
  requestHeaders: null,
131
166
  status: null
132
167
  };
168
+ let didMiddlewareRewrite = false;
133
169
  if (options.middlewareModule) {
134
170
  const middlewareResult = await applyAppMiddleware({
135
171
  basePath: options.basePath,
@@ -149,30 +185,46 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
149
185
  requestContext: preMiddlewareRequestContext
150
186
  });
151
187
  cleanPathname = middlewareResult.cleanPathname;
188
+ didMiddlewareRewrite = cleanPathname !== normalized.cleanPathname;
152
189
  if (middlewareResult.search !== null) url.search = middlewareResult.search;
190
+ resolvedUrl = cleanPathname + url.search;
153
191
  }
154
192
  const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareContext.headers);
155
193
  const postMiddlewareRequestContext = buildPostMwRequestContext(userlandRequest);
156
- const beforeFilesRewrite = await applyRewrite({
157
- basePathState,
158
- clearRequestContext: options.clearRequestContext,
159
- request: userlandRequest,
160
- requestContext: postMiddlewareRequestContext,
161
- rewrites: options.configRewrites.beforeFiles
162
- }, matchPathname(cleanPathname));
163
- if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;
164
- if (beforeFilesRewrite) cleanPathname = beforeFilesRewrite;
194
+ for (const rewrite of options.configRewrites.beforeFiles) {
195
+ const beforeFilesRewrite = await applyRewrite({
196
+ basePathState,
197
+ clearRequestContext: options.clearRequestContext,
198
+ request: normalizedUserlandRequest,
199
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
200
+ rewrites: [rewrite]
201
+ }, matchPathname(cleanPathname));
202
+ if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;
203
+ if (beforeFilesRewrite) {
204
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, beforeFilesRewrite);
205
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
206
+ }
207
+ }
165
208
  if (isImageOptimizationPath(cleanPathname)) {
166
- const imageUrlResult = validateImageUrl(url.searchParams.get("url"), request.url);
167
- if (imageUrlResult instanceof Response) return imageUrlResult;
168
- return Response.redirect(new URL(imageUrlResult, url.origin).href, 302);
209
+ const imageRedirect = resolveDevImageRedirect(url, [...options.imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...options.imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES], options.imageConfig?.qualities, { isDev: options.isDev });
210
+ if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
211
+ return Response.redirect(new URL(imageRedirect, url.origin).href, 302);
169
212
  }
170
213
  const metadataRouteResponse = await handleMetadataRouteRequest({
171
214
  metadataRoutes: options.metadataRoutes,
172
215
  cleanPathname,
173
216
  makeThenableParams: options.makeThenableParams
174
217
  });
175
- if (metadataRouteResponse) return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
218
+ if (metadataRouteResponse) {
219
+ applyConfigHeadersToResponse(metadataRouteResponse.headers, {
220
+ basePathState,
221
+ configHeaders: options.configHeaders,
222
+ overwriteExisting: STATIC_METADATA_CONFIG_HEADER_OVERRIDES,
223
+ pathname: matchPathname(cleanPathname),
224
+ requestContext: preMiddlewareRequestContext
225
+ });
226
+ return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
227
+ }
176
228
  const publicFileResponse = resolvePublicFileRoute({
177
229
  cleanPathname,
178
230
  middlewareContext,
@@ -184,10 +236,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
184
236
  options.clearRequestContext();
185
237
  return publicFileResponse;
186
238
  }
187
- if (isRscRequest) stripRscCacheBustingSearchParam(url);
239
+ stripRscCacheBustingSearchParam(url);
240
+ const resolved = new URL(resolvedUrl, url);
241
+ stripRscCacheBustingSearchParam(resolved);
242
+ resolvedUrl = resolved.pathname + resolved.search + resolved.hash;
188
243
  options.setNavigationContext({
189
244
  pathname: canonicalPathname,
190
- searchParams: url.searchParams,
245
+ searchParams: getResolvedSearchParams(),
191
246
  params: {}
192
247
  });
193
248
  const preActionMatch = options.matchRoute(cleanPathname);
@@ -216,53 +271,101 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
216
271
  middlewareContext,
217
272
  mountedSlotsHeader,
218
273
  request,
219
- searchParams: url.searchParams
274
+ searchParams: getResolvedSearchParams()
220
275
  });
221
276
  if (serverActionResponse) return serverActionResponse;
222
277
  let match = preActionMatch;
223
- if (!match || match.route.isDynamic) {
278
+ const renderPagesForMatchKind = async (matchKind) => {
279
+ const response = match === null || match.route.isDynamic ? await options.renderPagesFallback?.({
280
+ appRouteMatch: match ?? null,
281
+ allowRscDocumentFallback: didMiddlewareRewrite,
282
+ isDataRequest,
283
+ isRscRequest,
284
+ matchKind,
285
+ middlewareContext,
286
+ pathname: resolvedUrl,
287
+ pagesDataRequest,
288
+ request,
289
+ url
290
+ }) ?? null : null;
291
+ if (!response || !pagesDataRequest || resolvedUrl === originalResolvedUrl) return response;
292
+ const headers = new Headers(response.headers);
293
+ headers.set("x-nextjs-rewrite", resolvedUrl);
294
+ return new Response(response.body, {
295
+ headers,
296
+ status: response.status,
297
+ statusText: response.statusText
298
+ });
299
+ };
300
+ const staticPagesFallbackResponse = await renderPagesForMatchKind("static");
301
+ if (staticPagesFallbackResponse) {
302
+ options.clearRequestContext();
303
+ return staticPagesFallbackResponse;
304
+ }
305
+ if (!match || match.route.isDynamic) for (const rewrite of options.configRewrites.afterFiles) {
224
306
  const afterFilesRewrite = await applyRewrite({
225
307
  basePathState,
226
308
  clearRequestContext: options.clearRequestContext,
227
- request: userlandRequest,
228
- requestContext: postMiddlewareRequestContext,
229
- rewrites: options.configRewrites.afterFiles
309
+ request: normalizedUserlandRequest,
310
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
311
+ rewrites: [rewrite]
230
312
  }, matchPathname(cleanPathname));
231
313
  if (afterFilesRewrite instanceof Response) return afterFilesRewrite;
232
- if (afterFilesRewrite) {
233
- cleanPathname = afterFilesRewrite;
234
- match = options.matchRoute(cleanPathname);
314
+ if (!afterFilesRewrite) continue;
315
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, afterFilesRewrite);
316
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
317
+ match = options.matchRoute(cleanPathname);
318
+ const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
319
+ if (rewrittenStaticPagesResponse) {
320
+ options.clearRequestContext();
321
+ return rewrittenStaticPagesResponse;
322
+ }
323
+ const rewrittenDynamicPagesResponse = await renderPagesForMatchKind("dynamic");
324
+ if (rewrittenDynamicPagesResponse) {
325
+ options.clearRequestContext();
326
+ return rewrittenDynamicPagesResponse;
235
327
  }
328
+ if (match) break;
236
329
  }
237
- if (!match) {
330
+ const dynamicPagesFallbackResponse = await renderPagesForMatchKind("dynamic");
331
+ if (dynamicPagesFallbackResponse) {
332
+ options.clearRequestContext();
333
+ return dynamicPagesFallbackResponse;
334
+ }
335
+ if (!match) for (const rewrite of options.configRewrites.fallback) {
238
336
  const fallbackRewrite = await applyRewrite({
239
337
  basePathState,
240
338
  clearRequestContext: options.clearRequestContext,
241
- request: userlandRequest,
242
- requestContext: postMiddlewareRequestContext,
243
- rewrites: options.configRewrites.fallback
339
+ request: normalizedUserlandRequest,
340
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
341
+ rewrites: [rewrite]
244
342
  }, matchPathname(cleanPathname));
245
343
  if (fallbackRewrite instanceof Response) return fallbackRewrite;
246
- if (fallbackRewrite) {
247
- cleanPathname = fallbackRewrite;
248
- match = options.matchRoute(cleanPathname);
344
+ if (!fallbackRewrite) continue;
345
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
346
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
347
+ match = options.matchRoute(cleanPathname);
348
+ const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
349
+ if (rewrittenStaticPagesResponse) {
350
+ options.clearRequestContext();
351
+ return rewrittenStaticPagesResponse;
352
+ }
353
+ const rewrittenDynamicPagesResponse = await renderPagesForMatchKind("dynamic");
354
+ if (rewrittenDynamicPagesResponse) {
355
+ options.clearRequestContext();
356
+ return rewrittenDynamicPagesResponse;
249
357
  }
358
+ if (match) break;
359
+ }
360
+ if (pagesDataRequest) {
361
+ options.clearRequestContext();
362
+ return buildNextDataNotFoundResponse();
250
363
  }
251
364
  if (!match) {
252
365
  if (process.env.NODE_ENV !== "production" && canonicalPathname === "/favicon.ico") {
253
366
  options.clearRequestContext();
254
367
  return new Response("", { status: 404 });
255
368
  }
256
- const pagesFallbackResponse = await options.renderPagesFallback?.({
257
- isRscRequest,
258
- middlewareContext,
259
- request,
260
- url
261
- });
262
- if (pagesFallbackResponse) {
263
- options.clearRequestContext();
264
- return pagesFallbackResponse;
265
- }
266
369
  const renderedNotFoundResponse = await options.renderNotFound({
267
370
  isRscRequest,
268
371
  middlewareContext,
@@ -278,25 +381,37 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
278
381
  }
279
382
  const { route, params } = match;
280
383
  if (options.ensureRouteLoaded) await options.ensureRouteLoaded(route);
281
- const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
282
- const prerenderRouteParams = prerenderRouteParamsPayloadMatchesRoute(prerenderRouteParamsPayload, route.pattern, params) ? prerenderRouteParamsPayload.params : null;
384
+ const prerenderRouteParamsMatch = matchPrerenderRouteParamsPayload(readTrustedPrerenderRouteParams(request), route.pattern, params);
385
+ const prerenderRouteParams = prerenderRouteParamsMatch?.params ?? null;
386
+ const isPrerenderFallbackShell = prerenderRouteParamsMatch?.kind === "fallback-shell";
283
387
  const renderParams = prerenderRouteParams ?? params;
388
+ const resolvedSearchParams = getResolvedSearchParams();
389
+ const runtimeFallbackShells = options.cacheComponents === true && request.method === "GET" && !isRscRequest && !isPrerenderFallbackShell && route.params ? createAppPprFallbackShells({
390
+ params: route.params,
391
+ pattern: route.pattern,
392
+ rootParamNames: route.rootParamNames
393
+ }, params) : [];
284
394
  options.setNavigationContext({
285
395
  pathname: canonicalPathname,
286
- searchParams: url.searchParams,
396
+ searchParams: resolvedSearchParams,
287
397
  params: renderParams
288
398
  });
289
399
  const rootParams = pickRootParams(renderParams, route.rootParamNames);
290
400
  setRootParams(rootParams);
291
401
  if (route.routeHandler) {
292
402
  setCurrentFetchSoftTags(buildPageCacheTags(cleanPathname, [], [...route.routeSegments], "route"));
403
+ const routeHandlerRequest = isEdgeRouteHandler(route.routeHandler) ? userlandRequest : normalizedUserlandRequest;
404
+ const routeHandlerUrl = new URL(routeHandlerRequest.url);
405
+ const internalRscValues = isEdgeRouteHandler(route.routeHandler) ? [] : routeHandlerUrl.searchParams.getAll(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM);
406
+ routeHandlerUrl.search = resolvedSearchParams.toString();
407
+ for (const internalRscValue of internalRscValues) routeHandlerUrl.searchParams.append(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, internalRscValue);
293
408
  return options.dispatchMatchedRouteHandler({
294
409
  cleanPathname,
295
410
  middlewareContext,
296
411
  params: route.isDynamic ? renderParams : null,
297
- request,
412
+ request: new Request(routeHandlerUrl, routeHandlerRequest),
298
413
  route,
299
- searchParams: url.searchParams
414
+ searchParams: resolvedSearchParams
300
415
  });
301
416
  }
302
417
  const pageResponse = await options.dispatchMatchedPage({
@@ -313,12 +428,19 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
313
428
  middlewareContext,
314
429
  mountedSlotsHeader,
315
430
  params: renderParams,
316
- staticParamsValidationParams: prerenderRouteParams === null ? void 0 : params,
431
+ pprFallbackCacheShells: runtimeFallbackShells,
432
+ pprFallbackShell: isPrerenderFallbackShell ? {
433
+ fallbackParamNames: prerenderRouteParamsMatch.fallbackParamNames,
434
+ routePattern: route.pattern
435
+ } : void 0,
436
+ renderedConcreteUrlPaths: getRenderedConcreteUrlPathsForRoute(route.pattern),
437
+ skipStaticParamsValidation: isPrerenderFallbackShell,
438
+ staticParamsValidationParams: prerenderRouteParams === null || isPrerenderFallbackShell ? void 0 : params,
317
439
  rootParams,
318
440
  request,
319
441
  route,
320
442
  scriptNonce,
321
- searchParams: url.searchParams,
443
+ searchParams: resolvedSearchParams,
322
444
  renderMode
323
445
  });
324
446
  if (isProgressiveActionRender) return applyProgressiveActionSideEffects(pageResponse, progressiveActionResult);
@@ -361,13 +483,27 @@ function createAppRscHandler(options) {
361
483
  options.registerCacheAdapters();
362
484
  await options.ensureInstrumentation?.();
363
485
  const mwCtx = rawRequest.headers.get(VINEXT_MW_CTX_HEADER);
364
- const isDataRequest = rawRequest.headers.get("x-nextjs-data") === "1";
486
+ const hasDataRequestHeader = rawRequest.headers.get("x-nextjs-data") === "1";
487
+ const pagesDataUrl = new URL(rawRequest.url);
488
+ const pagesDataInScope = !options.basePath || hasBasePath(pagesDataUrl.pathname, options.basePath);
489
+ if (pagesDataInScope) pagesDataUrl.pathname = stripBasePath(pagesDataUrl.pathname, options.basePath);
490
+ const pagesDataCandidate = pagesDataInScope ? cloneRequestWithUrl(rawRequest, pagesDataUrl.toString()) : null;
491
+ const pagesDataNormalization = options.renderPagesFallback && pagesDataCandidate ? normalizePagesDataRequest(pagesDataCandidate, options.buildId) : null;
492
+ if (pagesDataNormalization?.notFoundResponse) return pagesDataNormalization.notFoundResponse;
493
+ const isDataRequest = hasDataRequestHeader || pagesDataNormalization?.isDataReq === true;
365
494
  const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(rawRequest);
366
495
  const filteredHeaders = filterInternalHeaders(rawRequest.headers);
367
496
  if (mwCtx !== null) filteredHeaders.set(VINEXT_MW_CTX_HEADER, mwCtx);
368
497
  const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
369
498
  if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
370
- const request = cloneRequestWithHeaders(rawRequest, filteredHeaders);
499
+ let appRequest = rawRequest;
500
+ if (pagesDataNormalization?.isDataReq) {
501
+ const appRequestUrl = new URL(pagesDataNormalization.request.url);
502
+ appRequestUrl.pathname = addBasePathToPathname(appRequestUrl.pathname, options.basePath);
503
+ appRequest = cloneRequestWithUrl(pagesDataCandidate, appRequestUrl.toString());
504
+ }
505
+ const request = cloneRequestWithHeaders(appRequest, filteredHeaders);
506
+ const pagesDataRequest = pagesDataNormalization?.isDataReq ? cloneRequestWithHeaders(pagesDataCandidate, filteredHeaders) : null;
371
507
  const executionContext = isExecutionContextLike(ctx) ? ctx : getRequestExecutionContext() ?? null;
372
508
  return runWithRequestContext(createRequestContext({
373
509
  headersContext: headersContextFromRequest(request, { draftModeSecret: options.draftModeSecret }),
@@ -378,7 +514,7 @@ function createAppRscHandler(options) {
378
514
  const preMiddlewareRequestContext = requestContextFromRequest(request);
379
515
  let response;
380
516
  try {
381
- response = await handleAppRscRequest(options, request, preMiddlewareRequestContext, isDataRequest);
517
+ response = await handleAppRscRequest(options, request, preMiddlewareRequestContext, isDataRequest, pagesDataRequest);
382
518
  } catch (error) {
383
519
  if (process.env.NODE_ENV !== "production") flattenErrorCauses(error);
384
520
  throw error;
@@ -29,6 +29,7 @@ type AppRscInterceptForMatching = {
29
29
  * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/generate-interception-routes-rewrites.ts
30
30
  */
31
31
  sourceMatchPattern?: string;
32
+ sourcePageSegments?: readonly string[];
32
33
  interceptLayouts: readonly unknown[];
33
34
  page: unknown;
34
35
  __pageLoader?: (() => Promise<unknown>) | null;
@@ -41,6 +42,7 @@ type AppRscSlotForMatching = {
41
42
  type AppRscSiblingInterceptForMatching = {
42
43
  targetPattern: string;
43
44
  sourceMatchPattern: string | null;
45
+ sourcePageSegments?: readonly string[];
44
46
  slotId: string | null;
45
47
  interceptLayouts: readonly unknown[];
46
48
  page: unknown;
@@ -63,6 +65,7 @@ type AppRscInterceptLookupEntry = {
63
65
  targetPatternParts: string[];
64
66
  sourceMatchPattern: string | null;
65
67
  sourceMatchPatternParts: string[] | null;
68
+ sourcePageSegments: readonly string[] | null;
66
69
  interceptLayouts: readonly unknown[];
67
70
  page: unknown;
68
71
  __pageLoader?: (() => Promise<unknown>) | null;
@@ -18,6 +18,7 @@ function appRscPathnameParts(pathname) {
18
18
  function createAppRscRouteMatcher(routes) {
19
19
  const routeTrie = buildRouteTrie(routes);
20
20
  const interceptLookup = createInterceptLookup(routes);
21
+ const routeIndexes = new Map(routes.map((route, index) => [route, index]));
21
22
  return {
22
23
  matchRoute(url) {
23
24
  return trieMatch(routeTrie, appRscPathnameParts(url));
@@ -26,16 +27,19 @@ function createAppRscRouteMatcher(routes) {
26
27
  if (sourcePathname === null) return null;
27
28
  const urlParts = appRscPathnameParts(pathname);
28
29
  const sourceParts = appRscPathnameParts(sourcePathname);
30
+ const matchedSourceRoute = trieMatch(routeTrie, sourceParts);
29
31
  for (const entry of interceptLookup) {
30
32
  if (!matchInterceptSource(sourceParts, entry)) continue;
31
33
  const params = matchAppRscRoutePattern(urlParts, entry.targetPatternParts);
32
34
  if (params === null) continue;
33
- const sourceRoute = routes[entry.sourceRouteIndex];
34
- const matchedSourceParams = sourceRoute ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts) : null;
35
+ const concreteSourceRouteIndex = matchedSourceRoute && entry.sourceMatchPatternParts !== null ? routeIndexes.get(matchedSourceRoute.route) ?? entry.sourceRouteIndex : entry.sourceRouteIndex;
36
+ const sourceRoute = routes[concreteSourceRouteIndex];
37
+ const matchedSourceParams = matchedSourceRoute && entry.sourceMatchPatternParts !== null ? matchedSourceRoute.params : sourceRoute ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts) : null;
35
38
  if (matchedSourceParams === null && entry.sourceMatchPatternParts === null) continue;
36
39
  const sourceParams = matchedSourceParams ?? createRouteParams();
37
40
  return {
38
41
  ...entry,
42
+ sourceRouteIndex: concreteSourceRouteIndex,
39
43
  matchedParams: mergeMatchedParams(sourceParams, params)
40
44
  };
41
45
  }
@@ -78,6 +82,7 @@ function createInterceptLookup(routes) {
78
82
  targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
79
83
  sourceMatchPattern,
80
84
  sourceMatchPatternParts,
85
+ sourcePageSegments: intercept.sourcePageSegments ?? null,
81
86
  interceptLayouts: intercept.interceptLayouts,
82
87
  page: intercept.page,
83
88
  __pageLoader: intercept.__pageLoader,
@@ -96,6 +101,7 @@ function createInterceptLookup(routes) {
96
101
  targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
97
102
  sourceMatchPattern,
98
103
  sourceMatchPatternParts,
104
+ sourcePageSegments: intercept.sourcePageSegments ?? null,
99
105
  interceptLayouts: intercept.interceptLayouts,
100
106
  page: intercept.page,
101
107
  __pageLoader: intercept.__pageLoader,
@@ -33,6 +33,14 @@ type ResolveAppPageSegmentConfigOptions = {
33
33
  */
34
34
  declare function resolveAppPageSegmentConfig(options: ResolveAppPageSegmentConfigOptions): EffectiveAppPageSegmentConfig;
35
35
  declare function resolveAppPageFetchCacheMode(options: ResolveAppPageSegmentConfigOptions): FetchCacheMode | null;
36
+ /**
37
+ * Resolve the `fetchCache` segment config exported by a route handler module.
38
+ *
39
+ * Route handlers have no layout chain, so the module's own export applies
40
+ * directly. Mirrors upstream's app-route module, which copies
41
+ * `userland.fetchCache` into the work store before invoking the handler.
42
+ */
43
+ declare function resolveAppRouteHandlerFetchCacheMode(handler: Pick<AppRouteSegmentConfigModule, "fetchCache">): FetchCacheMode | null;
36
44
  declare function isEdgeRuntime(runtime: string | undefined): boolean;
37
45
  //#endregion
38
- export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig };
46
+ export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig, resolveAppRouteHandlerFetchCacheMode };
@@ -88,8 +88,7 @@ function resolveAppPageSegmentConfig(options) {
88
88
  }
89
89
  if (config.dynamicConfig === "force-dynamic") config.revalidateSeconds = 0;
90
90
  if (config.fetchCache === void 0) {
91
- if (config.dynamicConfig === "force-dynamic") config.fetchCache = "force-no-store";
92
- else if (config.dynamicConfig === "error") config.fetchCache = "only-cache";
91
+ if (config.dynamicConfig === "error") config.fetchCache = "only-cache";
93
92
  }
94
93
  if (config.dynamicParamsConfig === void 0 && (config.dynamicConfig === "error" || config.dynamicConfig === "force-static")) config.dynamicParamsConfig = false;
95
94
  return config;
@@ -97,8 +96,18 @@ function resolveAppPageSegmentConfig(options) {
97
96
  function resolveAppPageFetchCacheMode(options) {
98
97
  return resolveAppPageSegmentConfig(options).fetchCache ?? null;
99
98
  }
99
+ /**
100
+ * Resolve the `fetchCache` segment config exported by a route handler module.
101
+ *
102
+ * Route handlers have no layout chain, so the module's own export applies
103
+ * directly. Mirrors upstream's app-route module, which copies
104
+ * `userland.fetchCache` into the work store before invoking the handler.
105
+ */
106
+ function resolveAppRouteHandlerFetchCacheMode(handler) {
107
+ return isRouteSegmentFetchCache(handler.fetchCache) ? handler.fetchCache : null;
108
+ }
100
109
  function isEdgeRuntime(runtime) {
101
110
  return isEdgeApiRuntime(runtime);
102
111
  }
103
112
  //#endregion
104
- export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig };
113
+ export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig, resolveAppRouteHandlerFetchCacheMode };
@@ -173,6 +173,7 @@ type HandleServerActionRscRequestOptions<TElement, TRoute extends AppServerActio
173
173
  renderToReadableStream: (model: AppServerActionRscModel<TElement>, options: RenderServerActionRscStreamOptions<TTemporaryReferences>) => BodyInit | null | Promise<BodyInit | null>;
174
174
  reportRequestError: AppServerActionErrorReporter;
175
175
  resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;
176
+ resolveRouteDynamicConfig?: (route: TRoute) => string | null | undefined;
176
177
  resolveRouteRuntime?: (route: TRoute) => AppServerActionRouteRuntime;
177
178
  request: Request;
178
179
  sanitizeErrorForClient: (error: unknown) => unknown;