vinext 0.1.7 → 0.1.8

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 (92) hide show
  1. package/dist/check.d.ts +18 -0
  2. package/dist/check.js +37 -17
  3. package/dist/cli.js +2 -2
  4. package/dist/config/next-config.d.ts +2 -1
  5. package/dist/config/next-config.js +3 -0
  6. package/dist/config/server-external-packages.d.ts +4 -0
  7. package/dist/config/server-external-packages.js +91 -0
  8. package/dist/deploy.d.ts +7 -0
  9. package/dist/deploy.js +25 -18
  10. package/dist/entries/app-rsc-entry.js +54 -10
  11. package/dist/entries/app-rsc-manifest.js +8 -0
  12. package/dist/entries/pages-client-entry.js +1 -0
  13. package/dist/entries/pages-server-entry.js +1 -0
  14. package/dist/index.js +46 -20
  15. package/dist/init.js +2 -1
  16. package/dist/plugins/middleware-server-only.d.ts +8 -6
  17. package/dist/plugins/middleware-server-only.js +8 -7
  18. package/dist/plugins/optimize-imports.js +1 -1
  19. package/dist/routing/app-route-graph.d.ts +6 -2
  20. package/dist/routing/app-route-graph.js +61 -13
  21. package/dist/routing/app-router.d.ts +5 -0
  22. package/dist/routing/app-router.js +5 -0
  23. package/dist/routing/file-matcher.d.ts +5 -0
  24. package/dist/routing/file-matcher.js +7 -1
  25. package/dist/server/app-browser-entry.js +42 -147
  26. package/dist/server/app-browser-history-controller.d.ts +2 -1
  27. package/dist/server/app-browser-history-controller.js +6 -2
  28. package/dist/server/app-browser-server-action-client.d.ts +32 -0
  29. package/dist/server/app-browser-server-action-client.js +128 -0
  30. package/dist/server/app-fallback-renderer.d.ts +3 -1
  31. package/dist/server/app-fallback-renderer.js +6 -2
  32. package/dist/server/app-page-boundary-render.d.ts +3 -0
  33. package/dist/server/app-page-boundary-render.js +14 -3
  34. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  35. package/dist/server/app-page-cache-finalizer.js +8 -2
  36. package/dist/server/app-page-dispatch.d.ts +33 -4
  37. package/dist/server/app-page-dispatch.js +62 -90
  38. package/dist/server/app-page-element-builder.d.ts +7 -1
  39. package/dist/server/app-page-element-builder.js +56 -19
  40. package/dist/server/app-page-head.d.ts +16 -1
  41. package/dist/server/app-page-head.js +44 -22
  42. package/dist/server/app-page-params.d.ts +2 -1
  43. package/dist/server/app-page-params.js +8 -1
  44. package/dist/server/app-page-ppr-runtime.d.ts +7 -0
  45. package/dist/server/app-page-ppr-runtime.js +70 -0
  46. package/dist/server/app-page-probe.d.ts +1 -0
  47. package/dist/server/app-page-probe.js +1 -1
  48. package/dist/server/app-page-render.d.ts +4 -1
  49. package/dist/server/app-page-render.js +8 -3
  50. package/dist/server/app-page-request.d.ts +8 -1
  51. package/dist/server/app-page-request.js +23 -11
  52. package/dist/server/app-page-route-wiring.d.ts +6 -1
  53. package/dist/server/app-page-route-wiring.js +30 -8
  54. package/dist/server/app-page-search-params-observation.d.ts +4 -2
  55. package/dist/server/app-page-search-params-observation.js +11 -7
  56. package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
  57. package/dist/server/app-route-handler-dispatch.js +1 -0
  58. package/dist/server/app-route-handler-execution.js +2 -1
  59. package/dist/server/app-route-module-loader.d.ts +2 -0
  60. package/dist/server/app-route-module-loader.js +1 -0
  61. package/dist/server/app-router-entry.js +7 -6
  62. package/dist/server/app-rsc-errors.js +7 -1
  63. package/dist/server/app-rsc-handler.d.ts +2 -1
  64. package/dist/server/app-rsc-handler.js +6 -9
  65. package/dist/server/app-rsc-route-matching.d.ts +7 -0
  66. package/dist/server/app-rsc-route-matching.js +36 -3
  67. package/dist/server/app-segment-config.d.ts +1 -0
  68. package/dist/server/app-segment-config.js +32 -2
  69. package/dist/server/app-server-action-execution.d.ts +4 -0
  70. package/dist/server/app-server-action-execution.js +41 -10
  71. package/dist/server/app-ssr-entry.js +4 -1
  72. package/dist/server/app-static-generation.d.ts +1 -0
  73. package/dist/server/app-static-generation.js +1 -0
  74. package/dist/server/headers.d.ts +3 -1
  75. package/dist/server/headers.js +3 -1
  76. package/dist/server/prod-server.js +15 -6
  77. package/dist/server/worker-utils.d.ts +2 -1
  78. package/dist/server/worker-utils.js +7 -1
  79. package/dist/shims/error-boundary.d.ts +19 -1
  80. package/dist/shims/error-boundary.js +11 -1
  81. package/dist/shims/headers.d.ts +3 -1
  82. package/dist/shims/headers.js +16 -5
  83. package/dist/shims/link.js +16 -12
  84. package/dist/shims/metadata.d.ts +3 -2
  85. package/dist/shims/metadata.js +8 -4
  86. package/dist/shims/router.js +13 -2
  87. package/dist/typegen.js +6 -5
  88. package/dist/utils/path.d.ts +2 -1
  89. package/dist/utils/path.js +1 -1
  90. package/dist/utils/project.d.ts +4 -0
  91. package/dist/utils/project.js +5 -1
  92. package/package.json +7 -3
@@ -1,6 +1,6 @@
1
1
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
2
2
  import { mergeMetadataEntries, mergeViewport, postProcessMetadata, resolveModuleMetadata as resolveModuleMetadata$1, resolveModuleViewport } from "../shims/metadata.js";
