vinext 1.4.1 → 1.4.3
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.
- package/README.md +5 -2
- package/dist/build/action-owner-manifest.js +1 -0
- package/dist/build/prerender-paths.d.ts +11 -1
- package/dist/build/prerender-paths.js +36 -10
- package/dist/check.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/client/dev-error-overlay.d.ts +2 -1
- package/dist/client/dev-error-overlay.js +8 -3
- package/dist/config/config-matchers.js +8 -4
- package/dist/config/destination-params.js +5 -2
- package/dist/config/next-config.d.ts +25 -1
- package/dist/config/next-config.js +31 -1
- package/dist/entries/app-rsc-entry.js +65 -30
- package/dist/entries/app-rsc-manifest.js +4 -0
- package/dist/entries/pages-server-entry.js +19 -4
- package/dist/index.js +37 -37
- package/dist/init-cloudflare.js +18 -2
- package/dist/init-platform.js +2 -2
- package/dist/init.js +42 -5
- package/dist/plugins/css-target.d.ts +18 -0
- package/dist/plugins/css-target.js +93 -0
- package/dist/routing/app-route-graph.d.ts +10 -0
- package/dist/routing/app-route-graph.js +15 -1
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +10 -8
- package/dist/server/app-action-forwarding.js +3 -1
- package/dist/server/app-browser-entry.js +37 -41
- package/dist/server/app-browser-error.d.ts +1 -1
- package/dist/server/app-browser-error.js +13 -4
- package/dist/server/app-browser-supplemental-refresh.d.ts +13 -0
- package/dist/server/app-browser-supplemental-refresh.js +36 -4
- package/dist/server/app-elements.d.ts +3 -0
- package/dist/server/app-elements.js +14 -1
- package/dist/server/app-fallback-renderer.js +2 -2
- package/dist/server/app-middleware.d.ts +2 -0
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-optimistic-routing.d.ts +12 -1
- package/dist/server/app-optimistic-routing.js +38 -16
- package/dist/server/app-page-boundary-render.js +4 -2
- package/dist/server/app-page-cache-render.js +1 -1
- package/dist/server/app-page-dispatch.d.ts +11 -1
- package/dist/server/app-page-dispatch.js +78 -31
- package/dist/server/app-page-element-builder.d.ts +11 -20
- package/dist/server/app-page-element-builder.js +39 -50
- package/dist/server/app-page-intercept-segment-config.d.ts +56 -0
- package/dist/server/app-page-intercept-segment-config.js +90 -0
- package/dist/server/app-page-navigation-params.d.ts +23 -0
- package/dist/server/app-page-navigation-params.js +49 -0
- package/dist/server/app-page-render.d.ts +5 -2
- package/dist/server/app-page-render.js +17 -3
- package/dist/server/app-page-request.d.ts +24 -2
- package/dist/server/app-page-request.js +10 -10
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +19 -13
- package/dist/server/app-page-segment-plan.js +9 -1
- package/dist/server/app-page-segment-state.d.ts +9 -0
- package/dist/server/app-page-segment-state.js +54 -1
- package/dist/server/app-pages-bridge.d.ts +6 -0
- package/dist/server/app-pages-bridge.js +8 -3
- package/dist/server/app-request-stage-independent-entry.js +2 -3
- package/dist/server/app-response-stage-entry.js +1 -0
- package/dist/server/app-route-module-loader.d.ts +2 -0
- package/dist/server/app-route-module-loader.js +1 -0
- package/dist/server/app-router-entry.js +2 -3
- package/dist/server/app-rsc-cache-busting.d.ts +8 -0
- package/dist/server/app-rsc-cache-busting.js +13 -1
- package/dist/server/app-rsc-combined-handler.js +2 -1
- package/dist/server/app-rsc-handler.d.ts +14 -1
- package/dist/server/app-rsc-handler.js +111 -62
- package/dist/server/app-rsc-response-finalizer.d.ts +18 -3
- package/dist/server/app-rsc-response-finalizer.js +61 -7
- package/dist/server/app-rsc-route-matching.d.ts +14 -0
- package/dist/server/app-rsc-route-matching.js +42 -18
- package/dist/server/app-server-action-execution.js +16 -10
- package/dist/server/app-ssr-entry.js +8 -0
- package/dist/server/cache-control.d.ts +2 -0
- package/dist/server/cache-control.js +3 -1
- package/dist/server/config-headers.d.ts +7 -0
- package/dist/server/config-headers.js +20 -1
- package/dist/server/image-animation.d.ts +9 -0
- package/dist/server/image-animation.js +118 -0
- package/dist/server/image-local-patterns.d.ts +21 -0
- package/dist/server/image-local-patterns.js +59 -0
- package/dist/server/image-optimization.d.ts +48 -27
- package/dist/server/image-optimization.js +316 -22
- package/dist/server/image-source-reader.d.ts +34 -0
- package/dist/server/image-source-reader.js +126 -0
- package/dist/server/metadata-route-response.d.ts +6 -1
- package/dist/server/metadata-route-response.js +46 -10
- package/dist/server/middleware-matcher.d.ts +1 -0
- package/dist/server/middleware-matcher.js +1 -1
- package/dist/server/middleware-runtime.d.ts +5 -0
- package/dist/server/middleware-runtime.js +48 -15
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +2 -1
- package/dist/server/nitro-public-files-plugin.js +20 -8
- package/dist/server/nitro-request-target-plugin.d.ts +17 -0
- package/dist/server/nitro-request-target-plugin.js +22 -0
- package/dist/server/open-redirect.d.ts +2 -1
- package/dist/server/open-redirect.js +2 -1
- package/dist/server/pages-client-assets.d.ts +1 -0
- package/dist/server/pages-data-route.d.ts +5 -1
- package/dist/server/pages-data-route.js +14 -6
- package/dist/server/pages-i18n.d.ts +7 -0
- package/dist/server/pages-i18n.js +14 -1
- package/dist/server/pages-node-compat.js +7 -3
- package/dist/server/pages-page-handler.js +4 -4
- package/dist/server/pages-request-pipeline.d.ts +9 -0
- package/dist/server/pages-request-pipeline.js +35 -15
- package/dist/server/pages-request-stage-entry.js +8 -2
- package/dist/server/pages-router-entry.js +3 -0
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +64 -62
- package/dist/server/request-pipeline.d.ts +5 -0
- package/dist/server/request-pipeline.js +11 -1
- package/dist/server/response-stage-cacheability.d.ts +7 -0
- package/dist/server/response-stage-cacheability.js +6 -5
- package/dist/server/srvx-middleware-origin.d.ts +13 -0
- package/dist/server/srvx-middleware-origin.js +19 -0
- package/dist/server/srvx-request-target.d.ts +12 -0
- package/dist/server/srvx-request-target.js +20 -0
- package/dist/server/static-file-cache.js +10 -22
- package/dist/server/worker-image-optimization.d.ts +10 -3
- package/dist/server/worker-image-optimization.js +43 -9
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/worker-utils.d.ts +8 -0
- package/dist/server/worker-utils.js +19 -2
- package/dist/shims/error-boundary.d.ts +6 -2
- package/dist/shims/error-boundary.js +4 -2
- package/dist/shims/image-props.d.ts +6 -0
- package/dist/shims/image-props.js +39 -3
- package/dist/shims/image.js +3 -3
- package/dist/shims/request-context.d.ts +3 -1
- package/dist/shims/slot.d.ts +3 -0
- package/dist/shims/slot.js +67 -9
- package/dist/shims/url-utils.js +6 -1
- package/dist/utils/base-path.d.ts +7 -0
- package/dist/utils/base-path.js +11 -1
- package/dist/utils/client-entry-manifest.d.ts +5 -0
- package/dist/utils/client-entry-manifest.js +1 -0
- package/dist/utils/client-runtime-metadata.d.ts +5 -0
- package/dist/utils/client-runtime-metadata.js +33 -7
- package/package.json +1 -1
|
@@ -4,8 +4,8 @@ import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js"
|
|
|
4
4
|
import { getCollectedFetchTags } from "../shims/fetch-cache.js";
|
|
5
5
|
import { readStreamAsText } from "../utils/text-stream.js";
|
|
6
6
|
import { buildAppPageFontLinkHeader, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
|
|
7
|
-
import { recordAppPageRenderError, traceAppPageRender } from "./app-page-tracing.js";
|
|
8
7
|
import { buildAppPageLinkHeader, createAppPageSsrErrorHandler, isAppSsrRenderResult } from "./app-page-stream.js";
|
|
8
|
+
import { recordAppPageRenderError, traceAppPageRender } from "./app-page-tracing.js";
|
|
9
9
|
import { consumeAppPageRenderObservationState, createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
|
|
10
10
|
import { buildAppPageTags } from "./implicit-tags.js";
|
|
11
11
|
//#region src/server/app-page-cache-render.ts
|
|
@@ -15,7 +15,7 @@ import { FetchCacheMode } from "../shims/fetch-cache-state.js";
|
|
|
15
15
|
import "../shims/fetch-cache.js";
|
|
16
16
|
import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
|
|
17
17
|
import { WarmPprFallbackShellCachesOptions } from "./app-ppr-fallback-shell-render.js";
|
|
18
|
-
import { ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
|
|
18
|
+
import { AppPageInterceptState, ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
|
|
19
19
|
import { ReactNode } from "react";
|
|
20
20
|
import { ReactFormState } from "react-dom/client";
|
|
21
21
|
//#region src/server/app-page-dispatch.d.ts
|
|
@@ -96,10 +96,17 @@ type AppPageModule = {
|
|
|
96
96
|
revalidate?: unknown;
|
|
97
97
|
};
|
|
98
98
|
type AppPageDispatchSlot = {
|
|
99
|
+
configLayouts?: readonly (AppPageModule | null | undefined)[] | null;
|
|
100
|
+
configLayoutTreePositions?: readonly number[] | null;
|
|
99
101
|
default?: AppPageModule | null;
|
|
102
|
+
layout?: AppPageModule | null;
|
|
103
|
+
layoutIndex?: number;
|
|
100
104
|
loading?: AppPageModule | null;
|
|
101
105
|
loadings?: readonly (AppPageModule | null | undefined)[] | null;
|
|
106
|
+
name?: string;
|
|
107
|
+
ownerTreePosition?: number | null;
|
|
102
108
|
page?: AppPageModule | null;
|
|
109
|
+
routeSegments?: readonly string[] | null;
|
|
103
110
|
slotPatternParts?: readonly string[] | null;
|
|
104
111
|
slotParamNames?: readonly string[] | null;
|
|
105
112
|
};
|
|
@@ -159,6 +166,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
159
166
|
buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, options?: {
|
|
160
167
|
isForceStatic?: boolean;
|
|
161
168
|
isUncacheableRender?: boolean;
|
|
169
|
+
routeTreeOnlyPrefetchShell?: boolean;
|
|
162
170
|
/** Layouts the navigating client holds, which the render may leave out. */
|
|
163
171
|
mountedLayouts?: ReadonlySet<string> | null;
|
|
164
172
|
observeMetadataSearchParamsAccess?: boolean;
|
|
@@ -184,6 +192,8 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
184
192
|
ensureRouteLoaded?: (route: TRoute) => unknown;
|
|
185
193
|
fetchCache?: FetchCacheMode | null;
|
|
186
194
|
findIntercept: (pathname: string) => AppPageDispatchIntercept | null;
|
|
195
|
+
/** This request's intercept, which dispatch resolves once before rendering. */
|
|
196
|
+
interceptState?: AppPageInterceptState<TRoute, unknown>;
|
|
187
197
|
formState?: ReactFormState | null;
|
|
188
198
|
actionError?: unknown;
|
|
189
199
|
actionFailed?: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import "../utils/protocol-headers.js";
|
|
3
3
|
import { VINEXT_INTERCEPTION_ID_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
|
|
4
|
-
import { VINEXT_MOUNTED_LAYOUTS_HEADER } from "./headers.js";
|
|
4
|
+
import { VINEXT_MOUNTED_LAYOUTS_HEADER, VINEXT_PARAMS_HEADER } from "./headers.js";
|
|
5
5
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
6
6
|
import { runInWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
7
7
|
import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityPatternDynamic, readRouteCacheabilityState } from "../shims/cacheability-classification.js";
|
|
@@ -21,16 +21,17 @@ import { resolveUncacheableCacheControl } from "./app-page-response.js";
|
|
|
21
21
|
import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
|
|
22
22
|
import { buildAppPageSpecialErrorResponse, resolveAppPageCaughtNotFoundBoundaries, resolveAppPageShellSpecialError, resolveAppPageSpecialError, resolveAppPageSpecialErrorStoredHeaders } from "./app-page-execution.js";
|
|
23
23
|
import { resolveAppPageLayoutHttpAccessBoundary, resolveAppPageParentHttpAccessBoundary, resolveAppPageRootHttpAccessBoundaryTreePosition } from "./app-page-boundary.js";
|
|
24
|
+
import { resolveAppPageNavigationParams } from "./app-page-navigation-params.js";
|
|
25
|
+
import { createAppPageRscErrorTracker } from "./app-page-stream.js";
|
|
24
26
|
import { isAppClientReference } from "./app-render-dependency.js";
|
|
25
27
|
import { resolveAppPageTraceOperation } from "./app-page-tracing.js";
|
|
26
|
-
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
27
|
-
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
28
|
-
import { createAppPageRscErrorTracker } from "./app-page-stream.js";
|
|
29
28
|
import { getDefaultHttpAccessFallbackModule } from "./default-http-access-fallback-modules.js";
|
|
29
|
+
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
30
30
|
import { consumeAppPageRenderObservationState, discardAppPageRenderState } from "./app-page-render-observation.js";
|
|
31
31
|
import { buildAppPageTags } from "./implicit-tags.js";
|
|
32
32
|
import { resolveAppPageMethodResponse } from "./app-page-method.js";
|
|
33
|
-
import {
|
|
33
|
+
import { resolveAppPageInterceptSegmentConfig } from "./app-page-intercept-segment-config.js";
|
|
34
|
+
import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptState, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
|
|
34
35
|
import { applyIneligibleRouteCachePolicy, renderAppPageLifecycle } from "./app-page-render.js";
|
|
35
36
|
//#region src/server/app-page-dispatch.ts
|
|
36
37
|
function getActiveLoadingTreePositions(route) {
|
|
@@ -146,12 +147,48 @@ function hasNoManifestAdmissionState(routePattern) {
|
|
|
146
147
|
}, admission.representation, admission.routePathname) === null;
|
|
147
148
|
}
|
|
148
149
|
async function dispatchAppPage(options) {
|
|
149
|
-
const dispatch = () => runWithFetchDedupe(() => dispatchAppPageInner(options));
|
|
150
|
+
const dispatch = () => runWithFetchDedupe(async () => dispatchAppPageInner(await withResolvedIntercept(options)));
|
|
150
151
|
let response;
|
|
151
152
|
if (!options.pprFallbackShell || !options.pprRuntime) response = await dispatch();
|
|
152
153
|
else response = await options.pprRuntime.run(options.pprFallbackShell, dispatch);
|
|
153
154
|
return options.isRscRequest ? response : traceResponseStart(response);
|
|
154
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Resolves the request's intercept once, for the render and its cache reads.
|
|
158
|
+
*
|
|
159
|
+
* Next.js renders an interception as its own route even when its source is the
|
|
160
|
+
* matched route (`app/shots/[id]` beside `app/shots/@modal/(.)[id]`, from
|
|
161
|
+
* `/shots/1` to `/shots/2`). vinext renders that through the matched route's
|
|
162
|
+
* own page render, so the interception's segment config replaces the route's
|
|
163
|
+
* before that render reads it.
|
|
164
|
+
*/
|
|
165
|
+
async function withResolvedIntercept(options) {
|
|
166
|
+
const interceptState = await resolveAppPageInterceptState({
|
|
167
|
+
cleanPathname: options.cleanPathname,
|
|
168
|
+
currentRoute: options.route,
|
|
169
|
+
findIntercept: options.findIntercept,
|
|
170
|
+
getSourceRoute: options.getSourceRoute,
|
|
171
|
+
interceptState: options.interceptState,
|
|
172
|
+
isRscRequest: options.isRscRequest
|
|
173
|
+
});
|
|
174
|
+
if (interceptState.kind !== "current-route") return {
|
|
175
|
+
...options,
|
|
176
|
+
interceptState
|
|
177
|
+
};
|
|
178
|
+
const config = resolveAppPageInterceptSegmentConfig(options.route, toInterceptOptions(options.interceptionContext, interceptState.intercept));
|
|
179
|
+
return {
|
|
180
|
+
...options,
|
|
181
|
+
interceptState,
|
|
182
|
+
dynamicConfig: config.dynamicConfig,
|
|
183
|
+
dynamicStaleTimeSeconds: config.dynamicStaleTimeSeconds,
|
|
184
|
+
fetchCache: config.fetchCacheMode,
|
|
185
|
+
hasAnyGenerateStaticParams: config.hasAnyGenerateStaticParams,
|
|
186
|
+
hasGenerateStaticParams: config.hasGenerateStaticParams,
|
|
187
|
+
isEdgeRuntime: config.isEdgeRuntime,
|
|
188
|
+
isStaticGenerationEdgeRuntime: config.isStaticGenerationEdgeRuntime,
|
|
189
|
+
revalidateSeconds: config.revalidateSeconds
|
|
190
|
+
};
|
|
191
|
+
}
|
|
155
192
|
async function dispatchAppPageInner(options) {
|
|
156
193
|
const route = options.route;
|
|
157
194
|
beginRouteCacheability("app-page", route.pattern);
|
|
@@ -206,6 +243,7 @@ async function dispatchAppPageInner(options) {
|
|
|
206
243
|
isDynamicError,
|
|
207
244
|
isForceDynamic,
|
|
208
245
|
isForceStatic,
|
|
246
|
+
isPrerender,
|
|
209
247
|
isProduction: options.isProduction,
|
|
210
248
|
isProgressiveActionRender: options.isProgressiveActionRender === true,
|
|
211
249
|
isRscRequest: options.isRscRequest,
|
|
@@ -255,7 +293,8 @@ async function dispatchAppPageInner(options) {
|
|
|
255
293
|
const isOnDemandRevalidate = _isOnDemandRevalidate();
|
|
256
294
|
const shouldReadCache = isStoredRender && !isOnDemandRevalidate;
|
|
257
295
|
const isCacheCandidate = isCacheEligibleRender && isStaticEligible && options.pprFallbackShell === void 0 && !isNeverStoredPath;
|
|
258
|
-
const
|
|
296
|
+
const routeTreeOnlyPrefetchShell = options.pprFallbackShell === void 0 && (options.pprRuntime === void 0 || !options.isProduction);
|
|
297
|
+
const isUncacheableRender = !(isCacheEligibleRender && isStaticEligible) && routeTreeOnlyPrefetchShell;
|
|
259
298
|
const mountedLayouts = isUncacheableRender && options.isRscRequest && (options.renderMode ?? "navigation") === "navigation" && options.interceptionContext === null && options.isProgressiveActionRender !== true ? parseMountedLayoutsHeader(options.request.headers.get(VINEXT_MOUNTED_LAYOUTS_HEADER)) : null;
|
|
260
299
|
if (shouldReadCache && isStaticEligible) {
|
|
261
300
|
traceOperation = resolveAppPageTraceOperation({
|
|
@@ -280,6 +319,7 @@ async function dispatchAppPageInner(options) {
|
|
|
280
319
|
getSourceRoute(sourceRouteIndex) {
|
|
281
320
|
return options.getSourceRoute(sourceRouteIndex);
|
|
282
321
|
},
|
|
322
|
+
interceptState: options.interceptState,
|
|
283
323
|
isRscRequest: options.isRscRequest,
|
|
284
324
|
toInterceptOpts(intercept) {
|
|
285
325
|
return toInterceptOptions(options.interceptionContext, intercept);
|
|
@@ -320,9 +360,10 @@ async function dispatchAppPageInner(options) {
|
|
|
320
360
|
isDynamicRscRequest: options.pprRuntime !== void 0 && options.isRscRequest && options.request.headers.get("Next-Router-Prefetch") !== "1" && options.renderedConcreteUrlPaths?.has(options.cleanPathname) !== true,
|
|
321
361
|
renderFreshPageForCache: async ({ renderDocument }) => {
|
|
322
362
|
const revalidationTarget = await resolveCacheRenderTarget();
|
|
323
|
-
const
|
|
324
|
-
const
|
|
325
|
-
const
|
|
363
|
+
const revalidationInterceptConfig = revalidationTarget.interceptOpts ? resolveAppPageInterceptSegmentConfig(revalidationTarget.route, revalidationTarget.interceptOpts) : null;
|
|
364
|
+
const revalidationDynamicConfig = revalidationInterceptConfig ? revalidationInterceptConfig.dynamicConfig : options.resolveRouteDynamicConfig?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? dynamicConfig : void 0);
|
|
365
|
+
const revalidationConfigRevalidateSeconds = revalidationInterceptConfig ? revalidationTarget.route === route ? currentRevalidateSeconds : revalidationInterceptConfig.revalidateSeconds : options.resolveRouteRevalidateSeconds?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? currentRevalidateSeconds : null);
|
|
366
|
+
const revalidationRouteRevalidateSeconds = revalidationTarget.route === route ? void 0 : revalidationConfigRevalidateSeconds ?? (revalidationDynamicConfig === "force-static" || revalidationDynamicConfig === "error" || options.isProduction && options.pprRuntime === void 0 && (revalidationInterceptConfig?.isStaticEligible ?? options.resolveRouteStaticEligible(revalidationTarget.route)) ? Infinity : null);
|
|
326
367
|
const revalidationRouteHead = {
|
|
327
368
|
observeSearchParams: revalidationDynamicConfig !== "force-static",
|
|
328
369
|
searchParams: new URLSearchParams(),
|
|
@@ -332,7 +373,7 @@ async function dispatchAppPageInner(options) {
|
|
|
332
373
|
return runAppPageRevalidationContext({
|
|
333
374
|
cleanPathname: options.cleanPathname,
|
|
334
375
|
displayPathname: options.displayPathname,
|
|
335
|
-
currentFetchCacheMode: options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
|
|
376
|
+
currentFetchCacheMode: revalidationInterceptConfig ? revalidationInterceptConfig.fetchCacheMode : options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
|
|
336
377
|
currentFetchRevalidate: revalidationConfigRevalidateSeconds,
|
|
337
378
|
draftModeSecret: options.draftModeSecret,
|
|
338
379
|
dynamicConfig: revalidationDynamicConfig,
|
|
@@ -347,6 +388,7 @@ async function dispatchAppPageInner(options) {
|
|
|
347
388
|
isForceStatic: revalidationDynamicConfig === "force-static",
|
|
348
389
|
observeMetadataSearchParamsAccess: revalidationDynamicConfig !== "force-static",
|
|
349
390
|
observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static",
|
|
391
|
+
routeTreeOnlyPrefetchShell,
|
|
350
392
|
serveStreamingMetadata: placeGeneratedMetadataInBody,
|
|
351
393
|
placeStreamedMetadataInHead: true,
|
|
352
394
|
onHeadPrepared(head) {
|
|
@@ -459,6 +501,7 @@ async function dispatchAppPageInner(options) {
|
|
|
459
501
|
isDynamicError,
|
|
460
502
|
isForceDynamic,
|
|
461
503
|
isForceStatic,
|
|
504
|
+
isPrerender,
|
|
462
505
|
isProduction: options.isProduction,
|
|
463
506
|
isProgressiveActionRender: options.isProgressiveActionRender === true,
|
|
464
507
|
isRscRequest: options.isRscRequest,
|
|
@@ -475,9 +518,9 @@ async function dispatchAppPageInner(options) {
|
|
|
475
518
|
}
|
|
476
519
|
const fallbackShellResponse = options.pprRuntime ? await options.pprRuntime.tryServe(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) : null;
|
|
477
520
|
if (fallbackShellResponse) return fallbackShellResponse;
|
|
478
|
-
let
|
|
479
|
-
let
|
|
480
|
-
let
|
|
521
|
+
let interceptConfig = null;
|
|
522
|
+
let isInterceptKnownDynamic = false;
|
|
523
|
+
let isInterceptRequestIndependent = false;
|
|
481
524
|
const renderedRouteHead = {
|
|
482
525
|
observeSearchParams: !isForceStatic,
|
|
483
526
|
searchParams: pageSearchParams,
|
|
@@ -489,27 +532,29 @@ async function dispatchAppPageInner(options) {
|
|
|
489
532
|
};
|
|
490
533
|
const interceptResult = await resolveAppPageIntercept({
|
|
491
534
|
async buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams) {
|
|
492
|
-
|
|
493
|
-
|
|
535
|
+
interceptConfig ??= resolveAppPageInterceptSegmentConfig(interceptRoute, interceptOpts);
|
|
536
|
+
const interceptDynamicConfig = interceptConfig.dynamicConfig;
|
|
537
|
+
if (interceptDynamicConfig === "force-static" || interceptDynamicConfig === "error") {
|
|
494
538
|
const { createStaticGenerationHeadersContext } = await import("./app-static-generation.js");
|
|
495
539
|
setHeadersContext(createStaticGenerationHeadersContext({
|
|
496
540
|
draftModeEnabled: isDraftMode,
|
|
497
541
|
draftModeSecret: options.draftModeSecret,
|
|
498
|
-
dynamicConfig:
|
|
542
|
+
dynamicConfig: interceptDynamicConfig,
|
|
499
543
|
routeKind: "page",
|
|
500
544
|
routePattern: interceptRoute.pattern
|
|
501
545
|
}));
|
|
502
546
|
} else setHeadersContext(requestHeadersContext);
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
setCurrentFetchCacheMode(
|
|
506
|
-
setCurrentFetchRevalidate(
|
|
507
|
-
setCurrentForceDynamicFetchDefault(
|
|
547
|
+
isInterceptKnownDynamic = interceptDynamicConfig === "force-dynamic" || interceptConfig.revalidateSeconds === 0;
|
|
548
|
+
isInterceptRequestIndependent = interceptDynamicConfig === "force-static" || interceptDynamicConfig === "error";
|
|
549
|
+
setCurrentFetchCacheMode(interceptConfig.fetchCacheMode);
|
|
550
|
+
setCurrentFetchRevalidate(interceptConfig.revalidateSeconds);
|
|
551
|
+
setCurrentForceDynamicFetchDefault(interceptDynamicConfig === "force-dynamic");
|
|
508
552
|
return options.buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, {
|
|
509
|
-
isForceStatic:
|
|
510
|
-
observeMetadataSearchParamsAccess:
|
|
511
|
-
observePageSearchParamsAccess:
|
|
553
|
+
isForceStatic: interceptDynamicConfig === "force-static",
|
|
554
|
+
observeMetadataSearchParamsAccess: interceptDynamicConfig !== "force-static",
|
|
555
|
+
observePageSearchParamsAccess: interceptDynamicConfig !== "force-static",
|
|
512
556
|
isUncacheableRender,
|
|
557
|
+
routeTreeOnlyPrefetchShell,
|
|
513
558
|
serveStreamingMetadata: placeGeneratedMetadataInBody,
|
|
514
559
|
placeStreamedMetadataInHead: options.renderWholeDocument === true,
|
|
515
560
|
onHeadPrepared
|
|
@@ -526,18 +571,20 @@ async function dispatchAppPageInner(options) {
|
|
|
526
571
|
getSourceRoute(sourceRouteIndex) {
|
|
527
572
|
return options.getSourceRoute(sourceRouteIndex);
|
|
528
573
|
},
|
|
574
|
+
interceptState: options.interceptState,
|
|
529
575
|
isRscRequest: options.isRscRequest,
|
|
530
576
|
resolveNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts) {
|
|
531
577
|
return resolveAppPageNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts);
|
|
532
578
|
},
|
|
533
|
-
renderInterceptResponse(sourceRoute, interceptElement) {
|
|
579
|
+
renderInterceptResponse(sourceRoute, interceptElement, navigationParams) {
|
|
534
580
|
const interceptOnError = options.createRscOnErrorHandler(options.cleanPathname, sourceRoute.pattern);
|
|
535
581
|
const interceptStream = options.renderToReadableStream(interceptElement, { onError: interceptOnError });
|
|
536
582
|
const interceptHeaders = new Headers({
|
|
537
583
|
"Content-Type": VINEXT_RSC_CONTENT_TYPE,
|
|
538
584
|
Vary: VINEXT_RSC_VARY_HEADER
|
|
539
585
|
});
|
|
540
|
-
if (
|
|
586
|
+
if (Object.keys(navigationParams).length > 0) interceptHeaders.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(navigationParams)));
|
|
587
|
+
if (!(options.pprRuntime !== void 0 || interceptConfig?.isStaticEligible === true) || isDraftMode || isInterceptKnownDynamic || options.isProduction && !isInterceptRequestIndependent) interceptHeaders.set("Cache-Control", resolveUncacheableCacheControl(options.isProduction));
|
|
541
588
|
mergeMiddlewareResponseHeaders(interceptHeaders, options.middlewareContext.headers);
|
|
542
589
|
applyRscCompatibilityIdHeader(interceptHeaders);
|
|
543
590
|
applyRscDeploymentIdHeader(interceptHeaders);
|
|
@@ -546,11 +593,10 @@ async function dispatchAppPageInner(options) {
|
|
|
546
593
|
headers: interceptHeaders
|
|
547
594
|
});
|
|
548
595
|
},
|
|
549
|
-
async resolveSearchParams(sourceRoute, searchParams) {
|
|
596
|
+
async resolveSearchParams(sourceRoute, searchParams, interceptOpts) {
|
|
550
597
|
await options.ensureRouteLoaded?.(sourceRoute);
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
return interceptDynamicConfig === "force-static" ? new URLSearchParams() : searchParams;
|
|
598
|
+
interceptConfig = resolveAppPageInterceptSegmentConfig(sourceRoute, interceptOpts);
|
|
599
|
+
return interceptConfig.dynamicConfig === "force-static" ? new URLSearchParams() : searchParams;
|
|
554
600
|
},
|
|
555
601
|
searchParams: options.searchParams,
|
|
556
602
|
setNavigationContext: options.setNavigationContext,
|
|
@@ -568,6 +614,7 @@ async function dispatchAppPageInner(options) {
|
|
|
568
614
|
observeMetadataSearchParamsAccess: !isForceStatic,
|
|
569
615
|
observePageSearchParamsAccess: !isForceStatic,
|
|
570
616
|
isUncacheableRender,
|
|
617
|
+
routeTreeOnlyPrefetchShell,
|
|
571
618
|
mountedLayouts: interceptResult.interceptOpts ? null : mountedLayouts,
|
|
572
619
|
serveStreamingMetadata: placeGeneratedMetadataInBody,
|
|
573
620
|
placeStreamedMetadataInHead: options.renderWholeDocument === true,
|
|
@@ -66,6 +66,8 @@ export type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> =
|
|
|
66
66
|
isForceStatic?: boolean;
|
|
67
67
|
/** The render can never be stored (see buildAppPageElements). */
|
|
68
68
|
isUncacheableRender?: boolean;
|
|
69
|
+
/** A loading shell without a loading boundary is the route tree (see buildAppPageElements). */
|
|
70
|
+
routeTreeOnlyPrefetchShell?: boolean;
|
|
69
71
|
/** Layouts the navigating client holds (see buildAppPageElements). */
|
|
70
72
|
mountedLayouts?: ReadonlySet<string> | null;
|
|
71
73
|
/** Observe page metadata `searchParams` access for cache-safety classification. */
|
|
@@ -116,24 +118,6 @@ export type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModu
|
|
|
116
118
|
htmlLimitedBots?: string;
|
|
117
119
|
scriptNonce?: string;
|
|
118
120
|
};
|
|
119
|
-
type AppPageNavigationParamModule = {
|
|
120
|
-
default?: unknown;
|
|
121
|
-
};
|
|
122
|
-
type AppPageNavigationParamSlot = {
|
|
123
|
-
default?: AppPageNavigationParamModule | null;
|
|
124
|
-
page?: AppPageNavigationParamModule | null;
|
|
125
|
-
slotPatternParts?: readonly string[] | null;
|
|
126
|
-
slotParamNames?: readonly string[] | null;
|
|
127
|
-
};
|
|
128
|
-
type AppPageNavigationParamRoute = {
|
|
129
|
-
params?: readonly string[] | null;
|
|
130
|
-
slots?: Readonly<Record<string, AppPageNavigationParamSlot>> | null;
|
|
131
|
-
};
|
|
132
|
-
type AppPageNavigationParamInterceptOptions = {
|
|
133
|
-
interceptPage?: unknown;
|
|
134
|
-
interceptParams?: AppPageParams | null;
|
|
135
|
-
interceptSlotKey?: string | null;
|
|
136
|
-
};
|
|
137
121
|
/**
|
|
138
122
|
* Build the App Router element tree for a matched route.
|
|
139
123
|
*
|
|
@@ -151,6 +135,15 @@ type AppPageNavigationParamInterceptOptions = {
|
|
|
151
135
|
* {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
|
|
152
136
|
*/
|
|
153
137
|
export declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
|
|
138
|
+
/**
|
|
139
|
+
* The state key of each segment a sibling intercept's levels retain, from the
|
|
140
|
+
* app root down to the segment its element renders, so its Activity lists key
|
|
141
|
+
* like Next.js's for the intercepting route: the marker segment carries its
|
|
142
|
+
* marker, and a dynamic marker segment keys per value. The intercepting
|
|
143
|
+
* route's own layouts and boundaries render inside its page element, so the
|
|
144
|
+
* levels stop above the first of them.
|
|
145
|
+
*/
|
|
146
|
+
export declare function resolveSiblingInterceptSegmentKeys(sourcePageSegments: readonly string[] | null | undefined, routeSegments: readonly string[] | null | undefined, opts: AppPageInterceptOptions | null | undefined, routeParams: AppPageParams, interceptParams: AppPageParams): readonly string[] | null;
|
|
154
147
|
export declare const APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS: readonly [{
|
|
155
148
|
readonly prefix: "(...)";
|
|
156
149
|
readonly levels: number;
|
|
@@ -172,7 +165,5 @@ export declare const APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS: readonly [{
|
|
|
172
165
|
*/
|
|
173
166
|
export declare function resolveInterceptedSlotIdentitySegments(sourcePageSegments: readonly string[] | null | undefined, slotKey: string): readonly AppPageSemanticSegment[] | null;
|
|
174
167
|
export declare function resolveInterceptedSlotSegments(sourcePageSegments: readonly string[] | null | undefined, slotKey: string): readonly string[] | null;
|
|
175
|
-
export declare function resolveSlotParamOverrides(route: AppPageNavigationParamRoute, routePath: string): Readonly<Record<string, AppPageParams>> | null;
|
|
176
|
-
export declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
|
|
177
168
|
//#endregion
|
|
178
169
|
export type { AppPageErrorModule, AppPageRouteWiringRoute };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { isPromiseLike } from "../utils/promise.js";
|
|
2
2
|
import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
|
|
3
|
-
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
4
3
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
5
4
|
import "./app-elements.js";
|
|
6
|
-
import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPagePatternStateKey, resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
|
|
5
|
+
import { APP_PAGE_SEGMENT_KEY, isAppPageRouteGroupSegment, resolveAppPagePatternStateKey, resolveAppPageRouteStateKey, resolveAppPageSemanticSegmentStateKey } from "./app-page-segment-state.js";
|
|
7
6
|
import { ErrorBoundary, ForbiddenBoundary, NotFoundBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
|
|
8
7
|
import { withUseCacheLayoutMarker, withUseCachePageMarker } from "../shims/internal/app-page-props-cache-key.js";
|
|
9
8
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
@@ -12,15 +11,16 @@ import { createAppPageMetadataSearchParamsObserver, makeObservedAppPageSearchPar
|
|
|
12
11
|
import { resolveAppPageBranchParams } from "./app-page-params.js";
|
|
13
12
|
import { collectAppPageSearchParams, hasAppPageDynamicMetadata, prepareAppPageHead, resolveActiveParallelRouteHeadInputs, resolveInterceptLayoutsBesidePage, slotInterceptKeepsSourceHead } from "./app-page-head.js";
|
|
14
13
|
import { createRouteNotFoundHeadPlanOptions, recoverAppPageRouteHead } from "./app-page-http-access-fallback-metadata.js";
|
|
15
|
-
import { ClientPageRoot } from "../shims/client-page-root.js";
|
|
16
14
|
import "./app-rsc-route-matching.js";
|
|
15
|
+
import { resolveSlotParamOverrides } from "./app-page-navigation-params.js";
|
|
17
16
|
import { createAppPageRenderDependency, invokeAppComponent, isAppClientReference, isAppRenderSuspension, isReactOwnedAppComponent, renderAfterAppDependencies } from "./app-render-dependency.js";
|
|
18
17
|
import { sanitizeErrorForClient } from "./app-rsc-errors.js";
|
|
19
18
|
import { resolveAppPageModuleTraceSegment, traceCreateComponentTree, traceGetLayoutOrPageModule } from "./app-page-tracing.js";
|
|
20
19
|
import { buildAppPageElements, createAppPageSourcePage, createAppPageTreePath, resolveAppPageLoadingModuleAtOrAbove } from "./app-page-route-wiring.js";
|
|
21
20
|
import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
|
|
22
|
-
import { createAppPageRenderIdentity } from "./app-page-render-identity.js";
|
|
23
21
|
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
22
|
+
import { ClientPageRoot } from "../shims/client-page-root.js";
|
|
23
|
+
import { createAppPageRenderIdentity } from "./app-page-render-identity.js";
|
|
24
24
|
import { Fragment, Suspense, cache, createElement } from "react";
|
|
25
25
|
//#region src/server/app-page-element-builder.ts
|
|
26
26
|
/**
|
|
@@ -107,7 +107,7 @@ function traceAppPageInterceptLayoutModules(modules, branchSegments, layoutSegme
|
|
|
107
107
|
async function buildPageElements(options) {
|
|
108
108
|
const { route, params, routePath, displayPathname = routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
|
|
109
109
|
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
110
|
-
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false, isForceStatic = false, isUncacheableRender = false, mountedLayouts = null, serveStreamingMetadata, placeStreamedMetadataInHead = false, isProduction = process.env.NODE_ENV === "production", onHeadPrepared } = pageRequest;
|
|
110
|
+
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false, isForceStatic = false, isUncacheableRender = false, routeTreeOnlyPrefetchShell = false, mountedLayouts = null, serveStreamingMetadata, placeStreamedMetadataInHead = false, isProduction = process.env.NODE_ENV === "production", onHeadPrepared } = pageRequest;
|
|
111
111
|
const pageModule = route.page;
|
|
112
112
|
const isSiblingIntercept = opts?.interceptSlotKey === "__vinext_page_intercept" && !!opts?.interceptPage;
|
|
113
113
|
const effectivePageModule = isSiblingIntercept ? opts.interceptPage : pageModule;
|
|
@@ -414,6 +414,7 @@ async function buildPageElements(options) {
|
|
|
414
414
|
globalErrorModule: globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE,
|
|
415
415
|
isRscRequest,
|
|
416
416
|
isUncacheableRender,
|
|
417
|
+
routeTreeOnlyPrefetchShell,
|
|
417
418
|
interceptionId: opts?.interceptionId ?? null,
|
|
418
419
|
mountedLayouts,
|
|
419
420
|
mountedSlotIds,
|
|
@@ -429,6 +430,7 @@ async function buildPageElements(options) {
|
|
|
429
430
|
routePath,
|
|
430
431
|
semanticPageIdentity,
|
|
431
432
|
semanticInterceptionTargetRouteId: opts?.interceptTargetRouteGraphId ?? null,
|
|
433
|
+
siblingInterceptSegmentKeys: isSiblingIntercept ? resolveSiblingInterceptSegmentKeys(sourcePageSegments, route.routeSegments, opts, params, effectiveParams) : null,
|
|
432
434
|
sourcePageSegments,
|
|
433
435
|
rootNotFoundModule: rootNotFoundModule ?? null,
|
|
434
436
|
rootForbiddenModule: rootForbiddenModule ?? null,
|
|
@@ -487,6 +489,37 @@ function buildSlotOverrides(route, routeParams, routePath, opts, interceptMetada
|
|
|
487
489
|
}
|
|
488
490
|
return Object.keys(overrides).length > 0 ? overrides : null;
|
|
489
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* The state key of each segment a sibling intercept's levels retain, from the
|
|
494
|
+
* app root down to the segment its element renders, so its Activity lists key
|
|
495
|
+
* like Next.js's for the intercepting route: the marker segment carries its
|
|
496
|
+
* marker, and a dynamic marker segment keys per value. The intercepting
|
|
497
|
+
* route's own layouts and boundaries render inside its page element, so the
|
|
498
|
+
* levels stop above the first of them.
|
|
499
|
+
*/
|
|
500
|
+
function resolveSiblingInterceptSegmentKeys(sourcePageSegments, routeSegments, opts, routeParams, interceptParams) {
|
|
501
|
+
if (!sourcePageSegments || !routeSegments) return null;
|
|
502
|
+
const markerIndex = sourcePageSegments.findIndex((segment) => APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS.some(({ prefix }) => segment.startsWith(prefix)));
|
|
503
|
+
if (markerIndex < 0) return null;
|
|
504
|
+
if (routeSegments.length !== markerIndex || routeSegments.some((segment, index) => segment !== sourcePageSegments[index])) return null;
|
|
505
|
+
const branchTreePositions = [
|
|
506
|
+
...(opts?.interceptLayouts ?? []).flatMap((layoutModule, index) => layoutModule?.default ? [opts?.interceptLayoutSegments?.[index]?.length ?? 0] : []),
|
|
507
|
+
...opts?.interceptLoadingTreePositions ?? [],
|
|
508
|
+
...opts?.interceptNotFoundTreePositions ?? [],
|
|
509
|
+
...opts?.interceptForbiddenTreePositions ?? [],
|
|
510
|
+
...opts?.interceptUnauthorizedTreePositions ?? [],
|
|
511
|
+
...opts?.interceptErrorTreePositions ?? []
|
|
512
|
+
];
|
|
513
|
+
const segmentCount = Math.max(markerIndex, Math.min(sourcePageSegments.length, markerIndex + Math.min(...branchTreePositions) - 1));
|
|
514
|
+
return sourcePageSegments.slice(0, segmentCount).map((segment, index) => {
|
|
515
|
+
const marker = index === markerIndex ? APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS.find(({ prefix }) => segment.startsWith(prefix)) : void 0;
|
|
516
|
+
return resolveAppPageSemanticSegmentStateKey({
|
|
517
|
+
marker: marker?.prefix ?? null,
|
|
518
|
+
paramSource: "route",
|
|
519
|
+
segment: marker ? segment.slice(marker.prefix.length) : segment
|
|
520
|
+
}, index < markerIndex ? routeParams : interceptParams);
|
|
521
|
+
});
|
|
522
|
+
}
|
|
490
523
|
const APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS = [
|
|
491
524
|
{
|
|
492
525
|
prefix: "(...)",
|
|
@@ -581,49 +614,5 @@ function resolveInterceptedSlotSegments(sourcePageSegments, slotKey) {
|
|
|
581
614
|
routeSegments.push(...sourcePageSegments.slice(markerIndex + 1).filter(isVisibleInterceptedSlotSegment));
|
|
582
615
|
return routeSegments;
|
|
583
616
|
}
|
|
584
|
-
function resolveSlotParamOverrides(route, routePath) {
|
|
585
|
-
const overrides = {};
|
|
586
|
-
const slots = route.slots;
|
|
587
|
-
if (slots) {
|
|
588
|
-
let urlParts = null;
|
|
589
|
-
const routeParamSet = collectParamNameSet(route.params);
|
|
590
|
-
for (const [slotKey, slot] of Object.entries(slots)) {
|
|
591
|
-
const patternParts = slot.slotPatternParts;
|
|
592
|
-
const paramNames = slot.slotParamNames;
|
|
593
|
-
if (!patternParts || patternParts.length === 0) continue;
|
|
594
|
-
if (paramNames && paramNames.every((name) => routeParamSet.has(name))) continue;
|
|
595
|
-
if (urlParts === null) urlParts = routePath.split("/").filter(Boolean);
|
|
596
|
-
const matched = matchRoutePattern(urlParts, patternParts);
|
|
597
|
-
if (!matched) continue;
|
|
598
|
-
overrides[slotKey] = matched;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
return Object.keys(overrides).length > 0 ? overrides : null;
|
|
602
|
-
}
|
|
603
|
-
function mergeAppPageParams(target, source) {
|
|
604
|
-
for (const [key, value] of Object.entries(source)) target[key] = value;
|
|
605
|
-
}
|
|
606
|
-
function isDefaultExportModule(module) {
|
|
607
|
-
return typeof module === "object" && module !== null;
|
|
608
|
-
}
|
|
609
|
-
function hasDefaultExport(module) {
|
|
610
|
-
if (!isDefaultExportModule(module)) return false;
|
|
611
|
-
return module?.default !== null && module?.default !== void 0;
|
|
612
|
-
}
|
|
613
|
-
function resolveAppPageNavigationParams(route, routeParams, routePath, opts) {
|
|
614
|
-
const navigationParams = { ...routeParams };
|
|
615
|
-
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
616
|
-
for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
|
|
617
|
-
const isInterceptedSlot = opts?.interceptSlotKey === slotKey && opts.interceptSlotKey !== "__vinext_page_intercept" && hasDefaultExport(opts.interceptPage);
|
|
618
|
-
if (!isInterceptedSlot && !hasDefaultExport(slot.page) && !hasDefaultExport(slot.default)) continue;
|
|
619
|
-
mergeAppPageParams(navigationParams, isInterceptedSlot ? opts?.interceptParams ?? routeParams : slotParamOverrides?.[slotKey] ?? routeParams);
|
|
620
|
-
}
|
|
621
|
-
return navigationParams;
|
|
622
|
-
}
|
|
623
|
-
function collectParamNameSet(params) {
|
|
624
|
-
const set = /* @__PURE__ */ new Set();
|
|
625
|
-
if (params) for (const name of params) set.add(name);
|
|
626
|
-
return set;
|
|
627
|
-
}
|
|
628
617
|
//#endregion
|
|
629
|
-
export { APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS, buildPageElements,
|
|
618
|
+
export { APP_PAGE_INTERCEPTION_MARKER_TRAVERSALS, buildPageElements, resolveInterceptedSlotIdentitySegments, resolveInterceptedSlotSegments, resolveSiblingInterceptSegmentKeys };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { FetchCacheMode } from "../shims/fetch-cache-state.js";
|
|
2
|
+
import "../shims/fetch-cache.js";
|
|
3
|
+
//#region src/server/app-page-intercept-segment-config.d.ts
|
|
4
|
+
type SegmentModule = Record<string, unknown>;
|
|
5
|
+
type AppPageInterceptSegmentConfigSlot = {
|
|
6
|
+
configLayouts?: readonly (SegmentModule | null | undefined)[] | null;
|
|
7
|
+
configLayoutTreePositions?: readonly number[] | null;
|
|
8
|
+
default?: SegmentModule | null;
|
|
9
|
+
layout?: SegmentModule | null;
|
|
10
|
+
layoutIndex?: number;
|
|
11
|
+
name?: string;
|
|
12
|
+
ownerTreePosition?: number | null;
|
|
13
|
+
page?: SegmentModule | null;
|
|
14
|
+
routeSegments?: readonly string[] | null;
|
|
15
|
+
};
|
|
16
|
+
/** The parts of the route an interception renders under that its config reads. */
|
|
17
|
+
export type AppPageInterceptSegmentConfigRoute = {
|
|
18
|
+
layouts?: readonly (SegmentModule | null | undefined)[];
|
|
19
|
+
layoutTreePositions?: readonly number[];
|
|
20
|
+
routeSegments?: readonly string[];
|
|
21
|
+
slots?: Readonly<Record<string, AppPageInterceptSegmentConfigSlot>> | null;
|
|
22
|
+
};
|
|
23
|
+
/** The parts of the interception's options its config reads. */
|
|
24
|
+
export type AppPageInterceptSegmentConfigOptions = {
|
|
25
|
+
interceptBranchSegments?: readonly string[] | null;
|
|
26
|
+
interceptLayoutSegments?: readonly (readonly string[])[] | null;
|
|
27
|
+
interceptLayouts?: readonly unknown[] | null;
|
|
28
|
+
interceptPage?: unknown;
|
|
29
|
+
interceptSlotKey: string;
|
|
30
|
+
interceptSourcePageSegments?: readonly string[] | null;
|
|
31
|
+
};
|
|
32
|
+
export type AppPageInterceptSegmentConfig = {
|
|
33
|
+
dynamicConfig: string | undefined;
|
|
34
|
+
dynamicStaleTimeSeconds: number | undefined;
|
|
35
|
+
fetchCacheMode: FetchCacheMode | null;
|
|
36
|
+
/** Whether any segment of the interception exports `generateStaticParams`. */
|
|
37
|
+
hasAnyGenerateStaticParams: boolean;
|
|
38
|
+
/** Whether one sits at or below the interception's last dynamic segment. */
|
|
39
|
+
hasGenerateStaticParams: boolean;
|
|
40
|
+
/** Whether the interception's own segments choose the edge runtime. */
|
|
41
|
+
isEdgeRuntime: boolean;
|
|
42
|
+
isStaticEligible: boolean;
|
|
43
|
+
isStaticGenerationEdgeRuntime: boolean;
|
|
44
|
+
revalidateSeconds: number | null;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Next.js renders an interception as its own route, whose loader tree holds
|
|
48
|
+
* the owner's layouts and the intercepting page, never the source's page, so
|
|
49
|
+
* its segment config comes from those modules alone. A sibling intercept's
|
|
50
|
+
* branch takes the children position below its owner folder; a slot
|
|
51
|
+
* intercept's branch takes its slot, beside the other slots of the owner's
|
|
52
|
+
* layouts, and children renders the owner's default.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveAppPageInterceptSegmentConfig(route: AppPageInterceptSegmentConfigRoute, interceptOpts: AppPageInterceptSegmentConfigOptions): AppPageInterceptSegmentConfig;
|
|
55
|
+
//#endregion
|
|
56
|
+
export {};
|