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,8 +1,8 @@
|
|
|
1
1
|
import { normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
2
2
|
import "./app-elements.js";
|
|
3
3
|
import { mergeElements } from "../shims/slot.js";
|
|
4
|
-
import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
|
|
5
4
|
import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
5
|
+
import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
|
|
6
6
|
import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
|
|
7
7
|
//#region src/server/app-browser-visible-commit.ts
|
|
8
8
|
const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
|
|
@@ -17,6 +17,8 @@ function commitOperationRecord(operation, visibleCommitVersion) {
|
|
|
17
17
|
return {
|
|
18
18
|
id: operation.id,
|
|
19
19
|
lane: operation.lane,
|
|
20
|
+
...operation.navigationCommitKind !== void 0 ? { navigationCommitKind: operation.navigationCommitKind } : {},
|
|
21
|
+
...operation.navigationId !== void 0 ? { navigationId: operation.navigationId } : {},
|
|
20
22
|
startedVisibleCommitVersion: operation.startedVisibleCommitVersion,
|
|
21
23
|
state: "committed",
|
|
22
24
|
visibleCommitVersion
|
|
@@ -56,9 +58,23 @@ function reduceApprovedVisibleCommitState(state, commit) {
|
|
|
56
58
|
const { action } = commit;
|
|
57
59
|
switch (action.type) {
|
|
58
60
|
case "traverse":
|
|
59
|
-
case "navigate":
|
|
60
|
-
|
|
61
|
-
const
|
|
61
|
+
case "navigate":
|
|
62
|
+
case "replace": {
|
|
63
|
+
const bfcacheCompatiblePreserveElementIds = action.reuseCurrentBfcacheIds && action.operation.lane !== "refresh" ? commit.decision.preserveElementIds.filter((id) => {
|
|
64
|
+
const previousBfcacheId = state.bfcacheIds[id];
|
|
65
|
+
return previousBfcacheId !== void 0 && action.bfcacheIds[id] === previousBfcacheId;
|
|
66
|
+
}) : [];
|
|
67
|
+
const preservedSlotOwnerElementIdSet = new Set(bfcacheCompatiblePreserveElementIds);
|
|
68
|
+
const preservePreviousSlotIds = action.reuseCurrentBfcacheIds ? commit.decision.preservePreviousSlotIds.filter((slotId) => {
|
|
69
|
+
const targetBinding = action.slotBindings.find((binding) => binding.slotId === slotId);
|
|
70
|
+
return targetBinding?.ownerLayoutId !== null && targetBinding?.ownerLayoutId !== void 0 && preservedSlotOwnerElementIdSet.has(targetBinding.ownerLayoutId);
|
|
71
|
+
}) : [];
|
|
72
|
+
const hmrPreservedSlotOwnerLayoutIds = action.operation.lane === "hmr" ? bfcacheCompatiblePreserveElementIds.filter((id) => preservePreviousSlotIds.some((slotId) => {
|
|
73
|
+
return action.slotBindings.find((binding) => binding.slotId === slotId)?.ownerLayoutId === id;
|
|
74
|
+
})) : [];
|
|
75
|
+
const hmrPreserveElementIds = action.operation.lane === "hmr" && state.routeId === action.routeId && Object.hasOwn(state.elements, state.routeId) ? [state.routeId, ...hmrPreservedSlotOwnerLayoutIds] : hmrPreservedSlotOwnerLayoutIds;
|
|
76
|
+
const hmrUniquePreserveElementIds = hmrPreserveElementIds.length > 1 ? [...new Set(hmrPreserveElementIds)] : hmrPreserveElementIds;
|
|
77
|
+
const preserveElementIds = action.operation.lane === "hmr" ? hmrUniquePreserveElementIds : bfcacheCompatiblePreserveElementIds;
|
|
62
78
|
const mergedElements = mergeElements(state.elements, action.elements, {
|
|
63
79
|
clearAbsentSlots: action.type === "traverse" || !action.reuseCurrentBfcacheIds,
|
|
64
80
|
preserveAbsentSlots: action.reuseCurrentBfcacheIds && commit.decision.preserveAbsentSlots,
|
|
@@ -84,20 +100,6 @@ function reduceApprovedVisibleCommitState(state, commit) {
|
|
|
84
100
|
slotBindings: mergeSlotBindings(state.slotBindings, action.slotBindings, action.layoutIds, preservePreviousSlotIds)
|
|
85
101
|
}, action.operation);
|
|
86
102
|
}
|
|
87
|
-
case "replace": return commitVisibleRouterState(state, {
|
|
88
|
-
bfcacheIds: action.bfcacheIds,
|
|
89
|
-
elements: action.elements,
|
|
90
|
-
interception: action.interception,
|
|
91
|
-
interceptionContext: action.interceptionContext,
|
|
92
|
-
layoutFlags: action.layoutFlags,
|
|
93
|
-
layoutIds: action.layoutIds,
|
|
94
|
-
navigationSnapshot: action.navigationSnapshot,
|
|
95
|
-
previousNextUrl: action.previousNextUrl,
|
|
96
|
-
renderId: action.renderId,
|
|
97
|
-
rootLayoutTreePath: action.rootLayoutTreePath,
|
|
98
|
-
routeId: action.routeId,
|
|
99
|
-
slotBindings: action.slotBindings
|
|
100
|
-
}, action.operation);
|
|
101
103
|
default: {
|
|
102
104
|
const _exhaustive = action.type;
|
|
103
105
|
throw new Error("[vinext] Unknown router action: " + String(_exhaustive));
|
|
@@ -176,14 +178,28 @@ function addCommitTransactionTrace(decision, pending) {
|
|
|
176
178
|
default: throw new Error("[vinext] Unknown commit decision: " + String(decision));
|
|
177
179
|
}
|
|
178
180
|
}
|
|
179
|
-
function approveHmrVisibleCommit(
|
|
181
|
+
function approveHmrVisibleCommit(options) {
|
|
182
|
+
const { currentState, pending } = options;
|
|
180
183
|
if (pending.action.operation.lane !== "hmr") throw new Error("[vinext] HMR visible commit approval requires an HMR pending operation");
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
const tracedDecision = addCommitTransactionTrace(resolvePendingNavigationCommitDecision({
|
|
185
|
+
activeNavigationId: pending.action.operation.id,
|
|
186
|
+
currentState,
|
|
187
|
+
pending,
|
|
188
|
+
routeManifest: options.routeManifest,
|
|
189
|
+
startedNavigationId: pending.action.operation.id,
|
|
190
|
+
targetHref: options.targetHref
|
|
191
|
+
}), pending);
|
|
192
|
+
if (tracedDecision.disposition === "commit") return {
|
|
193
|
+
approvedCommit: createApprovedVisibleCommit({
|
|
194
|
+
decision: tracedDecision,
|
|
195
|
+
pending
|
|
196
|
+
}),
|
|
197
|
+
decision: tracedDecision
|
|
198
|
+
};
|
|
199
|
+
return {
|
|
200
|
+
approvedCommit: null,
|
|
201
|
+
decision: tracedDecision
|
|
202
|
+
};
|
|
187
203
|
}
|
|
188
204
|
function approvePendingNavigationCommit(options) {
|
|
189
205
|
const decision = addCommitTransactionTrace(resolvePendingNavigationCommitDecision({
|
|
@@ -213,6 +229,8 @@ function approvePendingNavigationCommit(options) {
|
|
|
213
229
|
async function resolveAndClassifyNavigationCommit(options) {
|
|
214
230
|
const pending = await createPendingNavigationCommit({
|
|
215
231
|
currentState: options.currentState,
|
|
232
|
+
navigationCommitKind: void 0,
|
|
233
|
+
navigationId: options.startedNavigationId,
|
|
216
234
|
nextElements: options.nextElements,
|
|
217
235
|
navigationSnapshot: options.navigationSnapshot,
|
|
218
236
|
operationLane: options.operationLane,
|
|
@@ -6,6 +6,7 @@ import { ReactNode } from "react";
|
|
|
6
6
|
//#region src/server/app-elements-wire.d.ts
|
|
7
7
|
declare const APP_ARTIFACT_COMPATIBILITY_KEY = "__artifactCompatibility";
|
|
8
8
|
declare const APP_CACHE_ENTRY_REUSE_PROOF_KEY = "__cacheEntryReuseProof";
|
|
9
|
+
declare const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
|
|
9
10
|
declare const APP_INTERCEPTION_KEY = "__interception";
|
|
10
11
|
declare const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
11
12
|
declare const APP_LAYOUT_IDS_KEY = "__layoutIds";
|
|
@@ -70,6 +71,7 @@ type LayoutFlags = Readonly<Record<string, "s" | "d">>;
|
|
|
70
71
|
type AppElementsMetadata = {
|
|
71
72
|
artifactCompatibility: ArtifactCompatibilityEnvelope;
|
|
72
73
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
74
|
+
dynamicStaleTimeSeconds?: number;
|
|
73
75
|
interception: AppElementsInterception | null;
|
|
74
76
|
interceptionContext: string | null;
|
|
75
77
|
layoutIds: readonly string[];
|
|
@@ -100,6 +102,7 @@ type AppElementsWireElementKey = {
|
|
|
100
102
|
treePath: string;
|
|
101
103
|
};
|
|
102
104
|
type AppElementsWireMetadataInput = {
|
|
105
|
+
dynamicStaleTimeSeconds?: number;
|
|
103
106
|
interception?: AppElementsInterception | null;
|
|
104
107
|
interceptionContext: string | null;
|
|
105
108
|
layoutIds?: readonly string[];
|
|
@@ -109,6 +112,7 @@ type AppElementsWireMetadataInput = {
|
|
|
109
112
|
sourcePage?: string | null;
|
|
110
113
|
};
|
|
111
114
|
type AppElementsWireMetadataEntries = Readonly<{
|
|
115
|
+
[APP_DYNAMIC_STALE_TIME_KEY]?: number;
|
|
112
116
|
[APP_ROUTE_KEY]: string;
|
|
113
117
|
[APP_INTERCEPTION_KEY]?: AppElementsInterception;
|
|
114
118
|
[APP_INTERCEPTION_CONTEXT_KEY]: string | null;
|
|
@@ -123,10 +127,11 @@ type AppElementsWireMetadataEntries = Readonly<{
|
|
|
123
127
|
* known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements
|
|
124
128
|
* which only carry render-time values.
|
|
125
129
|
*/
|
|
126
|
-
type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | RenderObservation | readonly string[] | readonly AppElementsSlotBinding[]>>;
|
|
130
|
+
type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | RenderObservation | number | readonly string[] | readonly AppElementsSlotBinding[]>>;
|
|
127
131
|
type AppElementsWireKeys = {
|
|
128
132
|
readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;
|
|
129
133
|
readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;
|
|
134
|
+
readonly dynamicStaleTime: typeof APP_DYNAMIC_STALE_TIME_KEY;
|
|
130
135
|
readonly interception: typeof APP_INTERCEPTION_KEY;
|
|
131
136
|
readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;
|
|
132
137
|
readonly layoutIds: typeof APP_LAYOUT_IDS_KEY;
|
|
@@ -149,6 +154,7 @@ type AppElementsWireCodec = {
|
|
|
149
154
|
element: ReactNode | AppElements;
|
|
150
155
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
151
156
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
157
|
+
dynamicStaleTimeSeconds?: number;
|
|
152
158
|
layoutFlags: LayoutFlags;
|
|
153
159
|
renderObservation?: RenderObservation;
|
|
154
160
|
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
@@ -182,6 +188,7 @@ declare function buildOutgoingAppPayload(input: {
|
|
|
182
188
|
element: ReactNode | AppElements;
|
|
183
189
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
184
190
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
191
|
+
dynamicStaleTimeSeconds?: number;
|
|
185
192
|
layoutFlags: LayoutFlags;
|
|
186
193
|
renderObservation?: RenderObservation;
|
|
187
194
|
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
@@ -189,4 +196,4 @@ declare function buildOutgoingAppPayload(input: {
|
|
|
189
196
|
declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
|
|
190
197
|
declare const AppElementsWire: AppElementsWireCodec;
|
|
191
198
|
//#endregion
|
|
192
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|
|
199
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|
|
@@ -8,6 +8,7 @@ import { isValidElement } from "react";
|
|
|
8
8
|
const APP_INTERCEPTION_SEPARATOR = "\0";
|
|
9
9
|
const APP_ARTIFACT_COMPATIBILITY_KEY = "__artifactCompatibility";
|
|
10
10
|
const APP_CACHE_ENTRY_REUSE_PROOF_KEY = "__cacheEntryReuseProof";
|
|
11
|
+
const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
|
|
11
12
|
const APP_INTERCEPTION_KEY = "__interception";
|
|
12
13
|
const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
13
14
|
const APP_LAYOUT_IDS_KEY = "__layoutIds";
|
|
@@ -177,6 +178,7 @@ function createAppElementsWireMetadataEntries(input) {
|
|
|
177
178
|
[APP_INTERCEPTION_CONTEXT_KEY]: input.interceptionContext,
|
|
178
179
|
[APP_LAYOUT_IDS_KEY]: layoutIds,
|
|
179
180
|
[APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath,
|
|
181
|
+
...input.dynamicStaleTimeSeconds === void 0 ? {} : { [APP_DYNAMIC_STALE_TIME_KEY]: input.dynamicStaleTimeSeconds },
|
|
180
182
|
...input.sourcePage === null || input.sourcePage === void 0 ? {} : { [APP_SOURCE_PAGE_KEY]: input.sourcePage }
|
|
181
183
|
};
|
|
182
184
|
const entriesWithInterception = input.interception ? {
|
|
@@ -319,6 +321,7 @@ function buildOutgoingAppPayload(input) {
|
|
|
319
321
|
if (skippedLayoutIds.size > 0) payload[APP_SKIPPED_LAYOUT_IDS_KEY] = [...skippedLayoutIds];
|
|
320
322
|
payload[APP_ARTIFACT_COMPATIBILITY_KEY] = input.artifactCompatibility ?? createArtifactCompatibilityEnvelope();
|
|
321
323
|
if (input.cacheEntryReuseProof) payload[APP_CACHE_ENTRY_REUSE_PROOF_KEY] = input.cacheEntryReuseProof;
|
|
324
|
+
if (input.dynamicStaleTimeSeconds !== void 0) payload[APP_DYNAMIC_STALE_TIME_KEY] = input.dynamicStaleTimeSeconds;
|
|
322
325
|
if (input.renderObservation) payload[APP_RENDER_OBSERVATION_KEY] = input.renderObservation;
|
|
323
326
|
return payload;
|
|
324
327
|
}
|
|
@@ -394,10 +397,13 @@ function readAppElementsMetadata(elements) {
|
|
|
394
397
|
const interception = parseInterceptionMetadata(elements[APP_INTERCEPTION_KEY]);
|
|
395
398
|
const artifactCompatibility = readArtifactCompatibilityMetadata(elements[APP_ARTIFACT_COMPATIBILITY_KEY]);
|
|
396
399
|
const cacheEntryReuseProof = parseCacheEntryReuseProofMetadata(elements[APP_CACHE_ENTRY_REUSE_PROOF_KEY]);
|
|
400
|
+
const dynamicStaleTime = elements[APP_DYNAMIC_STALE_TIME_KEY];
|
|
401
|
+
const dynamicStaleTimeSeconds = typeof dynamicStaleTime === "number" && Number.isFinite(dynamicStaleTime) && dynamicStaleTime >= 0 ? dynamicStaleTime : void 0;
|
|
397
402
|
const sourcePage = readSourcePageMetadata(elements[APP_SOURCE_PAGE_KEY]);
|
|
398
403
|
return {
|
|
399
404
|
artifactCompatibility,
|
|
400
405
|
...cacheEntryReuseProof ? { cacheEntryReuseProof } : {},
|
|
406
|
+
...dynamicStaleTimeSeconds === void 0 ? {} : { dynamicStaleTimeSeconds },
|
|
401
407
|
interception,
|
|
402
408
|
interceptionContext: interceptionContext ?? null,
|
|
403
409
|
layoutIds,
|
|
@@ -413,6 +419,7 @@ const AppElementsWire = {
|
|
|
413
419
|
keys: {
|
|
414
420
|
artifactCompatibility: APP_ARTIFACT_COMPATIBILITY_KEY,
|
|
415
421
|
cacheEntryReuseProof: APP_CACHE_ENTRY_REUSE_PROOF_KEY,
|
|
422
|
+
dynamicStaleTime: APP_DYNAMIC_STALE_TIME_KEY,
|
|
416
423
|
interception: APP_INTERCEPTION_KEY,
|
|
417
424
|
interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,
|
|
418
425
|
layoutIds: APP_LAYOUT_IDS_KEY,
|
|
@@ -440,4 +447,4 @@ const AppElementsWire = {
|
|
|
440
447
|
withLayoutFlags
|
|
441
448
|
};
|
|
442
449
|
//#endregion
|
|
443
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|
|
450
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
1
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
2
2
|
|
|
3
3
|
//#region src/server/app-elements.d.ts
|
|
4
4
|
declare const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
|
|
@@ -6,4 +6,4 @@ declare function getMountedSlotIds(elements: AppElements): string[];
|
|
|
6
6
|
declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
|
|
7
7
|
declare function resolveVisitedResponseInterceptionContext(requestInterceptionContext: string | null, payloadInterceptionContext: string | null): string | null;
|
|
8
8
|
//#endregion
|
|
9
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
9
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
1
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
2
2
|
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
3
3
|
//#region src/server/app-elements.ts
|
|
4
4
|
const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
|
|
5
5
|
function getMountedSlotIds(elements) {
|
|
6
6
|
return Object.keys(elements).filter((key) => {
|
|
7
7
|
const value = elements[key];
|
|
8
|
-
|
|
8
|
+
const parsed = AppElementsWire.parseElementKey(key);
|
|
9
|
+
return parsed?.kind === "slot" && parsed.name !== "children" && value !== null && value !== void 0 && value !== UNMATCHED_SLOT;
|
|
9
10
|
}).sort();
|
|
10
11
|
}
|
|
11
12
|
function getMountedSlotIdsHeader(elements) {
|
|
@@ -15,4 +16,4 @@ function resolveVisitedResponseInterceptionContext(requestInterceptionContext, p
|
|
|
15
16
|
return payloadInterceptionContext ?? requestInterceptionContext;
|
|
16
17
|
}
|
|
17
18
|
//#endregion
|
|
18
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
19
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
@@ -4,6 +4,7 @@ import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
|
4
4
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
5
5
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
6
6
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
7
|
+
import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
|
|
7
8
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
8
9
|
import { AppPageBoundaryRoute } from "./app-page-boundary-render.js";
|
|
9
10
|
import { ReactNode } from "react";
|
|
@@ -27,11 +28,13 @@ type AppFallbackRendererFontProviders = {
|
|
|
27
28
|
getFontStyles: () => string[];
|
|
28
29
|
};
|
|
29
30
|
type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> = {
|
|
31
|
+
applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
|
|
30
32
|
clearRequestContext: () => void;
|
|
31
33
|
createRscOnErrorHandler: (request: Request, pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
32
34
|
fontProviders: AppFallbackRendererFontProviders;
|
|
33
35
|
getNavigationContext: () => NavigationContext | null;
|
|
34
|
-
globalErrorModule?: TModule | null;
|
|
36
|
+
globalErrorModule?: TModule | null; /** Whether experimental.globalNotFound is enabled for route-miss 404s. */
|
|
37
|
+
globalNotFoundEnabled?: boolean;
|
|
35
38
|
/**
|
|
36
39
|
* Loader for the user's `app/global-not-found.tsx` module. When provided,
|
|
37
40
|
* route-miss 404s render this module as a standalone document (skipping the
|
|
@@ -73,7 +76,7 @@ type AppFallbackRendererCallContext = {
|
|
|
73
76
|
sourcePageSegments?: readonly string[] | null;
|
|
74
77
|
};
|
|
75
78
|
type AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {
|
|
76
|
-
renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext) => Promise<Response | null>;
|
|
79
|
+
renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext, callContext?: AppFallbackRendererCallContext, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
|
|
77
80
|
renderHttpAccessFallback: (route: AppPageBoundaryRoute<TModule> | null, statusCode: number, isRscRequest: boolean, request: Request, opts: {
|
|
78
81
|
boundaryComponent?: AppPageComponent | null;
|
|
79
82
|
boundaryModule?: TModule | null;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./app-page-boundary-render.js";
|
|
2
2
|
import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
|
|
3
|
+
import { DEFAULT_GLOBAL_NOT_FOUND_MODULE } from "./default-global-not-found-module.js";
|
|
3
4
|
import { DEFAULT_NOT_FOUND_MODULE } from "./default-not-found-module.js";
|
|
4
5
|
//#region src/server/app-fallback-renderer.ts
|
|
5
6
|
const EMPTY_MW_CTX = {
|
|
@@ -7,7 +8,7 @@ const EMPTY_MW_CTX = {
|
|
|
7
8
|
status: null
|
|
8
9
|
};
|
|
9
10
|
function createAppFallbackRenderer(options) {
|
|
10
|
-
const { basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
11
|
+
const { applyFileBasedMetadata, basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, globalNotFoundEnabled = false, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
11
12
|
const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } = rootBoundaries;
|
|
12
13
|
const effectiveGlobalErrorModule = globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE;
|
|
13
14
|
const effectiveRootNotFoundModule = rootNotFoundModule ?? DEFAULT_NOT_FOUND_MODULE;
|
|
@@ -19,10 +20,12 @@ function createAppFallbackRenderer(options) {
|
|
|
19
20
|
}
|
|
20
21
|
return {
|
|
21
22
|
async renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, middlewareContext, callContext) {
|
|
22
|
-
|
|
23
|
+
const useGlobalNotFound = statusCode === 404 && globalNotFoundEnabled && !route && !opts?.boundaryComponent;
|
|
24
|
+
if (useGlobalNotFound && loadGlobalNotFoundModule) {
|
|
23
25
|
const globalNotFoundModule = await resolveGlobalNotFoundModule();
|
|
24
26
|
const globalNotFoundComponent = globalNotFoundModule?.default ?? null;
|
|
25
27
|
if (globalNotFoundComponent) return renderAppPageHttpAccessFallback({
|
|
28
|
+
applyFileBasedMetadata,
|
|
26
29
|
boundaryComponent: globalNotFoundComponent,
|
|
27
30
|
boundaryModule: globalNotFoundModule ?? null,
|
|
28
31
|
buildFontLinkHeader: fontProviders.buildFontLinkHeader,
|
|
@@ -56,7 +59,9 @@ function createAppFallbackRenderer(options) {
|
|
|
56
59
|
statusCode
|
|
57
60
|
});
|
|
58
61
|
}
|
|
62
|
+
const routeMissRootNotFoundModule = useGlobalNotFound ? DEFAULT_GLOBAL_NOT_FOUND_MODULE : effectiveRootNotFoundModule;
|
|
59
63
|
return renderAppPageHttpAccessFallback({
|
|
64
|
+
applyFileBasedMetadata,
|
|
60
65
|
basePath,
|
|
61
66
|
trailingSlash,
|
|
62
67
|
boundaryComponent: opts?.boundaryComponent ?? null,
|
|
@@ -73,7 +78,7 @@ function createAppFallbackRenderer(options) {
|
|
|
73
78
|
globalErrorModule: effectiveGlobalErrorModule,
|
|
74
79
|
isEdgeRuntime: callContext?.isEdgeRuntime,
|
|
75
80
|
isRscRequest,
|
|
76
|
-
layoutModules: opts?.layouts ?? null,
|
|
81
|
+
layoutModules: useGlobalNotFound ? [] : opts?.layouts ?? null,
|
|
77
82
|
loadSsrHandler: ssrLoader,
|
|
78
83
|
makeThenableParams,
|
|
79
84
|
matchedParams: opts?.matchedParams ?? route?.params ?? {},
|
|
@@ -82,12 +87,13 @@ function createAppFallbackRenderer(options) {
|
|
|
82
87
|
requestUrl: request.url,
|
|
83
88
|
resolveChildSegments,
|
|
84
89
|
rootForbiddenModule,
|
|
85
|
-
rootLayouts,
|
|
86
|
-
rootNotFoundModule:
|
|
90
|
+
rootLayouts: useGlobalNotFound ? [] : rootLayouts,
|
|
91
|
+
rootNotFoundModule: routeMissRootNotFoundModule,
|
|
87
92
|
rootUnauthorizedModule,
|
|
88
|
-
route,
|
|
93
|
+
route: useGlobalNotFound ? null : route,
|
|
89
94
|
renderToReadableStream: rscRenderer,
|
|
90
95
|
scriptNonce,
|
|
96
|
+
skipLayoutWrapping: useGlobalNotFound,
|
|
91
97
|
sourcePageSegments: callContext?.sourcePageSegments,
|
|
92
98
|
statusCode
|
|
93
99
|
});
|
|
@@ -95,8 +101,9 @@ function createAppFallbackRenderer(options) {
|
|
|
95
101
|
renderNotFound(route, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext) {
|
|
96
102
|
return this.renderHttpAccessFallback(route, 404, isRscRequest, request, { matchedParams }, scriptNonce, middlewareContext, callContext);
|
|
97
103
|
},
|
|
98
|
-
renderErrorBoundary(route, error, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext) {
|
|
104
|
+
renderErrorBoundary(route, error, isRscRequest, request, matchedParams, scriptNonce, middlewareContext, callContext, errorOrigin = "rsc") {
|
|
99
105
|
return renderAppPageErrorBoundary({
|
|
106
|
+
applyFileBasedMetadata,
|
|
100
107
|
basePath,
|
|
101
108
|
trailingSlash,
|
|
102
109
|
buildFontLinkHeader: fontProviders.buildFontLinkHeader,
|
|
@@ -105,6 +112,7 @@ function createAppFallbackRenderer(options) {
|
|
|
105
112
|
return buildRscOnErrorHandler(request, pathname, routePath);
|
|
106
113
|
},
|
|
107
114
|
error,
|
|
115
|
+
errorOrigin,
|
|
108
116
|
getFontLinks: fontProviders.getFontLinks,
|
|
109
117
|
getFontPreloads: fontProviders.getFontPreloads,
|
|
110
118
|
getFontStyles: fontProviders.getFontStyles,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/server/app-hydration-cache-publication.d.ts
|
|
2
|
+
type HydrationCachePublication = {
|
|
3
|
+
commit(): void;
|
|
4
|
+
complete(): void;
|
|
5
|
+
fail(): void;
|
|
6
|
+
invalidate(): void;
|
|
7
|
+
publish(publishCandidate: () => () => void): void;
|
|
8
|
+
};
|
|
9
|
+
declare function createHydrationCachePublication(): HydrationCachePublication;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { HydrationCachePublication, createHydrationCachePublication };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/server/app-hydration-cache-publication.ts
|
|
2
|
+
function createHydrationCachePublication() {
|
|
3
|
+
let state = "pending";
|
|
4
|
+
let pendingPublication = null;
|
|
5
|
+
let invalidatePublishedCandidate = null;
|
|
6
|
+
const publishPendingCandidate = () => {
|
|
7
|
+
if (state !== "committed" && state !== "complete" || pendingPublication === null) return;
|
|
8
|
+
const publishCandidate = pendingPublication;
|
|
9
|
+
pendingPublication = null;
|
|
10
|
+
invalidatePublishedCandidate = publishCandidate();
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
commit() {
|
|
14
|
+
if (state !== "pending") return;
|
|
15
|
+
state = "committed";
|
|
16
|
+
publishPendingCandidate();
|
|
17
|
+
},
|
|
18
|
+
complete() {
|
|
19
|
+
if (state === "committed") state = "complete";
|
|
20
|
+
},
|
|
21
|
+
fail() {
|
|
22
|
+
if (state === "complete" || state === "invalidated") return;
|
|
23
|
+
state = "invalidated";
|
|
24
|
+
pendingPublication = null;
|
|
25
|
+
invalidatePublishedCandidate?.();
|
|
26
|
+
invalidatePublishedCandidate = null;
|
|
27
|
+
},
|
|
28
|
+
invalidate() {
|
|
29
|
+
if (state === "invalidated") return;
|
|
30
|
+
state = "invalidated";
|
|
31
|
+
pendingPublication = null;
|
|
32
|
+
invalidatePublishedCandidate?.();
|
|
33
|
+
invalidatePublishedCandidate = null;
|
|
34
|
+
},
|
|
35
|
+
publish(publishCandidate) {
|
|
36
|
+
if (state === "invalidated") return;
|
|
37
|
+
pendingPublication = publishCandidate;
|
|
38
|
+
publishPendingCandidate();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createHydrationCachePublication };
|
|
@@ -12,11 +12,11 @@ type ApplyAppMiddlewareOptions = {
|
|
|
12
12
|
basePath?: string;
|
|
13
13
|
cleanPathname: string;
|
|
14
14
|
context: AppMiddlewareContext;
|
|
15
|
+
hadBasePath?: boolean;
|
|
15
16
|
i18nConfig?: NextI18nConfig | null;
|
|
16
17
|
/**
|
|
17
|
-
* Whether the inbound request was a `_next/data` fetch
|
|
18
|
-
*
|
|
19
|
-
* INTERNAL_HEADERS and is stripped before this function runs.
|
|
18
|
+
* Whether the inbound request was recognized as a `_next/data` fetch from
|
|
19
|
+
* trusted URL normalization before internal headers were stripped.
|
|
20
20
|
*/
|
|
21
21
|
isDataRequest?: boolean;
|
|
22
22
|
filePath?: string;
|
|
@@ -34,6 +34,7 @@ type ApplyAppMiddlewareOptions = {
|
|
|
34
34
|
type ApplyAppMiddlewareResult = {
|
|
35
35
|
kind: "continue";
|
|
36
36
|
cleanPathname: string;
|
|
37
|
+
rewritten: boolean;
|
|
37
38
|
search: string | null;
|
|
38
39
|
} | {
|
|
39
40
|
kind: "response";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { VINEXT_MW_CTX_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
+
import { FLIGHT_HEADERS } from "./headers.js";
|
|
3
|
+
import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
|
|
3
4
|
import { isExternalUrl, proxyExternalRequest } from "../config/config-matchers.js";
|
|
4
5
|
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
6
|
import { cloneRequestWithHeaders, processMiddlewareHeaders } from "./request-pipeline.js";
|
|
@@ -100,6 +101,7 @@ async function applyAppMiddleware(options) {
|
|
|
100
101
|
const forwarded = applyForwardedMiddlewareContext(options.request, options.context);
|
|
101
102
|
const middlewareRequest = requestWithoutFlightHeaders(options.request);
|
|
102
103
|
let cleanPathname = options.cleanPathname;
|
|
104
|
+
let rewritten = false;
|
|
103
105
|
let search = null;
|
|
104
106
|
if (forwarded.rewriteUrl) try {
|
|
105
107
|
if (isExternalMiddlewareRewrite(forwarded.rewriteUrl, middlewareRequest)) return {
|
|
@@ -108,6 +110,7 @@ async function applyAppMiddleware(options) {
|
|
|
108
110
|
};
|
|
109
111
|
const rewriteParsed = new URL(forwarded.rewriteUrl, middlewareRequest.url);
|
|
110
112
|
cleanPathname = rewriteParsed.pathname;
|
|
113
|
+
rewritten = true;
|
|
111
114
|
search = rewriteParsed.search;
|
|
112
115
|
} catch (e) {
|
|
113
116
|
console.error("[vinext] Failed to apply forwarded middleware rewrite:", e);
|
|
@@ -116,7 +119,7 @@ async function applyAppMiddleware(options) {
|
|
|
116
119
|
if (!forwarded.applied) {
|
|
117
120
|
const result = await executeMiddleware({
|
|
118
121
|
basePath: options.basePath,
|
|
119
|
-
hadBasePath: true,
|
|
122
|
+
hadBasePath: options.hadBasePath ?? true,
|
|
120
123
|
filePath: options.filePath,
|
|
121
124
|
i18nConfig: options.i18nConfig,
|
|
122
125
|
isDataRequest: options.isDataRequest,
|
|
@@ -150,6 +153,7 @@ async function applyAppMiddleware(options) {
|
|
|
150
153
|
};
|
|
151
154
|
const rewriteParsed = new URL(result.rewriteUrl, middlewareRequest.url);
|
|
152
155
|
cleanPathname = rewriteParsed.pathname;
|
|
156
|
+
rewritten = true;
|
|
153
157
|
search = rewriteParsed.search;
|
|
154
158
|
}
|
|
155
159
|
}
|
|
@@ -161,6 +165,7 @@ async function applyAppMiddleware(options) {
|
|
|
161
165
|
return {
|
|
162
166
|
kind: "continue",
|
|
163
167
|
cleanPathname,
|
|
168
|
+
rewritten,
|
|
164
169
|
search
|
|
165
170
|
};
|
|
166
171
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { buildParams, decodeMatchedParams, splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
2
2
|
import { stripBasePath } from "../utils/base-path.js";
|
|
3
|
-
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
4
3
|
import { isUnknownRecord } from "../utils/record.js";
|
|
5
4
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
6
5
|
import "./app-elements.js";
|
|
6
|
+
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
7
7
|
import { stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
8
8
|
import { Suspense, createElement, isValidElement } from "react";
|
|
9
9
|
//#region src/server/app-optimistic-routing.ts
|
|
@@ -162,8 +162,15 @@ function elementHasSuspenseFallback(value, depth = 0) {
|
|
|
162
162
|
if (!isUnknownRecord(props)) return false;
|
|
163
163
|
return elementHasSuspenseFallback(Reflect.get(props, "children"), depth + 1);
|
|
164
164
|
}
|
|
165
|
-
function getPageElementIds(elements) {
|
|
166
|
-
|
|
165
|
+
function getPageElementIds(elements, route) {
|
|
166
|
+
const pageElementIds = /* @__PURE__ */ new Set();
|
|
167
|
+
if (route.pageId && Object.hasOwn(elements, route.pageId)) pageElementIds.add(route.pageId);
|
|
168
|
+
for (const slotId of route.slotIds) {
|
|
169
|
+
const parsed = AppElementsWire.parseElementKey(slotId);
|
|
170
|
+
if (parsed?.kind === "slot" && parsed.name === "children" && Object.hasOwn(elements, slotId)) pageElementIds.add(slotId);
|
|
171
|
+
}
|
|
172
|
+
for (const key of Object.keys(elements)) if (AppElementsWire.parseElementKey(key)?.kind === "page") pageElementIds.add(key);
|
|
173
|
+
return Array.from(pageElementIds).sort();
|
|
167
174
|
}
|
|
168
175
|
function OptimisticRouteSegment() {
|
|
169
176
|
throw OPTIMISTIC_ROUTE_SEGMENT_SUSPENSE_TRIGGER;
|
|
@@ -182,7 +189,7 @@ function createOptimisticRouteTemplate(options) {
|
|
|
182
189
|
if (!options.allowLoadingShell && !elementHasSuspenseFallback(routeElement)) return null;
|
|
183
190
|
if (options.allowLoadingShell && options.elements["__prefetchLoadingShell"] !== "LoadingBoundary") return null;
|
|
184
191
|
if (options.allowLoadingShell && (routeElement === void 0 || routeElement === null)) return null;
|
|
185
|
-
const pageElementIds = getPageElementIds(options.elements);
|
|
192
|
+
const pageElementIds = getPageElementIds(options.elements, match.route);
|
|
186
193
|
if (pageElementIds.length === 0) return null;
|
|
187
194
|
return {
|
|
188
195
|
elements: options.elements,
|
|
@@ -4,6 +4,7 @@ import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
|
4
4
|
import { AppPageParams } from "./app-page-boundary.js";
|
|
5
5
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
6
6
|
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
7
|
+
import { ApplyAppPageFileBasedMetadata } from "./app-page-head.js";
|
|
7
8
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
8
9
|
import { ComponentType, ReactNode } from "react";
|
|
9
10
|
|
|
@@ -27,6 +28,7 @@ type AppPageBoundaryRoute<TModule extends AppPageModule = AppPageModule> = {
|
|
|
27
28
|
unauthorized?: TModule | null;
|
|
28
29
|
};
|
|
29
30
|
type AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageModule> = {
|
|
31
|
+
applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
|
|
30
32
|
buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;
|
|
31
33
|
clearRequestContext: () => void;
|
|
32
34
|
createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
@@ -73,6 +75,7 @@ type RenderAppPageHttpAccessFallbackOptions<TModule extends AppPageModule = AppP
|
|
|
73
75
|
} & AppPageBoundaryRenderCommonOptions<TModule>;
|
|
74
76
|
type RenderAppPageErrorBoundaryOptions<TModule extends AppPageModule = AppPageModule> = {
|
|
75
77
|
error: unknown;
|
|
78
|
+
errorOrigin?: "rsc" | "ssr";
|
|
76
79
|
matchedParams?: AppPageParams | null;
|
|
77
80
|
route?: AppPageBoundaryRoute<TModule> | null;
|
|
78
81
|
sanitizeErrorForClient: (error: Error) => Error;
|
|
@@ -3,7 +3,7 @@ import { AppElementsWire } from "./app-elements-wire.js";
|
|
|
3
3
|
import "./app-elements.js";
|
|
4
4
|
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
5
5
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
6
|
-
import { ErrorBoundary, GlobalErrorBoundary } from "../shims/error-boundary.js";
|
|
6
|
+
import { ErrorBoundary, GlobalErrorBoundary, SerializedErrorBoundary } from "../shims/error-boundary.js";
|
|
7
7
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
8
8
|
import { MetadataHead, ViewportHead } from "../shims/metadata.js";
|
|
9
9
|
import { resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
@@ -152,6 +152,7 @@ async function renderAppPageHttpAccessFallback(options) {
|
|
|
152
152
|
const pathname = new URL(options.requestUrl).pathname;
|
|
153
153
|
const routeSegments = resolveHttpAccessFallbackHeadRouteSegments(options.route, layoutModules);
|
|
154
154
|
const { metadata, viewport } = await resolveAppPageHead({
|
|
155
|
+
applyFileBasedMetadata: options.applyFileBasedMetadata,
|
|
155
156
|
basePath: options.basePath ?? "",
|
|
156
157
|
layoutModules,
|
|
157
158
|
layoutTreePositions: resolveHttpAccessFallbackHeadLayoutTreePositions(options.route, layoutModules),
|
|
@@ -214,7 +215,7 @@ async function renderAppPageErrorBoundary(options) {
|
|
|
214
215
|
if (!errorBoundary.component) return null;
|
|
215
216
|
const rawError = options.error instanceof Error ? options.error : new Error(String(options.error));
|
|
216
217
|
rewriteClientHookError(rawError);
|
|
217
|
-
const errorObject = options.sanitizeErrorForClient(rawError);
|
|
218
|
+
const errorObject = options.errorOrigin === "ssr" ? rawError : options.sanitizeErrorForClient(rawError);
|
|
218
219
|
const matchedParams = options.matchedParams ?? options.route?.params ?? {};
|
|
219
220
|
const layoutModules = options.route?.layouts ?? options.rootLayouts;
|
|
220
221
|
const pathname = new URL(options.requestUrl).pathname;
|
|
@@ -224,6 +225,7 @@ async function renderAppPageErrorBoundary(options) {
|
|
|
224
225
|
})];
|
|
225
226
|
if (!errorBoundary.isGlobalError) try {
|
|
226
227
|
const { metadata, viewport } = await resolveAppPageHead({
|
|
228
|
+
applyFileBasedMetadata: options.applyFileBasedMetadata,
|
|
227
229
|
basePath: options.basePath ?? "",
|
|
228
230
|
fallbackOnFileMetadataError: true,
|
|
229
231
|
layoutModules,
|
|
@@ -247,7 +249,16 @@ async function renderAppPageErrorBoundary(options) {
|
|
|
247
249
|
console.error(`[vinext] App page error boundary head resolution failed for ${options.route?.pattern ?? pathname}:`, error);
|
|
248
250
|
}
|
|
249
251
|
const buildElement = (BoundaryComponent) => {
|
|
250
|
-
const
|
|
252
|
+
const serializedError = {
|
|
253
|
+
digest: "digest" in errorObject ? String(errorObject.digest) : void 0,
|
|
254
|
+
message: errorObject.message,
|
|
255
|
+
name: errorObject.name,
|
|
256
|
+
stack: process.env.NODE_ENV !== "production" ? errorObject.stack : void 0
|
|
257
|
+
};
|
|
258
|
+
const boundaryElement = errorBoundary.isGlobalError && BoundaryComponent !== DEFAULT_GLOBAL_ERROR_COMPONENT ? createElement(SerializedErrorBoundary, {
|
|
259
|
+
error: serializedError,
|
|
260
|
+
fallback: BoundaryComponent
|
|
261
|
+
}) : createElement(BoundaryComponent, { error: errorObject });
|
|
251
262
|
return wrapRenderedBoundaryElement({
|
|
252
263
|
element: createElement(Fragment, null, ...headElements, errorBoundary.isGlobalError ? createElement(GlobalErrorBoundary, {
|
|
253
264
|
fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
|
|
@@ -30,6 +30,7 @@ type FinalizeAppPageHtmlCacheResponseOptions = {
|
|
|
30
30
|
isrRscKey: AppPageRscCacheKeyBuilder;
|
|
31
31
|
isrSet: AppPageCacheSetter;
|
|
32
32
|
interceptionContext?: string | null;
|
|
33
|
+
omitPendingDynamicCacheState?: boolean;
|
|
33
34
|
preserveClientResponseHeaders?: boolean;
|
|
34
35
|
expireSeconds?: number;
|
|
35
36
|
revalidateSeconds: number | null;
|