3
- import { resolveAppPageSegmentParams } from "./app-page-params.js";
3
+ import { resolveAppPageBranchParams, resolveAppPageSegmentParams } from "./app-page-params.js";
4
4
  import { tagAppPageMetadataError } from "./app-page-execution.js";
5
5
  //#region src/server/app-page-head.ts
6
6
  /**
@@ -24,23 +24,44 @@ async function resolveModuleMetadata(...args) {
24
24
  }
25
25
  function resolveActiveParallelRouteHeadInputs(options) {
26
26
  return Object.entries(options.slots ?? {}).map(([slotKey, slot]) => {
27
- if (options.interceptSlotKey === slotKey && options.interceptPage) return {
28
- layoutModules: options.interceptLayouts ?? [],
29
- pageModule: options.interceptPage,
30
- params: options.interceptParams ?? options.params,
31
- routeSegments: options.routeSegments
32
- };
27
+ const ownerTreePosition = options.layoutTreePositions?.[slot.layoutIndex ?? 0] ?? 0;
28
+ const ownerParams = resolveAppPageSegmentParams(options.routeSegments, ownerTreePosition, options.params);
29
+ if (options.interceptSlotKey === slotKey && options.interceptPage) {
30
+ const interceptLayouts = options.interceptLayouts ?? [];
31
+ return {
32
+ layoutModules: [slot.layout, ...interceptLayouts].filter(isPresent),
33
+ layoutParams: [...slot.layout ? [ownerParams] : [], ...interceptLayouts.filter(isPresent).map((_, index) => {
34
+ const segments = options.interceptLayoutSegments?.[index] ?? [];
35
+ return {
36
+ ...ownerParams,
37
+ ...resolveParallelLayoutParams(options.interceptBranchSegments ?? segments, segments.length, options.interceptParams ?? options.params)
38
+ };
39
+ })],
40
+ layoutTreePositions: [...slot.layout ? [0] : [], ...interceptLayouts.filter(isPresent).map(() => options.routeSegments.length)],
41
+ pageModule: options.interceptPage,
42
+ params: options.interceptParams ?? options.params,
43
+ routeSegments: options.routeSegments
44
+ };
45
+ }
33
46
  return {
34
- layoutModules: slot.layout ? [slot.layout] : [],
47
+ layoutModules: [slot.layout, ...slot.configLayouts ?? []].filter(isPresent),
48
+ layoutParams: [...slot.layout ? [ownerParams] : [], ...(slot.configLayoutTreePositions ?? []).map((treePosition) => ({
49
+ ...ownerParams,
50
+ ...resolveParallelLayoutParams(slot.routeSegments ?? options.routeSegments, treePosition, options.slotParams?.[slotKey] ?? options.params)
51
+ }))],
52
+ layoutTreePositions: [...slot.layout ? [0] : [], ...slot.configLayoutTreePositions ?? []],
35
53
  pageModule: slot.page,
36
- params: options.params,
37
- routeSegments: options.routeSegments
54
+ params: options.slotParams?.[slotKey] ?? options.params,
55
+ routeSegments: slot.routeSegments ?? options.routeSegments
38
56
  };
39
57
  });
40
58
  }
41
59
  function isPresent(value) {
42
60
  return value !== null && value !== void 0;
43
61
  }
62
+ function resolveParallelLayoutParams(routeSegments, treePosition, params) {
63
+ return resolveAppPageBranchParams(routeSegments, treePosition, params);
64
+ }
44
65
  function hasGenerateMetadata(module) {
45
66
  return typeof module?.generateMetadata === "function";
46
67
  }
@@ -111,7 +132,7 @@ async function resolveLayoutViewport(layoutInputs, params, routeSegments) {
111
132
  return resolveModuleViewport(layoutInput.module, layoutParams);
112
133
  }));
113
134
  }
114
- async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackRouteSegments, pageSearchParams, parent) {
135
+ async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackRouteSegments, pageSearchParams, parent, searchParamsObserver) {
115
136
  const params = parallelRoute.params ?? fallbackParams;
116
137
  const routeSegments = parallelRoute.routeSegments ?? fallbackRouteSegments;
117
138
  const metadataResults = [];
@@ -119,13 +140,15 @@ async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackR
119
140
  const metadataSources = [];
120
141
  let accumulatedMetadata = parent;
121
142
  const layoutModules = [...parallelRoute.layoutModules ?? [], parallelRoute.layoutModule].filter(isPresent);
143
+ const layoutTreePositions = parallelRoute.layoutTreePositions ?? [];
144
+ const layoutParams = parallelRoute.layoutParams ?? [];
122
145
  const hasDynamicMetadata = layoutModules.some(hasGenerateMetadata) || hasGenerateMetadata(parallelRoute.pageModule);
123
- const layoutViewportPromises = layoutModules.map((layoutModule) => resolveModuleViewport(layoutModule, params));
124
- const pageViewportPromise = parallelRoute.pageModule ? resolveModuleViewport(parallelRoute.pageModule, params) : Promise.resolve(null);
146
+ const layoutViewportPromises = layoutModules.map((layoutModule, index) => resolveModuleViewport(layoutModule, layoutParams[index] ?? resolveParallelLayoutParams(routeSegments, layoutTreePositions[index] ?? 0, params)));
147
+ const pageViewportPromise = parallelRoute.pageModule ? resolveModuleViewport(parallelRoute.pageModule, params, pageSearchParams, searchParamsObserver) : Promise.resolve(null);
125
148
  for (const layoutViewportPromise of layoutViewportPromises) layoutViewportPromise.catch(() => null);
126
149
  pageViewportPromise.catch(() => null);
127
- for (const layoutModule of layoutModules) {
128
- const layoutMetadata = await resolveModuleMetadata(layoutModule, params, void 0, accumulatedMetadata);
150
+ for (const [index, layoutModule] of layoutModules.entries()) {
151
+ const layoutMetadata = await resolveModuleMetadata(layoutModule, layoutParams[index] ?? resolveParallelLayoutParams(routeSegments, layoutTreePositions[index] ?? 0, params), void 0, accumulatedMetadata);
129
152
  metadataResults.push(layoutMetadata);
130
153
  metadataSources.push({
131
154
  metadata: layoutMetadata,
@@ -137,7 +160,7 @@ async function resolveParallelRouteHead(parallelRoute, fallbackParams, fallbackR
137
160
  }
138
161
  }
139
162
  if (parallelRoute.pageModule) {
140
- const pageMetadata = await resolveModuleMetadata(parallelRoute.pageModule, params, pageSearchParams, accumulatedMetadata);
163
+ const pageMetadata = await resolveModuleMetadata(parallelRoute.pageModule, params, pageSearchParams, accumulatedMetadata, searchParamsObserver);
141
164
  metadataResults.push(pageMetadata);
142
165
  metadataSources.push({
143
166
  metadata: pageMetadata,
@@ -170,9 +193,9 @@ async function resolveAppPageHeadInner(options) {
170
193
  layoutMetadataResultsForParent.catch(() => null);
171
194
  const pageParentPromise = layoutMetadataResultsForParent.then((metadataResults) => metadataResults.length > 0 ? mergeMetadataEntries(metadataResults.map((metadata) => ({ metadata }))) : {});
172
195
  pageParentPromise.catch(() => null);
173
- const pageMetadataPromise = options.pageModule ? resolveModuleMetadata(options.pageModule, options.params, pageSearchParams, pageParentPromise) : Promise.resolve(null);
174
- const pageViewportPromise = options.pageModule ? resolveModuleViewport(options.pageModule, options.params) : Promise.resolve(null);
175
- const parallelRouteHeadPromise = Promise.all((options.parallelRoutes ?? []).map((parallelRoute) => resolveParallelRouteHead(parallelRoute, options.params, routeSegments, pageSearchParams, pageParentPromise)));
196
+ const pageMetadataPromise = options.pageModule ? resolveModuleMetadata(options.pageModule, options.params, pageSearchParams, pageParentPromise, options.searchParamsObserver) : Promise.resolve(null);
197
+ const pageViewportPromise = options.pageModule ? resolveModuleViewport(options.pageModule, options.params, pageSearchParams, options.searchParamsObserver) : Promise.resolve(null);
198
+ const parallelRouteHeadPromise = Promise.all((options.parallelRoutes ?? []).map((parallelRoute) => resolveParallelRouteHead(parallelRoute, options.params, routeSegments, pageSearchParams, pageParentPromise, options.searchParamsObserver)));
176
199
  const [layoutMetadataResults, layoutViewportResults, pageMetadata, pageViewport, parallelRouteHeads] = await Promise.all([
177
200
  layoutMetadataPromise,
178
201
  layoutViewportPromise,
@@ -205,9 +228,8 @@ async function resolveAppPageHeadInner(options) {
205
228
  const metadataSources = createMetadataSources(layoutMetadataResults, routeSegments, layoutSourcePositions, pageMetadata, Boolean(options.pageModule));
206
229
  metadataSources.push(...parallelMetadataSources);
207
230
  let metadata = resolvedMetadataBase;
208
- if (options.metadataRoutes.length > 0) try {
209
- const { applyFileBasedMetadata } = await import("./file-based-metadata.js");
210
- metadata = await applyFileBasedMetadata(resolvedMetadataBase, options.routePath, options.params, options.metadataRoutes, {
231
+ if (options.applyFileBasedMetadata && options.metadataRoutes.length > 0) try {
232
+ metadata = await options.applyFileBasedMetadata(resolvedMetadataBase, options.routePath, options.params, options.metadataRoutes, {
211
233
  routeSegments,
212
234
  metadataSources,
213
235
  basePath: options.basePath ?? ""
@@ -4,5 +4,6 @@ import { AppPageParams } from "./app-page-boundary.js";
4
4
  declare function getAppPageSegmentParamName(segment: string): string | null;
5
5
  declare function resolveAppPageSegmentParamScopeKeys(routeSegments: readonly string[] | null | undefined, treePosition: number): readonly string[];
6
6
  declare function resolveAppPageSegmentParams(routeSegments: readonly string[] | null | undefined, treePosition: number, matchedParams: AppPageParams): AppPageParams;
7
+ declare function resolveAppPageBranchParams(branchSegments: readonly string[], treePosition: number, matchedParams: AppPageParams, scopedSegments?: readonly string[]): AppPageParams;
7
8
  //#endregion
8
- export { getAppPageSegmentParamName, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
9
+ export { getAppPageSegmentParamName, resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
@@ -35,5 +35,12 @@ function resolveAppPageSegmentParams(routeSegments, treePosition, matchedParams)
35
35
  }
36
36
  return segmentParams;
37
37
  }
38
+ function resolveAppPageBranchParams(branchSegments, treePosition, matchedParams, scopedSegments = branchSegments) {
39
+ const branchParamNames = new Set(branchSegments.map(getAppPageSegmentParamName).filter((name) => name !== null));
40
+ const scopedParams = {};
41
+ for (const [name, value] of Object.entries(matchedParams)) if (!branchParamNames.has(name)) scopedParams[name] = value;
42
+ Object.assign(scopedParams, resolveAppPageSegmentParams(scopedSegments, treePosition, matchedParams));
43
+ return scopedParams;
44
+ }
38
45
  //#endregion
39
- export { getAppPageSegmentParamName, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
46
+ export { getAppPageSegmentParamName, resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams };
@@ -0,0 +1,7 @@
1
+ import { createAppPprFallbackShells } from "./app-ppr-fallback-shell.js";
2
+ import { AppPageDispatchRoute, AppPagePprRuntime } from "./app-page-dispatch.js";
3
+
4
+ //#region src/server/app-page-ppr-runtime.d.ts
5
+ declare const appPagePprRuntime: AppPagePprRuntime<AppPageDispatchRoute>;
6
+ //#endregion
7
+ export { appPagePprRuntime, createAppPprFallbackShells };
@@ -0,0 +1,70 @@
1
+ import { beginPprFallbackShellFinalRender, createPprFallbackShellState, getPprFallbackShellState, runWithPprFallbackShellState } from "../shims/ppr-fallback-shell.js";
2
+ import { createAppPprFallbackShells } from "./app-ppr-fallback-shell.js";
3
+ import { hasSearchParams, shouldReadAppPageCache } from "./app-page-dispatch.js";
4
+ //#region src/server/app-page-ppr-runtime.ts
5
+ function classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
6
+ if (options.renderedConcreteUrlPaths?.has(options.cleanPathname) === true) return { kind: "skip-known-pregenerated-route" };
7
+ const fallbackShells = options.pprFallbackCacheShells;
8
+ if (!fallbackShells || fallbackShells.length === 0) return { kind: "skip-no-fallback-shells" };
9
+ if (options.isRscRequest) return { kind: "skip-rsc-request" };
10
+ if (options.request.method !== "GET") return { kind: "skip-non-get" };
11
+ if (!isForceStatic && hasSearchParams(options.searchParams)) return { kind: "skip-search-params" };
12
+ if (!shouldReadAppPageCache({
13
+ isDraftMode,
14
+ isForceDynamic,
15
+ isProgressiveActionRender: options.isProgressiveActionRender === true,
16
+ isProduction: options.isProduction,
17
+ isRscRequest: false,
18
+ revalidateSeconds: currentRevalidateSeconds,
19
+ scriptNonce: options.scriptNonce
20
+ })) return { kind: "skip-cache-disabled" };
21
+ return {
22
+ kind: "probe-fallback-shells",
23
+ fallbackShells
24
+ };
25
+ }
26
+ async function probePprFallbackShellCache(options, fallbackShells, currentRevalidateSeconds) {
27
+ const { readAppPageFallbackShellCacheResponse } = await import("./app-page-cache.js");
28
+ const { rewriteAppPprFallbackShellHtmlNavigation } = await import("./app-ppr-fallback-shell.js");
29
+ for (const fallbackShell of fallbackShells) {
30
+ const fallbackShellResponse = await readAppPageFallbackShellCacheResponse({
31
+ clearRequestContext: options.clearRequestContext,
32
+ expireSeconds: options.expireSeconds,
33
+ fallbackPathname: fallbackShell.pathname,
34
+ isEdgeRuntime: options.isEdgeRuntime,
35
+ isrDebug: options.isrDebug,
36
+ isrGet: options.isrGet,
37
+ isrHtmlKey: options.isrHtmlKey,
38
+ middlewareHeaders: options.middlewareContext.headers,
39
+ middlewareStatus: options.middlewareContext.status,
40
+ revalidateSeconds: currentRevalidateSeconds ?? 0,
41
+ rewriteHtml(html) {
42
+ return rewriteAppPprFallbackShellHtmlNavigation({
43
+ html,
44
+ params: options.params,
45
+ pathname: options.cleanPathname,
46
+ searchParams: options.searchParams
47
+ });
48
+ }
49
+ });
50
+ if (fallbackShellResponse) return fallbackShellResponse;
51
+ }
52
+ return null;
53
+ }
54
+ const appPagePprRuntime = {
55
+ beginFinalRender: beginPprFallbackShellFinalRender,
56
+ getState: getPprFallbackShellState,
57
+ run(shell, fn) {
58
+ return runWithPprFallbackShellState(createPprFallbackShellState(shell), fn);
59
+ },
60
+ async tryServe(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
61
+ const decision = classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic);
62
+ return decision.kind === "probe-fallback-shells" ? probePprFallbackShellCache(options, decision.fallbackShells, currentRevalidateSeconds) : null;
63
+ },
64
+ async warm(options) {
65
+ const { warmPprFallbackShellCaches } = await import("./app-ppr-fallback-shell-render.js");
66
+ await warmPprFallbackShellCaches(options);
67
+ }
68
+ };
69
+ //#endregion
70
+ export { appPagePprRuntime, createAppPprFallbackShells };
@@ -119,6 +119,7 @@ type ProbeAppPageBeforeRenderResult = {
119
119
  };
120
120
  type ProbeAppPageBeforeRenderOptions = {
121
121
  hasLoadingBoundary: boolean;
122
+ probePageBeforeRender?: boolean;
122
123
  skipProbes?: boolean;
123
124
  layoutCount: number;
124
125
  probeLayoutAt: (layoutIndex: number) => unknown;
@@ -252,7 +252,7 @@ async function probeAppPageBeforeRender(options) {
252
252
  layoutFlags
253
253
  };
254
254
  }
255
- if (options.hasLoadingBoundary) return {
255
+ if (options.hasLoadingBoundary || options.probePageBeforeRender === false) return {
256
256
  response: null,
257
257
  layoutFlags
258
258
  };
@@ -37,6 +37,7 @@ type RenderAppPageLifecycleOptions = {
37
37
  cleanPathname: string;
38
38
  clearRequestContext: () => void;
39
39
  consumeDynamicUsage: () => boolean;
40
+ peekDynamicUsage?: () => boolean;
40
41
  consumeRenderObservationState?: () => AppPageRenderObservationState; /** Read and clear any invalid dynamic usage error recorded during render (dev-only). */
