vinext 0.1.7 → 0.2.0
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 +51 -30
- package/dist/build/inject-pregenerated-paths.d.ts +4 -0
- package/dist/build/inject-pregenerated-paths.js +18 -0
- package/dist/build/layout-classification.js +1 -1
- package/dist/build/nitro-route-rules.js +1 -1
- package/dist/build/pages-client-assets-module.d.ts +11 -0
- package/dist/build/pages-client-assets-module.js +27 -0
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +13 -6
- package/dist/build/report.d.ts +13 -2
- package/dist/build/report.js +99 -2
- package/dist/build/run-prerender.d.ts +7 -0
- package/dist/build/run-prerender.js +10 -1
- package/dist/build/standalone.js +2 -0
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.d.ts +18 -0
- package/dist/check.js +77 -19
- package/dist/cli-args.d.ts +1 -2
- package/dist/cli-args.js +1 -1
- package/dist/cli-dev-config.d.ts +12 -0
- package/dist/cli-dev-config.js +23 -0
- package/dist/cli.js +113 -97
- package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay-store.js +1 -1
- package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay.js +2 -2
- package/dist/client/navigation-runtime.d.ts +2 -0
- package/dist/client/navigation-runtime.js +3 -1
- package/dist/client/window-next.d.ts +2 -1
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.js +2 -2
- package/dist/config/config-matchers.js +14 -10
- package/dist/config/next-config.d.ts +6 -3
- package/dist/config/next-config.js +47 -1
- package/dist/config/prerender.d.ts +34 -0
- package/dist/config/prerender.js +55 -0
- package/dist/config/server-external-packages.d.ts +4 -0
- package/dist/config/server-external-packages.js +91 -0
- package/dist/entries/app-rsc-entry.d.ts +2 -1
- package/dist/entries/app-rsc-entry.js +89 -15
- package/dist/entries/app-rsc-manifest.js +10 -0
- package/dist/entries/pages-client-entry.d.ts +3 -0
- package/dist/entries/pages-client-entry.js +16 -1
- package/dist/entries/pages-server-entry.js +6 -2
- package/dist/image/image-adapters-virtual.d.ts +59 -0
- package/dist/image/image-adapters-virtual.js +59 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +211 -118
- package/dist/init-cloudflare.d.ts +43 -0
- package/dist/init-cloudflare.js +839 -0
- package/dist/init-platform.d.ts +40 -0
- package/dist/init-platform.js +195 -0
- package/dist/init.d.ts +16 -38
- package/dist/init.js +208 -97
- package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
- package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
- package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
- package/dist/packages/cloudflare/src/deploy-config.js +150 -0
- package/dist/packages/cloudflare/src/deploy-help.js +55 -0
- package/dist/packages/cloudflare/src/deploy.js +276 -0
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
- package/dist/plugins/ast-scope.d.ts +16 -0
- package/dist/plugins/ast-scope.js +62 -0
- package/dist/plugins/ast-utils.d.ts +27 -1
- package/dist/plugins/ast-utils.js +32 -1
- package/dist/plugins/css-module-imports.d.ts +14 -0
- package/dist/plugins/css-module-imports.js +59 -0
- package/dist/plugins/extensionless-dynamic-import.js +2 -2
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +530 -0
- package/dist/plugins/middleware-server-only.d.ts +8 -6
- package/dist/plugins/middleware-server-only.js +8 -7
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/typeof-window.d.ts +1 -1
- package/dist/plugins/typeof-window.js +28 -56
- package/dist/routing/app-route-graph.d.ts +29 -4
- package/dist/routing/app-route-graph.js +182 -40
- package/dist/routing/app-router.d.ts +5 -0
- package/dist/routing/app-router.js +5 -0
- package/dist/routing/file-matcher.d.ts +8 -0
- package/dist/routing/file-matcher.js +10 -1
- package/dist/routing/pages-router.js +2 -2
- package/dist/server/api-handler.js +9 -14
- package/dist/server/app-browser-action-result.d.ts +4 -1
- package/dist/server/app-browser-action-result.js +8 -1
- package/dist/server/app-browser-entry.js +194 -190
- package/dist/server/app-browser-history-controller.d.ts +2 -1
- package/dist/server/app-browser-history-controller.js +6 -2
- package/dist/server/app-browser-interception-context.d.ts +1 -0
- package/dist/server/app-browser-interception-context.js +4 -2
- package/dist/server/app-browser-navigation-controller.d.ts +2 -0
- package/dist/server/app-browser-navigation-controller.js +60 -31
- package/dist/server/app-browser-server-action-client.d.ts +32 -0
- package/dist/server/app-browser-server-action-client.js +127 -0
- package/dist/server/app-browser-state.d.ts +11 -1
- package/dist/server/app-browser-state.js +25 -8
- package/dist/server/app-browser-visible-commit.d.ts +6 -1
- package/dist/server/app-browser-visible-commit.js +43 -25
- package/dist/server/app-elements-wire.d.ts +9 -2
- package/dist/server/app-elements-wire.js +8 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +4 -3
- package/dist/server/app-fallback-renderer.d.ts +5 -2
- package/dist/server/app-fallback-renderer.js +15 -7
- package/dist/server/app-hydration-cache-publication.d.ts +11 -0
- package/dist/server/app-hydration-cache-publication.js +43 -0
- package/dist/server/app-middleware.d.ts +4 -3
- package/dist/server/app-middleware.js +8 -3
- package/dist/server/app-optimistic-routing.js +11 -4
- package/dist/server/app-page-boundary-render.d.ts +3 -0
- package/dist/server/app-page-boundary-render.js +14 -3
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +10 -3
- package/dist/server/app-page-cache-render.d.ts +1 -0
- package/dist/server/app-page-cache-render.js +8 -4
- package/dist/server/app-page-cache.d.ts +1 -0
- package/dist/server/app-page-cache.js +5 -2
- package/dist/server/app-page-dispatch.d.ts +33 -4
- package/dist/server/app-page-dispatch.js +63 -90
- package/dist/server/app-page-element-builder.d.ts +9 -2
- package/dist/server/app-page-element-builder.js +114 -23
- package/dist/server/app-page-head.d.ts +16 -1
- package/dist/server/app-page-head.js +44 -22
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +8 -1
- package/dist/server/app-page-ppr-runtime.d.ts +7 -0
- package/dist/server/app-page-ppr-runtime.js +70 -0
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +6 -1
- package/dist/server/app-page-render-identity.d.ts +1 -0
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render.d.ts +4 -1
- package/dist/server/app-page-render.js +26 -3
- package/dist/server/app-page-request.d.ts +22 -1
- package/dist/server/app-page-request.js +92 -15
- package/dist/server/app-page-route-wiring.d.ts +14 -2
- package/dist/server/app-page-route-wiring.js +61 -25
- package/dist/server/app-page-search-params-observation.d.ts +4 -2
- package/dist/server/app-page-search-params-observation.js +11 -7
- package/dist/server/app-page-segment-state.d.ts +2 -1
- package/dist/server/app-page-segment-state.js +3 -1
- package/dist/server/app-page-stream.d.ts +5 -0
- package/dist/server/app-page-stream.js +3 -1
- package/dist/server/app-ppr-fallback-shell-render.d.ts +4 -3
- package/dist/server/app-route-handler-dispatch.js +1 -0
- package/dist/server/app-route-handler-execution.js +7 -2
- package/dist/server/app-route-handler-response.js +1 -0
- package/dist/server/app-route-handler-runtime.js +1 -1
- 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 +16 -8
- package/dist/server/app-rsc-errors.js +7 -1
- package/dist/server/app-rsc-handler.d.ts +3 -1
- package/dist/server/app-rsc-handler.js +67 -39
- package/dist/server/app-rsc-request-normalization.d.ts +3 -2
- package/dist/server/app-rsc-request-normalization.js +6 -3
- package/dist/server/app-rsc-route-matching.d.ts +7 -0
- package/dist/server/app-rsc-route-matching.js +36 -3
- package/dist/server/app-segment-config.d.ts +12 -0
- package/dist/server/app-segment-config.js +91 -5
- package/dist/server/app-server-action-execution.d.ts +5 -0
- package/dist/server/app-server-action-execution.js +94 -33
- package/dist/server/app-ssr-entry.d.ts +3 -0
- package/dist/server/app-ssr-entry.js +19 -8
- package/dist/server/app-ssr-stream.d.ts +7 -3
- package/dist/server/app-ssr-stream.js +10 -6
- package/dist/server/app-static-generation.d.ts +1 -0
- package/dist/server/app-static-generation.js +1 -0
- package/dist/server/app-visited-response-cache.d.ts +6 -0
- package/dist/server/app-visited-response-cache.js +3 -1
- package/dist/server/client-trace-metadata.js +26 -0
- package/dist/server/default-global-not-found-module.d.ts +14 -0
- package/dist/server/default-global-not-found-module.js +14 -0
- package/dist/server/dev-route-files.js +4 -0
- package/dist/server/dev-server.js +19 -18
- package/dist/server/dev-stack-sourcemap.d.ts +1 -1
- package/dist/server/dev-stack-sourcemap.js +1 -1
- package/dist/server/fetch-handler.d.ts +2 -0
- package/dist/server/fetch-handler.js +18 -0
- package/dist/server/headers.d.ts +5 -15
- package/dist/server/headers.js +4 -15
- package/dist/server/image-optimization.d.ts +51 -1
- package/dist/server/image-optimization.js +52 -2
- package/dist/server/implicit-tags.js +1 -1
- package/dist/server/isr-cache.d.ts +1 -1
- package/dist/server/isr-cache.js +2 -2
- package/dist/server/metadata-routes.d.ts +3 -1
- package/dist/server/metadata-routes.js +12 -2
- package/dist/server/middleware-runtime.js +6 -1
- package/dist/server/navigation-planner.d.ts +1 -0
- package/dist/server/navigation-planner.js +14 -3
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +4 -6
- package/dist/server/pages-asset-tags.js +12 -12
- package/dist/server/pages-client-assets.d.ts +12 -0
- package/dist/server/pages-client-assets.js +10 -0
- package/dist/server/pages-node-compat.d.ts +8 -1
- package/dist/server/pages-node-compat.js +32 -4
- package/dist/server/pages-page-data.d.ts +24 -1
- package/dist/server/pages-page-data.js +45 -24
- package/dist/server/pages-page-handler.d.ts +2 -1
- package/dist/server/pages-page-handler.js +19 -12
- package/dist/server/pages-page-response.d.ts +7 -0
- package/dist/server/pages-page-response.js +4 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -0
- package/dist/server/pages-request-pipeline.js +25 -1
- package/dist/server/pages-router-entry.d.ts +30 -0
- package/dist/server/pages-router-entry.js +108 -0
- package/dist/server/prerender-manifest.d.ts +3 -1
- package/dist/server/prerender-route-params.js +1 -1
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +48 -26
- package/dist/server/request-pipeline.js +1 -0
- package/dist/server/seed-cache.js +4 -4
- package/dist/server/worker-utils.d.ts +2 -1
- package/dist/server/worker-utils.js +7 -1
- package/dist/shims/app-router-scroll-state.d.ts +1 -0
- package/dist/shims/app-router-scroll-state.js +1 -0
- package/dist/shims/app-router-scroll.js +2 -1
- package/dist/shims/cache.js +19 -15
- package/dist/shims/cdn-cache.js +1 -1
- package/dist/shims/dynamic-preload-chunks.js +2 -1
- package/dist/shims/error-boundary.d.ts +19 -1
- package/dist/shims/error-boundary.js +11 -1
- package/dist/shims/form.d.ts +3 -1
- package/dist/shims/form.js +37 -43
- package/dist/shims/headers.d.ts +9 -1
- package/dist/shims/headers.js +31 -6
- package/dist/shims/image.js +75 -14
- package/dist/shims/internal/app-route-detection.d.ts +2 -17
- package/dist/shims/internal/app-route-detection.js +4 -17
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
- package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
- package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
- package/dist/shims/internal/pages-data-target.d.ts +10 -9
- package/dist/shims/internal/pages-data-target.js +91 -12
- package/dist/shims/internal/pages-router-components.d.ts +7 -0
- package/dist/shims/internal/pages-router-components.js +13 -0
- package/dist/shims/layout-segment-context.d.ts +4 -1
- package/dist/shims/layout-segment-context.js +18 -4
- package/dist/shims/link.js +70 -37
- package/dist/shims/metadata.d.ts +3 -2
- package/dist/shims/metadata.js +8 -4
- package/dist/shims/navigation.d.ts +5 -1
- package/dist/shims/navigation.js +45 -10
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/root-params.d.ts +15 -1
- package/dist/shims/root-params.js +21 -1
- package/dist/shims/router.d.ts +5 -7
- package/dist/shims/router.js +374 -94
- package/dist/shims/server.js +3 -2
- package/dist/shims/slot.js +3 -6
- package/dist/typegen.js +6 -5
- package/dist/utils/client-runtime-metadata.d.ts +2 -18
- package/dist/utils/client-runtime-metadata.js +31 -22
- package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
- package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
- package/dist/utils/domain-locale.d.ts +6 -3
- package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
- package/dist/{server → utils}/middleware-request-headers.js +2 -2
- package/dist/utils/path.d.ts +2 -1
- package/dist/utils/path.js +1 -1
- package/dist/utils/project.d.ts +52 -2
- package/dist/utils/project.js +230 -5
- package/dist/utils/protocol-headers.d.ts +17 -0
- package/dist/utils/protocol-headers.js +17 -0
- package/dist/utils/react-version.d.ts +4 -0
- package/dist/utils/react-version.js +44 -0
- package/package.json +53 -4
- package/dist/deploy.d.ts +0 -190
- package/dist/deploy.js +0 -1033
- package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
- /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
|
@@ -1,17 +1,27 @@
|
|
|
1
|
-
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
2
1
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
3
|
-
import { APP_RSC_RENDER_MODE_NAVIGATION
|
|
2
|
+
import { APP_RSC_RENDER_MODE_NAVIGATION } from "./app-rsc-render-mode.js";
|
|
4
3
|
import "./app-elements.js";
|
|
5
4
|
import { createAppPageRenderIdentity } from "./app-page-render-identity.js";
|
|
5
|
+
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
6
6
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
7
|
+
import { resolveAppPageBranchParams } from "./app-page-params.js";
|
|
7
8
|
import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-page-head.js";
|
|
8
|
-
import { makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
|
|
9
|
+
import { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
|
|
9
10
|
import { buildAppPageElements, createAppPageSourcePage, createAppPageTreePath } from "./app-page-route-wiring.js";
|
|
10
11
|
import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
|
|
11
12
|
import "./app-rsc-route-matching.js";
|
|
12
13
|
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
13
14
|
import { createElement } from "react";
|
|
14
15
|
//#region src/server/app-page-element-builder.ts
|
|
16
|
+
function resolveInterceptLayoutParams(branchSegments, layoutSegments, params) {
|
|
17
|
+
return resolveAppPageBranchParams(branchSegments, layoutSegments.length, params, layoutSegments);
|
|
18
|
+
}
|
|
19
|
+
const REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference");
|
|
20
|
+
function isReactOwnedPageComponent(component) {
|
|
21
|
+
if (typeof component !== "function") return true;
|
|
22
|
+
const candidate = component;
|
|
23
|
+
return candidate.$$typeof === REACT_CLIENT_REFERENCE || candidate.prototype?.isReactComponent != null;
|
|
24
|
+
}
|
|
15
25
|
/**
|
|
16
26
|
* Build the App Router element tree for a matched route.
|
|
17
27
|
*
|
|
@@ -30,7 +40,8 @@ import { createElement } from "react";
|
|
|
30
40
|
*/
|
|
31
41
|
async function buildPageElements(options) {
|
|
32
42
|
const { route, params, routePath, displayPathname = routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
|
|
33
|
-
const
|
|
43
|
+
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
44
|
+
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false } = pageRequest;
|
|
34
45
|
const pageModule = route.page;
|
|
35
46
|
const isSiblingIntercept = opts?.interceptSlotKey === "__vinext_page_intercept" && !!opts?.interceptPage;
|
|
36
47
|
const effectivePageModule = isSiblingIntercept ? opts.interceptPage : pageModule;
|
|
@@ -40,6 +51,7 @@ async function buildPageElements(options) {
|
|
|
40
51
|
const hasPageModule = !!pageModule;
|
|
41
52
|
const renderIdentity = createAppPageRenderIdentity({
|
|
42
53
|
displayPathname,
|
|
54
|
+
targetMatchedPathname: routePath,
|
|
43
55
|
interceptionContext: opts?.interceptionContext ?? null,
|
|
44
56
|
interceptSourceMatchedUrl: opts?.interceptSourceMatchedUrl ?? null,
|
|
45
57
|
interceptSlotId: isSiblingIntercept ? null : opts?.interceptSlotId ?? null
|
|
@@ -64,44 +76,68 @@ async function buildPageElements(options) {
|
|
|
64
76
|
};
|
|
65
77
|
}
|
|
66
78
|
const { hasDynamicMetadata, metadata: resolvedMetadata, pageSearchParams, viewport: resolvedViewport } = await resolveAppPageHead({
|
|
79
|
+
applyFileBasedMetadata: options.applyFileBasedMetadata,
|
|
67
80
|
basePath: options.basePath ?? "",
|
|
68
81
|
layoutModules: route.layouts,
|
|
69
82
|
layoutTreePositions: route.layoutTreePositions,
|
|
70
83
|
metadataRoutes,
|
|
71
|
-
pageModule: effectivePageModule ?? null,
|
|
72
|
-
parallelRoutes: resolveActiveParallelRouteHeadInputs({
|
|
84
|
+
pageModule: isSiblingIntercept ? null : effectivePageModule ?? null,
|
|
85
|
+
parallelRoutes: [...resolveActiveParallelRouteHeadInputs({
|
|
86
|
+
interceptBranchSegments: opts?.interceptBranchSegments ?? null,
|
|
73
87
|
interceptLayouts: opts?.interceptLayouts ?? null,
|
|
88
|
+
interceptLayoutSegments: opts?.interceptLayoutSegments ?? null,
|
|
74
89
|
interceptPage: opts?.interceptPage ?? null,
|
|
75
90
|
interceptParams: opts?.interceptParams ?? null,
|
|
76
91
|
interceptSlotKey: opts?.interceptSlotKey ?? null,
|
|
92
|
+
layoutTreePositions: route.layoutTreePositions,
|
|
77
93
|
params,
|
|
78
94
|
routeSegments: route.routeSegments ?? [],
|
|
95
|
+
slotParams: slotParamOverrides,
|
|
79
96
|
slots: route.slots ?? null
|
|
80
|
-
}),
|
|
97
|
+
}), ...isSiblingIntercept ? [{
|
|
98
|
+
layoutModules: opts?.interceptLayouts ?? [],
|
|
99
|
+
layoutParams: (opts?.interceptLayoutSegments ?? []).map((segments) => resolveInterceptLayoutParams(opts?.interceptBranchSegments ?? segments, segments, effectiveParams)),
|
|
100
|
+
pageModule: effectivePageModule ?? null,
|
|
101
|
+
params: effectiveParams,
|
|
102
|
+
routeSegments: opts?.interceptSourcePageSegments ?? route.routeSegments ?? []
|
|
103
|
+
}] : []],
|
|
81
104
|
params: effectiveParams,
|
|
82
105
|
routePath: route.pattern,
|
|
83
106
|
routeSegments: route.routeSegments ?? null,
|
|
84
|
-
searchParams
|
|
107
|
+
searchParams,
|
|
108
|
+
searchParamsObserver: observeMetadataSearchParamsAccess ? createAppPageSearchParamsObserver() : void 0
|
|
85
109
|
});
|
|
86
110
|
const pageProps = { params: makeThenableParams(effectiveParams) };
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
111
|
+
const hasRequestSearchParams = Object.keys(pageSearchParams).length > 0;
|
|
112
|
+
const createPageElement = (PageComponent, props) => {
|
|
113
|
+
if (isReactOwnedPageComponent(PageComponent)) {
|
|
114
|
+
const invocationProps = { ...props };
|
|
115
|
+
if (searchParams) invocationProps.searchParams = observePageSearchParamsAccess ? makeObservedAppPageSearchParamsThenable(pageSearchParams, { markDynamic: hasRequestSearchParams }) : makeThenableParams(pageSearchParams);
|
|
116
|
+
return createElement(PageComponent, invocationProps);
|
|
117
|
+
}
|
|
118
|
+
const ServerPageComponent = PageComponent;
|
|
119
|
+
const PageInvoker = () => {
|
|
120
|
+
const invocationProps = { ...props };
|
|
121
|
+
if (searchParams) invocationProps.searchParams = observePageSearchParamsAccess ? makeObservedAppPageSearchParamsThenable(pageSearchParams) : makeThenableParams(pageSearchParams);
|
|
122
|
+
return ServerPageComponent(invocationProps);
|
|
123
|
+
};
|
|
124
|
+
return createElement(PageInvoker);
|
|
125
|
+
};
|
|
126
|
+
const pageSearchParamsThenable = searchParams ? makeThenableParams(pageSearchParams) : void 0;
|
|
92
127
|
const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(" ")) : null;
|
|
93
128
|
const slotOverrides = buildSlotOverrides(route, params, routePath, opts);
|
|
94
129
|
const metadataPlacement = hasDynamicMetadata && shouldServeStreamingMetadata(pageRequest.request.headers.get("user-agent") ?? "", options.htmlLimitedBots) ? "body" : "head";
|
|
95
|
-
let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ?
|
|
96
|
-
if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
130
|
+
let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ? createPageElement(EffectivePageComponent, pageProps) : null;
|
|
131
|
+
if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) for (let i = opts.interceptLayouts.length - 1; i >= 0; i--) {
|
|
132
|
+
const LayoutComponent = opts.interceptLayouts[i]?.default;
|
|
133
|
+
if (LayoutComponent) {
|
|
134
|
+
const interceptLayoutSegments = opts.interceptLayoutSegments?.[i] ?? [];
|
|
135
|
+
siblingInterceptElement = createElement(LayoutComponent, { params: makeThenableParams(resolveInterceptLayoutParams(opts.interceptBranchSegments ?? interceptLayoutSegments, interceptLayoutSegments, effectiveParams)) }, siblingInterceptElement);
|
|
101
136
|
}
|
|
102
137
|
}
|
|
103
138
|
return buildAppPageElements({
|
|
104
|
-
element: isSiblingIntercept ? siblingInterceptElement : EffectivePageComponent ?
|
|
139
|
+
element: isSiblingIntercept ? siblingInterceptElement : EffectivePageComponent ? createPageElement(EffectivePageComponent, pageProps) : null,
|
|
140
|
+
createPageElement,
|
|
105
141
|
globalErrorModule: globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE,
|
|
106
142
|
isRscRequest,
|
|
107
143
|
layoutParamAccess: options.layoutParamAccess,
|
|
@@ -142,20 +178,75 @@ async function buildPageElements(options) {
|
|
|
142
178
|
function buildSlotOverrides(route, routeParams, routePath, opts) {
|
|
143
179
|
const overrides = {};
|
|
144
180
|
if (opts && opts.interceptSlotKey && opts.interceptPage && opts.interceptSlotKey !== "__vinext_page_intercept") overrides[opts.interceptSlotKey] = {
|
|
181
|
+
branchSegments: opts.interceptBranchSegments ?? null,
|
|
145
182
|
layoutModules: opts.interceptLayouts || null,
|
|
183
|
+
layoutSegments: opts.interceptLayoutSegments ?? null,
|
|
146
184
|
pageModule: opts.interceptPage,
|
|
147
|
-
params: opts.interceptParams || routeParams
|
|
185
|
+
params: opts.interceptParams || routeParams,
|
|
186
|
+
routeSegments: resolveInterceptedSlotSegments(opts.interceptSourcePageSegments, opts.interceptSlotKey)
|
|
148
187
|
};
|
|
149
188
|
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
150
189
|
for (const [slotKey, params] of Object.entries(slotParamOverrides ?? {})) {
|
|
151
190
|
const existing = overrides[slotKey];
|
|
152
191
|
overrides[slotKey] = existing ? {
|
|
153
192
|
...existing,
|
|
154
|
-
params
|
|
193
|
+
params: existing.params ?? params
|
|
155
194
|
} : { params };
|
|
156
195
|
}
|
|
157
196
|
return Object.keys(overrides).length > 0 ? overrides : null;
|
|
158
197
|
}
|
|
198
|
+
function resolveInterceptedSlotSegments(sourcePageSegments, slotKey) {
|
|
199
|
+
if (!sourcePageSegments) return null;
|
|
200
|
+
const markerTraversals = [
|
|
201
|
+
{
|
|
202
|
+
prefix: "(...)",
|
|
203
|
+
levels: Number.POSITIVE_INFINITY
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
prefix: "(..)(..)",
|
|
207
|
+
levels: 2
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
prefix: "(..)",
|
|
211
|
+
levels: 1
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
prefix: "(.)",
|
|
215
|
+
levels: 0
|
|
216
|
+
}
|
|
217
|
+
];
|
|
218
|
+
const markerIndex = sourcePageSegments.findIndex((segment) => markerTraversals.some(({ prefix }) => segment.startsWith(prefix)));
|
|
219
|
+
if (markerIndex < 0) return null;
|
|
220
|
+
const slotPathSeparator = slotKey.indexOf("@");
|
|
221
|
+
const ownerSegments = (slotPathSeparator >= 0 ? slotKey.slice(slotPathSeparator + 1) : "").split("/").filter(Boolean);
|
|
222
|
+
let segmentStart = ownerSegments.length;
|
|
223
|
+
if (segmentStart === 0 || segmentStart > markerIndex || !ownerSegments.every((segment, index) => sourcePageSegments[index] === segment)) {
|
|
224
|
+
let slotName = null;
|
|
225
|
+
for (let index = ownerSegments.length - 1; index >= 0; index--) if (ownerSegments[index].startsWith("@")) {
|
|
226
|
+
slotName = ownerSegments[index];
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
let slotIndex = -1;
|
|
230
|
+
if (slotName) {
|
|
231
|
+
for (let index = markerIndex - 1; index >= 0; index--) if (sourcePageSegments[index] === slotName) {
|
|
232
|
+
slotIndex = index;
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (slotIndex < 0) return null;
|
|
237
|
+
segmentStart = slotIndex + 1;
|
|
238
|
+
}
|
|
239
|
+
const routeSegments = sourcePageSegments.slice(segmentStart, markerIndex).filter((segment) => !segment.startsWith("@") && !(segment.startsWith("(") && segment.endsWith(")")));
|
|
240
|
+
const markerSegment = sourcePageSegments[markerIndex];
|
|
241
|
+
const marker = markerTraversals.find(({ prefix }) => markerSegment.startsWith(prefix));
|
|
242
|
+
if (!marker) return null;
|
|
243
|
+
if (Number.isFinite(marker.levels)) routeSegments.splice(Math.max(0, routeSegments.length - marker.levels), marker.levels);
|
|
244
|
+
else routeSegments.length = 0;
|
|
245
|
+
const targetSegment = markerSegment.slice(marker.prefix.length);
|
|
246
|
+
if (targetSegment) routeSegments.push(targetSegment);
|
|
247
|
+
routeSegments.push(...sourcePageSegments.slice(markerIndex + 1).filter((segment) => !segment.startsWith("@") && !(segment.startsWith("(") && segment.endsWith(")"))));
|
|
248
|
+
return routeSegments;
|
|
249
|
+
}
|
|
159
250
|
function resolveSlotParamOverrides(route, routePath) {
|
|
160
251
|
const overrides = {};
|
|
161
252
|
const slots = route.slots;
|
|
@@ -201,4 +292,4 @@ function collectParamNameSet(params) {
|
|
|
201
292
|
return set;
|
|
202
293
|
}
|
|
203
294
|
//#endregion
|
|
204
|
-
export { buildPageElements, resolveAppPageNavigationParams };
|
|
295
|
+
export { buildPageElements, resolveAppPageNavigationParams, resolveInterceptedSlotSegments };
|
|
@@ -1,31 +1,45 @@
|
|
|
1
1
|
import { MetadataFileRoute } from "./metadata-routes.js";
|
|
2
2
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
3
|
+
import { ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
3
4
|
import { Metadata, Viewport } from "../shims/metadata.js";
|
|
5
|
+
import { applyFileBasedMetadata } from "./file-based-metadata.js";
|
|
4
6
|
|
|
5
7
|
//#region src/server/app-page-head.d.ts
|
|
6
8
|
type AppPageSearchParams = Record<string, string | string[]>;
|
|
7
9
|
type AppPageHeadModule = Record<string, unknown>;
|
|
10
|
+
type ApplyAppPageFileBasedMetadata = typeof applyFileBasedMetadata;
|
|
8
11
|
type AppPageHeadParallelRoute<TModule extends AppPageHeadModule = AppPageHeadModule> = {
|
|
12
|
+
layoutParams?: readonly AppPageParams[] | null;
|
|
9
13
|
layoutModule?: TModule | null;
|
|
10
14
|
layoutModules?: readonly (TModule | null | undefined)[] | null;
|
|
15
|
+
layoutTreePositions?: readonly number[] | null;
|
|
11
16
|
pageModule?: TModule | null;
|
|
12
17
|
params?: AppPageParams | null;
|
|
13
18
|
routeSegments?: readonly string[] | null;
|
|
14
19
|
};
|
|
15
20
|
type AppPageHeadSlot<TModule extends AppPageHeadModule = AppPageHeadModule> = {
|
|
21
|
+
configLayouts?: readonly (TModule | null | undefined)[] | null;
|
|
22
|
+
configLayoutTreePositions?: readonly number[] | null;
|
|
16
23
|
layout?: TModule | null;
|
|
24
|
+
layoutIndex?: number;
|
|
17
25
|
page?: TModule | null;
|
|
26
|
+
routeSegments?: readonly string[] | null;
|
|
18
27
|
};
|
|
19
28
|
type ResolveActiveParallelRouteHeadInputsOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {
|
|
20
29
|
interceptLayouts?: readonly (TModule | null | undefined)[] | null;
|
|
30
|
+
interceptBranchSegments?: readonly string[] | null;
|
|
31
|
+
interceptLayoutSegments?: readonly (readonly string[])[] | null;
|
|
21
32
|
interceptPage?: TModule | null;
|
|
22
33
|
interceptParams?: AppPageParams | null;
|
|
23
34
|
interceptSlotKey?: string | null;
|
|
35
|
+
layoutTreePositions?: readonly number[] | null;
|
|
24
36
|
params: AppPageParams;
|
|
25
37
|
routeSegments: readonly string[];
|
|
38
|
+
slotParams?: Readonly<Record<string, AppPageParams>> | null;
|
|
26
39
|
slots?: Record<string, AppPageHeadSlot<TModule>> | null;
|
|
27
40
|
};
|
|
28
41
|
type ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadModule> = {
|
|
42
|
+
applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
|
|
29
43
|
/**
|
|
30
44
|
* Configured next.config `basePath`. Threaded into `applyFileBasedMetadata`
|
|
31
45
|
* so file-based metadata route URLs (icon, opengraph-image, manifest, ...)
|
|
@@ -43,6 +57,7 @@ type ResolveAppPageHeadOptions<TModule extends AppPageHeadModule = AppPageHeadMo
|
|
|
43
57
|
routePath: string;
|
|
44
58
|
routeSegments?: readonly string[] | null;
|
|
45
59
|
searchParams?: URLSearchParams | null;
|
|
60
|
+
searchParamsObserver?: ThenableParamsObserver;
|
|
46
61
|
};
|
|
47
62
|
type ResolveAppPageHeadResult = {
|
|
48
63
|
hasDynamicMetadata: boolean;
|
|
@@ -59,4 +74,4 @@ declare function resolveActiveParallelRouteHeadInputs<TModule extends AppPageHea
|
|
|
59
74
|
declare function collectAppPageSearchParams(searchParams: URLSearchParams | null | undefined): AppPageSearchParamsCollection;
|
|
60
75
|
declare function resolveAppPageHead<TModule extends AppPageHeadModule>(options: ResolveAppPageHeadOptions<TModule>): Promise<ResolveAppPageHeadResult>;
|
|
61
76
|
//#endregion
|
|
62
|
-
export { AppPageSearchParams, collectAppPageSearchParams, resolveActiveParallelRouteHeadInputs, resolveAppPageHead };
|
|
77
|
+
export { AppPageSearchParams, ApplyAppPageFileBasedMetadata, collectAppPageSearchParams, resolveActiveParallelRouteHeadInputs, resolveAppPageHead };
|
|
@@ -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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
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
|
-
|
|
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;
|
|
@@ -12,6 +12,7 @@ const DEFAULT_SUBTREE_PROBE_MAX_NODES = 1e3;
|
|
|
12
12
|
const REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref");
|
|
13
13
|
const REACT_LAZY_TYPE = Symbol.for("react.lazy");
|
|
14
14
|
const REACT_MEMO_TYPE = Symbol.for("react.memo");
|
|
15
|
+
const REACT_CLIENT_REFERENCE_TYPE = Symbol.for("react.client.reference");
|
|
15
16
|
var AppPageSubtreeProbeLimitError = class extends Error {
|
|
16
17
|
constructor(message) {
|
|
17
18
|
super(message);
|
|
@@ -36,6 +37,9 @@ function isObjectLike(value) {
|
|
|
36
37
|
function isUnknownFunction(value) {
|
|
37
38
|
return typeof value === "function";
|
|
38
39
|
}
|
|
40
|
+
function isReactClientReference(value) {
|
|
41
|
+
return isObjectLike(value) && Reflect.get(value, "$$typeof") === REACT_CLIENT_REFERENCE_TYPE;
|
|
42
|
+
}
|
|
39
43
|
function readReactMemoType(value) {
|
|
40
44
|
if (!isObjectLike(value) || Reflect.get(value, "$$typeof") !== REACT_MEMO_TYPE) return null;
|
|
41
45
|
return { innerType: Reflect.get(value, "type") };
|
|
@@ -80,6 +84,7 @@ async function probeReactServerSubtree(node, options = {}) {
|
|
|
80
84
|
};
|
|
81
85
|
const renderElementType = async (type, props, depth, wrapperDepth = 0) => {
|
|
82
86
|
if (wrapperDepth > maxDepth) throw new AppPageSubtreeProbeLimitError("App page layout subtree probe exceeded max depth");
|
|
87
|
+
if (isReactClientReference(type)) return false;
|
|
83
88
|
if (isUnknownFunction(type)) {
|
|
84
89
|
await visit(type(props), depth + 1);
|
|
85
90
|
return true;
|
|
@@ -252,7 +257,7 @@ async function probeAppPageBeforeRender(options) {
|
|
|
252
257
|
layoutFlags
|
|
253
258
|
};
|
|
254
259
|
}
|
|
255
|
-
if (options.hasLoadingBoundary) return {
|
|
260
|
+
if (options.hasLoadingBoundary || options.probePageBeforeRender === false) return {
|
|
256
261
|
response: null,
|
|
257
262
|
layoutFlags
|
|
258
263
|
};
|
|
@@ -2,6 +2,7 @@ import { AppElementsInterception } from "./app-elements-wire.js";
|
|
|
2
2
|
//#region src/server/app-page-render-identity.d.ts
|
|
3
3
|
type AppPageRenderIdentityInput = {
|
|
4
4
|
displayPathname: string;
|
|
5
|
+
targetMatchedPathname?: string;
|
|
5
6
|
interceptionContext?: string | null;
|
|
6
7
|
interceptSourceMatchedUrl?: string | null;
|
|
7
8
|
interceptSlotId?: string | null;
|
|
@@ -13,7 +13,7 @@ function normalizeAppPageInterceptionProofPathname(pathname) {
|
|
|
13
13
|
}
|
|
14
14
|
function createAppPageRenderIdentity(input) {
|
|
15
15
|
const interceptionContext = input.interceptionContext ?? null;
|
|
16
|
-
const targetMatchedPathname = normalizeAppPageRenderMatchedPathname(input.displayPathname);
|
|
16
|
+
const targetMatchedPathname = normalizeAppPageRenderMatchedPathname(input.targetMatchedPathname ?? input.displayPathname);
|
|
17
17
|
const sourceMatchedPathname = normalizeAppPageInterceptionProofPathname(input.interceptSourceMatchedUrl ?? null);
|
|
18
18
|
const slotId = input.interceptSlotId ?? null;
|
|
19
19
|
const matchedRoutePathname = sourceMatchedPathname ?? targetMatchedPathname;
|
|
@@ -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: {
|