41
42
  consumeInvalidDynamicUsageError?: () => unknown;
42
43
  createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
@@ -60,6 +61,8 @@ type RenderAppPageLifecycleOptions = {
60
61
  isProgressiveActionRender?: boolean;
61
62
  isPrerender?: boolean;
62
63
  isProduction: boolean;
64
+ probePageBeforeRender?: boolean;
65
+ omitPendingDynamicCacheState?: boolean;
63
66
  isRscRequest: boolean;
64
67
  isrDebug?: AppPageDebugLogger;
65
68
  isrHtmlKey: (pathname: string) => string;
@@ -81,7 +84,7 @@ type RenderAppPageLifecycleOptions = {
81
84
  expireSeconds?: number;
82
85
  formState?: ReactFormState | null;
83
86
  revalidateSeconds: number | null;
84
- renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;
87
+ renderErrorBoundaryResponse: (error: unknown, errorOrigin: "rsc" | "ssr") => Promise<Response | null>;
85
88
  renderLayoutSpecialError: (specialError: AppPageSpecialError, layoutIndex: number) => Promise<Response>;
86
89
  renderPageSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;
87
90
  renderToReadableStream: (element: ReactNode | AppOutgoingElements, options: {
@@ -248,8 +248,11 @@ function wrapRscResponseForDevErrorReporting(response, consumeInvalidDynamicUsag
248
248
  });
249
249
  }
250
250
  async function renderAppPageLifecycle(options) {
251
+ const configuredProbePageBeforeRender = options.probePageBeforeRender ?? options.isRscRequest;
252
+ const probePageBeforeRender = options.isRscRequest || configuredProbePageBeforeRender && !(options.peekDynamicUsage?.() ?? false);
251
253
  const preRenderResult = await probeAppPageBeforeRender({
252
254
  hasLoadingBoundary: options.hasLoadingBoundary,
255
+ probePageBeforeRender,
253
256
  skipProbes: options.pprFallbackShellSignal !== void 0,
254
257
  layoutCount: options.layoutCount,
255
258
  probeLayoutAt(layoutIndex) {
@@ -430,7 +433,8 @@ async function renderAppPageLifecycle(options) {
430
433
  if (!options.isProduction) renderEnd = performance.now();
431
434
  },
432
435
  renderErrorBoundaryResponse(error) {
433
- return options.renderErrorBoundaryResponse(rscErrorTracker.getCapturedError() ?? error);
436
+ const capturedRscError = rscErrorTracker.getCapturedError();
437
+ return options.renderErrorBoundaryResponse(capturedRscError ?? error, capturedRscError === null ? "ssr" : "rsc");
434
438
  },
435
439
  async renderHtmlStream() {
436
440
  const ssrHandler = await options.loadSsrHandler();
@@ -462,7 +466,7 @@ async function renderAppPageLifecycle(options) {
462
466
  if (!htmlStream) throw new Error("[vinext] Expected an HTML stream when no fallback response was returned");
463
467
  const linkHeader = buildAppPageLinkHeader(htmlRender.linkHeader, fontLinkHeader, options.reactMaxHeadersLength);
464
468
  if (options.isPrerender === true) await htmlRender.metadataReady;
465
- if (options.hasLoadingBoundary) {
469
+ if (options.hasLoadingBoundary || !probePageBeforeRender) {
466
470
  const captured = rscErrorTracker.getCapturedSpecialError();
467
471
  if (captured) {
468
472
  const specialError = resolveAppPageSpecialError(captured);
@@ -480,8 +484,8 @@ async function renderAppPageLifecycle(options) {
480
484
  revalidateSeconds
481
485
  }));
482
486
  }
487
+ let dynamicUsedDuringRender = options.consumeDynamicUsage();
483
488
  const draftCookie = options.getDraftModeCookieHeader();
484
- const dynamicUsedDuringRender = options.consumeDynamicUsage();
485
489
  let dynamicUsedBeforeContextCleanup = dynamicUsedDuringRender;
486
490
  const safeHtmlStream = deferUntilStreamConsumed(htmlStream, () => {
487
491
  dynamicUsedBeforeContextCleanup = dynamicUsedBeforeContextCleanup || options.consumeDynamicUsage();
@@ -575,6 +579,7 @@ async function renderAppPageLifecycle(options) {
575
579
  isrRscKey: options.isrRscKey,
576
580
  isrSet: options.isrSet,
577
581
  interceptionContext: options.interceptionContext,
582
+ omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
578
583
  preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,
579
584
  expireSeconds,
580
585
  revalidateSeconds,
@@ -40,8 +40,11 @@ type BuildAppPageElementResult<TElement> = {
40
40
  };
41
41
  type AppPageInterceptMatch<TPage = unknown> = {
42
42
  interceptLayouts?: readonly unknown[] | null;
43
+ interceptLayoutSegments?: readonly (readonly string[])[] | null;
44
+ interceptBranchSegments?: readonly string[] | null;
43
45
  __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
44
46
  matchedParams: AppPageParams;
47
+ sourceMatchedParams?: AppPageParams;
45
48
  page: TPage;
46
49
  __pageLoader?: (() => Promise<TPage>) | null;
47
50
  __loadState?: {
@@ -88,7 +91,10 @@ type ResolveAppPageInterceptionRerenderTargetResult<TRoute, TInterceptOpts> = {
88
91
  type ResolveAppPageActionRerenderTargetOptions<TRoute, TPage, TInterceptOpts> = ResolveAppPageInterceptionRerenderTargetOptions<TRoute, TPage, TInterceptOpts>;
89
92
  type ResolveAppPageActionRerenderTargetResult<TRoute, TInterceptOpts> = ResolveAppPageInterceptionRerenderTargetResult<TRoute, TInterceptOpts>;
90
93
  type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
91
- buildPageElement: (route: TRoute, params: AppPageParams, interceptOpts: TInterceptOpts | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<TElement>;
94
+ buildPageElement: (route: TRoute, params: AppPageParams, interceptOpts: TInterceptOpts | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker, buildOptions?: {
95
+ observeMetadataSearchParamsAccess?: boolean;
96
+ observePageSearchParamsAccess?: boolean;
97
+ }) => Promise<TElement>;
92
98
  cleanPathname: string;
93
99
  currentRoute: TRoute;
94
100
  findIntercept: (pathname: string) => AppPageInterceptMatch<TPage> | null;
@@ -98,6 +104,7 @@ type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
98
104
  layoutParamAccess?: AppLayoutParamAccessTracker;
99
105
  resolveNavigationParams: (route: TRoute, params: AppPageParams, pathname: string, interceptOpts: TInterceptOpts) => AppPageParams;
100
106
  renderInterceptResponse: (route: TRoute, element: TElement) => Promise<Response> | Response;
107
+ resolveSearchParams?: (route: TRoute, searchParams: URLSearchParams) => Awaitable<URLSearchParams>;
101
108
  searchParams: URLSearchParams;
102
109
  setNavigationContext: (context: {
103
110
  params: AppPageParams;
@@ -97,7 +97,7 @@ async function resolveAppPageInterceptMatch(options) {
97
97
  return {
98
98
  interceptOpts: options.toInterceptOpts(interceptState.intercept),
99
99
  matchedParams: interceptState.intercept.matchedParams,
100
- sourceParams: pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
100
+ sourceParams: pickRouteParams(interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
101
101
  sourceRoute: interceptState.sourceRoute
102
102
  };
103
103
  }
@@ -145,12 +145,18 @@ async function resolveAppPageInterceptionRerenderTarget(options) {
145
145
  isRscRequest: options.isRscRequest,
146
146
  toInterceptOpts: options.toInterceptOpts
147
147
  });
148
- if (interceptState.kind === "source-route") return {
149
- interceptOpts: options.toInterceptOpts(interceptState.intercept),
150
- navigationParams: interceptState.intercept.matchedParams,
151
- params: pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
152
- route: interceptState.sourceRoute
153
- };
148
+ if (interceptState.kind === "source-route") {
149
+ const sourceMatchedParams = interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams;
150
+ return {
151
+ interceptOpts: options.toInterceptOpts(interceptState.intercept),
152
+ navigationParams: {
153
+ ...sourceMatchedParams,
154
+ ...interceptState.intercept.matchedParams
155
+ },
156
+ params: pickRouteParams(sourceMatchedParams, options.getRouteParamNames(interceptState.sourceRoute)),
157
+ route: interceptState.sourceRoute
158
+ };
159
+ }
154
160
  return {
155
161
  interceptOpts: interceptState.kind === "current-route" ? options.toInterceptOpts(interceptState.intercept) : void 0,
156
162
  navigationParams: options.currentParams,
@@ -174,13 +180,19 @@ async function resolveAppPageIntercept(options) {
174
180
  if (interceptState.kind === "source-route") {
175
181
  const renderRoute = interceptState.sourceRoute;
176
182
  const interceptOpts = options.toInterceptOpts(interceptState.intercept);
177
- const renderParams = pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute));
183
+ const sourceMatchedParams = interceptState.intercept.sourceMatchedParams ?? interceptState.intercept.matchedParams;
184
+ const navigationParams = {
185
+ ...sourceMatchedParams,
186
+ ...interceptState.intercept.matchedParams
187
+ };
188
+ const renderSearchParams = options.resolveSearchParams ? await options.resolveSearchParams(renderRoute, options.searchParams) : options.searchParams;
189
+ const renderParams = pickRouteParams(sourceMatchedParams, options.getRouteParamNames(interceptState.sourceRoute));
178
190
  options.setNavigationContext({
179
- params: options.resolveNavigationParams(renderRoute, interceptState.intercept.matchedParams, options.cleanPathname, interceptOpts),
191
+ params: options.resolveNavigationParams(renderRoute, navigationParams, options.cleanPathname, interceptOpts),
180
192
  pathname: options.cleanPathname,
181
- searchParams: options.searchParams
193
+ searchParams: renderSearchParams
182
194
  });
183
- const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, options.searchParams, options.layoutParamAccess);
195
+ const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, renderSearchParams, options.layoutParamAccess);
184
196
  return {
185
197
  interceptOpts: void 0,
186
198
  response: await options.renderInterceptResponse(renderRoute, interceptElement)
@@ -2,9 +2,9 @@ import { AppRouteSemanticIds } from "../routing/app-route-graph.js";
2
2
  import { AppElements, AppElementsInterception } from "./app-elements-wire.js";
3
3
  import { AppPageParams } from "./app-page-boundary.js";
4
4
  import { ThenableParamsObserver } from "../shims/thenable-params.js";
5
+ import { Metadata, Viewport } from "../shims/metadata.js";
5
6
  import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
6
7
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
7
- import { Metadata, Viewport } from "../shims/metadata.js";
8
8
  import { AppPageRenderIdentity } from "./app-page-render-identity.js";
9
9
  import { resolveAppPageChildSegments } from "./app-page-segment-state.js";
10
10
  import { ComponentType, ReactNode } from "react";
@@ -31,6 +31,8 @@ type AppPageRouteWiringSlot<TModule extends AppPageModule = AppPageModule, TErro
31
31
  /** Graph-owned semantic slot identity. */id?: string | null; /** Slot prop name passed to the owning layout (e.g. "modal" from @modal). */
32
32
  name: string;
33
33
  default?: TModule | null;
34
+ configLayouts?: readonly (TModule | null | undefined)[] | null;
35
+ configLayoutTreePositions?: readonly number[] | null;
34
36
  error?: TErrorModule | null;
35
37
  layout?: TModule | null;
36
38
  layoutIndex: number;
@@ -83,6 +85,8 @@ type AppPageRouteWiringRoute<TModule extends AppPageModule = AppPageModule, TErr
83
85
  templates?: readonly (TModule | null | undefined)[] | null;
84
86
  };
85
87
  type AppPageSlotOverride<TModule extends AppPageModule = AppPageModule> = {
88
+ branchSegments?: readonly string[] | null;
89
+ layoutSegments?: readonly (readonly string[])[] | null;
86
90
  layoutModules?: readonly (TModule | null | undefined)[] | null;
87
91
  /**
88
92
  * The page module to render for this slot. Optional — when omitted, the
@@ -118,6 +122,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
118
122
  rootNotFoundModule?: TModule | null;
119
123
  rootUnauthorizedModule?: TModule | null;
120
124
  route: AppPageRouteWiringRoute<TModule, TErrorModule>;
125
+ createPageElement?: (component: AppPageComponent, props: Readonly<Record<string, unknown>>) => ReactNode;
121
126
  searchParams?: unknown;
122
127
  slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;
123
128
  };
@@ -8,7 +8,7 @@ import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
8
8
  import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
9
9
  import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
10
10
  import { Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
11
- import { resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
11
+ import { resolveAppPageBranchParams, resolveAppPageSegmentParamScopeKeys, resolveAppPageSegmentParams } from "./app-page-params.js";
12
12
  import { probeReactServerSubtree } from "./app-page-probe.js";
13
13
  import { resolveAppPageChildSegments, resolveAppPageRouteStateKey, resolveAppPageSegmentStateKey } from "./app-page-segment-state.js";
14
14
  import { Fragment, Suspense } from "react";
@@ -16,6 +16,9 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
16
  //#region src/server/app-page-route-wiring.tsx
17
17
  const APP_PAGE_LAYOUT_PROBE_CHILD = /* @__PURE__ */ jsx(Fragment, {});
18
18
  const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
19
+ function resolveSlotLayoutParams(routeSegments, treePosition, params) {
20
+ return resolveAppPageBranchParams(routeSegments, treePosition, params);
21
+ }
19
22
  function getDefaultExport(module) {
20
23
  return module?.default ?? null;
21
24
  }
@@ -293,7 +296,9 @@ function buildAppPageElements(options) {
293
296
  const slotId = resolveAppPageSlotId(slot, layoutEntries[targetIndex]?.treePath ?? "/");
294
297
  const slotOverride = resolveSlotOverride(slotKey, slotName);
295
298
  const slotParams = getEffectiveSlotParams(slotKey, slotName);
296
- const slotResetKey = resolveAppPageRouteStateKey(slot.routeSegments ?? [], slotParams);
299
+ const slotRouteSegments = slot.routeSegments ?? [];
300
+ const slotOwnerParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntries[targetIndex]?.treePosition ?? 0, options.matchedParams);
301
+ const slotResetKey = resolveAppPageRouteStateKey(slotRouteSegments, slotParams);
297
302
  const overrideOrPageComponent = getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page);
298
303
  const defaultComponent = getDefaultExport(slot.default);
299
304
  if (!overrideOrPageComponent && defaultComponent && options.isRscRequest && options.mountedSlotIds?.has(slotId)) continue;
@@ -302,23 +307,40 @@ function buildAppPageElements(options) {
302
307
  elements[slotId] = AppElementsWire.unmatchedSlotValue;
303
308
  continue;
304
309
  }
305
- const slotThenableParams = options.makeThenableParams(slotParams);
306
- const slotProps = { params: slotThenableParams };
310
+ const slotProps = { params: options.makeThenableParams(slotParams) };
307
311
  if (options.searchParams !== void 0) slotProps.searchParams = options.searchParams;
308
312
  if (slotOverride?.props) Object.assign(slotProps, slotOverride.props);
309
- let slotElement = /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
313
+ let slotElement = options.createPageElement ? options.createPageElement(slotComponent, slotProps) : (() => {
314
+ return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
315
+ })();
316
+ const hasSlotTreeOverride = slotOverride?.pageModule != null || slotOverride?.layoutModules !== void 0;
310
317
  const interceptLayouts = slotOverride?.layoutModules ?? [];
311
318
  for (let layoutIndex = interceptLayouts.length - 1; layoutIndex >= 0; layoutIndex--) {
312
319
  const interceptLayoutComponent = getDefaultExport(interceptLayouts[layoutIndex]);
313
320
  if (!interceptLayoutComponent) continue;
314
- slotElement = /* @__PURE__ */ jsx(interceptLayoutComponent, {
315
- params: slotThenableParams,
321
+ const InterceptLayoutComponent = interceptLayoutComponent;
322
+ const interceptLayoutParams = resolveSlotLayoutParams(slotOverride?.branchSegments ?? slotRouteSegments, slotOverride?.layoutSegments?.[layoutIndex]?.length ?? slotRouteSegments.length, slotParams);
323
+ slotElement = /* @__PURE__ */ jsx(InterceptLayoutComponent, {
324
+ params: options.makeThenableParams(interceptLayoutParams),
325
+ children: slotElement
326
+ });
327
+ }
328
+ if (!hasSlotTreeOverride) for (let layoutIndex = (slot.configLayouts?.length ?? 0) - 1; layoutIndex >= 0; layoutIndex--) {
329
+ const nestedLayoutComponent = getDefaultExport(slot.configLayouts?.[layoutIndex]);
330
+ if (!nestedLayoutComponent) continue;
331
+ const NestedLayoutComponent = nestedLayoutComponent;
332
+ const nestedLayoutParams = resolveSlotLayoutParams(slotRouteSegments, slot.configLayoutTreePositions?.[layoutIndex] ?? 0, slotParams);
333
+ slotElement = /* @__PURE__ */ jsx(NestedLayoutComponent, {
334
+ params: options.makeThenableParams({
335
+ ...slotOwnerParams,
336
+ ...nestedLayoutParams
337
+ }),
316
338
  children: slotElement
317
339
  });
318
340
  }
319
341
  const slotLayoutComponent = getDefaultExport(slot.layout);
320
342
  if (slotLayoutComponent) slotElement = /* @__PURE__ */ jsx(slotLayoutComponent, {
321
- params: slotThenableParams,
343
+ params: options.makeThenableParams(slotOwnerParams),
322
344
  children: slotElement
323
345
  });
324
346
  const slotLoadingComponent = getDefaultExport(slot.loading);
@@ -1,10 +1,12 @@
1
- import { ThenableParams } from "../shims/thenable-params.js";
1
+ import { ThenableParams, ThenableParamsObserver } from "../shims/thenable-params.js";
2
2
  import { AppPageSearchParams } from "./app-page-head.js";
3
3
 
4
4
  //#region src/server/app-page-search-params-observation.d.ts
5
5
  type AppPageSearchParamsObservationOptions = {
6
+ markDynamic?: boolean;
6
7
  observeReactPromiseStatus?: boolean;
7
8
  };
9
+ declare function createAppPageSearchParamsObserver(options?: AppPageSearchParamsObservationOptions): ThenableParamsObserver;
8
10
  declare function makeObservedAppPageSearchParamsThenable(pageSearchParams: AppPageSearchParams, options?: AppPageSearchParamsObservationOptions): ThenableParams<AppPageSearchParams>;
9
11
  //#endregion
10
- export { makeObservedAppPageSearchParamsThenable };
12
+ export { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable };
@@ -1,15 +1,19 @@
1
- import { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope } from "../shims/headers.js";
1
+ import { markDynamicUsage, markRenderRequestApiUsage, throwIfInsideCacheScope, throwIfStaticGenerationAccessError } from "../shims/headers.js";
2
2
  import { makeThenableParams } from "../shims/thenable-params.js";
3
3
  //#region src/server/app-page-search-params-observation.ts
4
- function markAppPageSearchParamsAccess() {
4
+ function markAppPageSearchParamsAccess(markDynamic) {
5
+ throwIfStaticGenerationAccessError();
5
6
  throwIfInsideCacheScope("searchParams");
6
- markDynamicUsage();
7
+ if (markDynamic) markDynamicUsage();
7
8
  markRenderRequestApiUsage("searchParams");
8
9
  }
9
- function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {}) {
10
- const observer = { observeParamAccess() {
11
- markAppPageSearchParamsAccess();
10
+ function createAppPageSearchParamsObserver(options = {}) {
11
+ return { observeParamAccess() {
12
+ markAppPageSearchParamsAccess(options.markDynamic !== false);
12
13
  } };
14
+ }
15
+ function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {}) {
16
+ const observer = createAppPageSearchParamsObserver(options);
13
17
  if (options.observeReactPromiseStatus === true) return makeThenableParams(pageSearchParams, {
14
18
  ...observer,
15
19
  observeReactPromiseStatus: true
@@ -17,4 +21,4 @@ function makeObservedAppPageSearchParamsThenable(pageSearchParams, options = {})
17
21
  return makeThenableParams(pageSearchParams, observer);
18
22
  }
19
23
  //#endregion
20
- export { makeObservedAppPageSearchParamsThenable };
24
+ export { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable };
@@ -4,7 +4,7 @@ import { ReactNode } from "react";
4
4
  //#region src/server/app-ppr-fallback-shell-render.d.ts
5
5
  type AppPageBoundaryOnError = (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
6
6
  type AppPageRenderableElement = ReactNode | Record<string, ReactNode>;
7
- declare function warmPprFallbackShellCaches(options: {
7
+ type WarmPprFallbackShellCachesOptions = {
8
8
  element: AppPageRenderableElement;
9
9
  onError: AppPageBoundaryOnError;
10
10
  renderToReadableStream: (element: AppPageRenderableElement, options: {
@@ -12,6 +12,7 @@ declare function warmPprFallbackShellCaches(options: {
12
12
  signal?: AbortSignal;
13
13
  }) => ReadableStream<Uint8Array>;
14
14
  state: PprFallbackShellState;
15
- }): Promise<void>;
15
+ };
16
+ declare function warmPprFallbackShellCaches(options: WarmPprFallbackShellCachesOptions): Promise<void>;
16
17
  //#endregion
17
- export { warmPprFallbackShellCaches };
18
+ export { WarmPprFallbackShellCachesOptions, warmPprFallbackShellCaches };
@@ -24,6 +24,7 @@ function buildRouteHandlerPageCacheTags(pathname, extraTags, routeSegments) {
24
24
  async function runInRouteHandlerRevalidationContext(options, renderFn) {
25
25
  await runWithRequestContext(createRequestContext({
26
26
  headersContext: createStaticGenerationHeadersContext({
27
+ draftModeEnabled: false,
27
28
  draftModeSecret: options.draftModeSecret,
28
29
  dynamicConfig: options.dynamicConfig,
29
30
  routeKind: "route",
@@ -1,4 +1,4 @@
1
- import { setHeadersContext } from "../shims/headers.js";
1
+ import { isDraftModeRequest, setHeadersContext } from "../shims/headers.js";
2
2
  import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
3
3
  import { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss } from "./app-route-handler-response.js";
4
4
  import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
@@ -8,6 +8,7 @@ import { resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidat
8
8
  function configureAppRouteStaticGenerationContext(options) {
9
9
  if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") {
10
10
  setHeadersContext(createStaticGenerationHeadersContext({
11
+ draftModeEnabled: options.draftModeSecret !== void 0 && isDraftModeRequest(options.request, options.draftModeSecret),
11
12
  draftModeSecret: options.draftModeSecret,
12
13
  dynamicConfig: options.dynamicConfig,
13
14
  routeKind: "route",
@@ -36,11 +36,13 @@ type LazyLoadableSlot = {
36
36
  page?: unknown;
37
37
  default?: unknown;
38
38
  layout?: unknown;
39
+ configLayouts?: readonly unknown[];
39
40
  loading?: unknown;
40
41
  error?: unknown;
41
42
  __loadPage?: LazyModuleThunk | null;
42
43
  __loadDefault?: LazyModuleThunk | null;
43
44
  __loadLayout?: LazyModuleThunk | null;
45
+ __loadConfigLayouts?: LazyModuleLoaderArray | null;
44
46
  __loadLoading?: LazyModuleThunk | null;
45
47
  __loadError?: LazyModuleThunk | null; /** Hydrated only after an intercept matches, not with the slot's base modules. */
46
48
  intercepts?: LazyLoadableIntercept[];