vinext 0.0.46 → 0.0.48
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 +8 -6
- package/dist/build/layout-classification.js +3 -1
- package/dist/build/layout-classification.js.map +1 -1
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +80 -24
- package/dist/build/prerender.js.map +1 -1
- package/dist/build/report.d.ts +9 -5
- package/dist/build/report.js +17 -7
- package/dist/build/report.js.map +1 -1
- package/dist/build/route-classification-injector.d.ts +35 -0
- package/dist/build/route-classification-injector.js +61 -0
- package/dist/build/route-classification-injector.js.map +1 -0
- package/dist/build/route-classification-manifest.d.ts +1 -1
- package/dist/build/run-prerender.d.ts +5 -0
- package/dist/build/run-prerender.js +4 -1
- package/dist/build/run-prerender.js.map +1 -1
- package/dist/build/server-manifest.js +2 -7
- package/dist/build/server-manifest.js.map +1 -1
- package/dist/build/standalone.js +3 -5
- package/dist/build/standalone.js.map +1 -1
- package/dist/build/static-export.d.ts +1 -1
- package/dist/check.js +45 -29
- package/dist/check.js.map +1 -1
- package/dist/cli-args.d.ts +33 -0
- package/dist/cli-args.js +121 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli.js +11 -20
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare/kv-cache-handler.js +29 -9
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/config/config-matchers.js +46 -37
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/next-config.d.ts +4 -2
- package/dist/config/next-config.js +3 -0
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.d.ts +18 -2
- package/dist/deploy.js +47 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +4 -3
- package/dist/entries/app-rsc-entry.js +379 -858
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.d.ts +1 -1
- package/dist/entries/app-rsc-manifest.js +6 -1
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/pages-client-entry.js +3 -2
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +19 -61
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +12 -3
- package/dist/entries/runtime-entry-module.js +15 -4
- package/dist/entries/runtime-entry-module.js.map +1 -1
- package/dist/index.js +40 -58
- package/dist/index.js.map +1 -1
- package/dist/plugins/fonts.js +54 -32
- package/dist/plugins/fonts.js.map +1 -1
- package/dist/plugins/og-assets.js +15 -16
- package/dist/plugins/og-assets.js.map +1 -1
- package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
- package/dist/plugins/rsc-client-shim-excludes.js +11 -1
- package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
- package/dist/routing/app-route-graph.d.ts +195 -0
- package/dist/routing/app-route-graph.js +1022 -0
- package/dist/routing/app-route-graph.js.map +1 -0
- package/dist/routing/app-router.d.ts +14 -88
- package/dist/routing/app-router.js +21 -712
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts +3 -1
- package/dist/routing/file-matcher.js +6 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.js +10 -19
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/route-matching.d.ts +28 -0
- package/dist/routing/route-matching.js +44 -0
- package/dist/routing/route-matching.js.map +1 -0
- package/dist/routing/route-pattern.js +4 -1
- package/dist/routing/route-pattern.js.map +1 -1
- package/dist/routing/route-trie.d.ts +8 -0
- package/dist/routing/route-trie.js +12 -1
- package/dist/routing/route-trie.js.map +1 -1
- package/dist/routing/route-validation.js +3 -4
- package/dist/routing/route-validation.js.map +1 -1
- package/dist/routing/utils.d.ts +8 -1
- package/dist/routing/utils.js +25 -2
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/app-browser-entry.js +145 -294
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-error.d.ts +3 -4
- package/dist/server/app-browser-error.js +8 -4
- package/dist/server/app-browser-error.js.map +1 -1
- package/dist/server/app-browser-navigation-controller.d.ts +75 -0
- package/dist/server/app-browser-navigation-controller.js +290 -0
- package/dist/server/app-browser-navigation-controller.js.map +1 -0
- package/dist/server/app-browser-state.d.ts +33 -15
- package/dist/server/app-browser-state.js +52 -59
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +68 -0
- package/dist/server/app-browser-visible-commit.js +182 -0
- package/dist/server/app-browser-visible-commit.js.map +1 -0
- package/dist/server/app-client-reference-preloader.d.ts +15 -0
- package/dist/server/app-client-reference-preloader.js +46 -0
- package/dist/server/app-client-reference-preloader.js.map +1 -0
- package/dist/server/app-elements-wire.d.ts +130 -0
- package/dist/server/app-elements-wire.js +205 -0
- package/dist/server/app-elements-wire.js.map +1 -0
- package/dist/server/app-elements.d.ts +2 -84
- package/dist/server/app-elements.js +4 -107
- package/dist/server/app-elements.js.map +1 -1
- package/dist/server/app-fallback-renderer.d.ts +57 -0
- package/dist/server/app-fallback-renderer.js +79 -0
- package/dist/server/app-fallback-renderer.js.map +1 -0
- package/dist/server/app-hook-warning-suppression.d.ts +7 -0
- package/dist/server/app-hook-warning-suppression.js +12 -0
- package/dist/server/app-hook-warning-suppression.js.map +1 -0
- package/dist/server/app-middleware.d.ts +2 -1
- package/dist/server/app-middleware.js +34 -11
- package/dist/server/app-middleware.js.map +1 -1
- package/dist/server/app-mounted-slots-header.d.ts +17 -0
- package/dist/server/app-mounted-slots-header.js +21 -0
- package/dist/server/app-mounted-slots-header.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +3 -3
- package/dist/server/app-page-boundary-render.js +8 -5
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-boundary.js.map +1 -1
- package/dist/server/app-page-cache.d.ts +19 -4
- package/dist/server/app-page-cache.js +60 -22
- package/dist/server/app-page-cache.js.map +1 -1
- package/dist/server/app-page-dispatch.d.ts +9 -5
- package/dist/server/app-page-dispatch.js +41 -17
- package/dist/server/app-page-dispatch.js.map +1 -1
- package/dist/server/app-page-element-builder.d.ts +61 -0
- package/dist/server/app-page-element-builder.js +142 -0
- package/dist/server/app-page-element-builder.js.map +1 -0
- package/dist/server/app-page-execution.d.ts +23 -5
- package/dist/server/app-page-execution.js +39 -24
- package/dist/server/app-page-execution.js.map +1 -1
- package/dist/server/app-page-head.js +2 -1
- package/dist/server/app-page-head.js.map +1 -1
- package/dist/server/app-page-method.js +2 -5
- package/dist/server/app-page-method.js.map +1 -1
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +3 -3
- package/dist/server/app-page-params.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +1 -1
- package/dist/server/app-page-probe.js +5 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-page-render.d.ts +6 -2
- package/dist/server/app-page-render.js +118 -30
- package/dist/server/app-page-render.js.map +1 -1
- package/dist/server/app-page-request.d.ts +19 -5
- package/dist/server/app-page-request.js +49 -7
- package/dist/server/app-page-request.js.map +1 -1
- package/dist/server/app-page-response.d.ts +1 -0
- package/dist/server/app-page-response.js +6 -9
- package/dist/server/app-page-response.js.map +1 -1
- package/dist/server/app-page-route-wiring.d.ts +20 -4
- package/dist/server/app-page-route-wiring.js +15 -12
- package/dist/server/app-page-route-wiring.js.map +1 -1
- package/dist/server/app-page-stream.d.ts +7 -0
- package/dist/server/app-page-stream.js +9 -2
- package/dist/server/app-page-stream.js.map +1 -1
- package/dist/server/app-post-middleware-context.d.ts +16 -0
- package/dist/server/app-post-middleware-context.js +28 -0
- package/dist/server/app-post-middleware-context.js.map +1 -0
- package/dist/server/app-prerender-endpoints.js +3 -2
- package/dist/server/app-prerender-endpoints.js.map +1 -1
- package/dist/server/app-request-context.d.ts +22 -0
- package/dist/server/app-request-context.js +30 -0
- package/dist/server/app-request-context.js.map +1 -0
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +7 -2
- package/dist/server/app-route-handler-cache.js.map +1 -1
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +8 -5
- package/dist/server/app-route-handler-dispatch.js.map +1 -1
- package/dist/server/app-route-handler-execution.d.ts +2 -1
- package/dist/server/app-route-handler-execution.js +2 -2
- package/dist/server/app-route-handler-execution.js.map +1 -1
- package/dist/server/app-route-handler-policy.js +13 -13
- package/dist/server/app-route-handler-policy.js.map +1 -1
- package/dist/server/app-route-handler-response.d.ts +4 -2
- package/dist/server/app-route-handler-response.js +9 -7
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +9 -1
- package/dist/server/app-route-handler-runtime.js +11 -1
- package/dist/server/app-route-handler-runtime.js.map +1 -1
- package/dist/server/app-router-entry.js +9 -4
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +34 -0
- package/dist/server/app-rsc-cache-busting.js +137 -0
- package/dist/server/app-rsc-cache-busting.js.map +1 -0
- package/dist/server/app-rsc-error-handler.d.ts +21 -0
- package/dist/server/app-rsc-error-handler.js +30 -0
- package/dist/server/app-rsc-error-handler.js.map +1 -0
- package/dist/server/app-rsc-handler.d.ts +117 -0
- package/dist/server/app-rsc-handler.js +271 -0
- package/dist/server/app-rsc-handler.js.map +1 -0
- package/dist/server/app-rsc-request-normalization.d.ts +42 -0
- package/dist/server/app-rsc-request-normalization.js +67 -0
- package/dist/server/app-rsc-request-normalization.js.map +1 -0
- package/dist/server/app-rsc-response-finalizer.d.ts +30 -0
- package/dist/server/app-rsc-response-finalizer.js +38 -0
- package/dist/server/app-rsc-response-finalizer.js.map +1 -0
- package/dist/server/app-rsc-route-matching.js +8 -4
- package/dist/server/app-rsc-route-matching.js.map +1 -1
- package/dist/server/app-segment-config.d.ts +33 -0
- package/dist/server/app-segment-config.js +90 -0
- package/dist/server/app-segment-config.js.map +1 -0
- package/dist/server/app-server-action-execution.d.ts +2 -0
- package/dist/server/app-server-action-execution.js +45 -51
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/app-ssr-entry.js +21 -20
- package/dist/server/app-ssr-entry.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +44 -0
- package/dist/server/artifact-compatibility.js +82 -0
- package/dist/server/artifact-compatibility.js.map +1 -0
- package/dist/server/cache-control.d.ts +24 -0
- package/dist/server/cache-control.js +33 -0
- package/dist/server/cache-control.js.map +1 -0
- package/dist/server/cache-proof.d.ts +200 -0
- package/dist/server/cache-proof.js +342 -0
- package/dist/server/cache-proof.js.map +1 -0
- package/dist/server/dev-error-overlay-store.d.ts +23 -0
- package/dist/server/dev-error-overlay-store.js +67 -0
- package/dist/server/dev-error-overlay-store.js.map +1 -0
- package/dist/server/dev-error-overlay.d.ts +15 -0
- package/dist/server/dev-error-overlay.js +548 -0
- package/dist/server/dev-error-overlay.js.map +1 -0
- package/dist/server/dev-origin-check.js +8 -4
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-server.js +1 -6
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/http-error-responses.d.ts +67 -0
- package/dist/server/http-error-responses.js +77 -0
- package/dist/server/http-error-responses.js.map +1 -0
- package/dist/server/image-optimization.js +2 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/instrumentation-runtime.d.ts +44 -0
- package/dist/server/instrumentation-runtime.js +29 -0
- package/dist/server/instrumentation-runtime.js.map +1 -0
- package/dist/server/isr-cache.d.ts +2 -7
- package/dist/server/isr-cache.js +7 -10
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-route-response.js +6 -5
- package/dist/server/metadata-route-response.js.map +1 -1
- package/dist/server/metadata-routes.d.ts +1 -0
- package/dist/server/metadata-routes.js +6 -0
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-matcher.js +2 -2
- package/dist/server/middleware-matcher.js.map +1 -1
- package/dist/server/middleware-response-headers.js +21 -0
- package/dist/server/middleware-response-headers.js.map +1 -1
- package/dist/server/middleware-runtime.js +3 -3
- package/dist/server/middleware-runtime.js.map +1 -1
- package/dist/server/navigation-trace.d.ts +33 -0
- package/dist/server/navigation-trace.js +35 -0
- package/dist/server/navigation-trace.js.map +1 -0
- package/dist/server/next-error-digest.d.ts +44 -0
- package/dist/server/next-error-digest.js +40 -0
- package/dist/server/next-error-digest.js.map +1 -0
- package/dist/server/pages-api-route.js +2 -1
- package/dist/server/pages-api-route.js.map +1 -1
- package/dist/server/pages-node-compat.js +4 -16
- package/dist/server/pages-node-compat.js.map +1 -1
- package/dist/server/pages-page-data.d.ts +2 -1
- package/dist/server/pages-page-data.js +6 -5
- package/dist/server/pages-page-data.js.map +1 -1
- package/dist/server/pages-page-response.d.ts +3 -8
- package/dist/server/pages-page-response.js +46 -15
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.d.ts +6 -0
- package/dist/server/prod-server.js +28 -21
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +42 -1
- package/dist/server/request-pipeline.js +97 -17
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/server/rsc-stream-hints.d.ts +3 -1
- package/dist/server/rsc-stream-hints.js +4 -1
- package/dist/server/rsc-stream-hints.js.map +1 -1
- package/dist/server/seed-cache.js +19 -8
- package/dist/server/seed-cache.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts +2 -2
- package/dist/shims/cache-runtime.js +31 -17
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts +15 -3
- package/dist/shims/cache.js +45 -20
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +17 -1
- package/dist/shims/error-boundary.js +31 -1
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +4 -1
- package/dist/shims/fetch-cache.js +57 -16
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/head-state.js +2 -3
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/headers.js +4 -44
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/i18n-state.js +2 -3
- package/dist/shims/i18n-state.js.map +1 -1
- package/dist/shims/image.js +93 -5
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/internal/als-registry.d.ts +15 -0
- package/dist/shims/internal/als-registry.js +55 -0
- package/dist/shims/internal/als-registry.js.map +1 -0
- package/dist/shims/internal/cookie-serialize.d.ts +46 -0
- package/dist/shims/internal/cookie-serialize.js +51 -0
- package/dist/shims/internal/cookie-serialize.js.map +1 -0
- package/dist/shims/link.js +31 -26
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +26 -1
- package/dist/shims/metadata.js +94 -4
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.js +2 -3
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts +2 -7
- package/dist/shims/navigation.js +44 -36
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/request-context.js +2 -4
- package/dist/shims/request-context.js.map +1 -1
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router-state.js +2 -3
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.js +2 -2
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/server.js +5 -30
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/slot.js +5 -4
- package/dist/shims/slot.js.map +1 -1
- package/dist/shims/thenable-params.d.ts +5 -2
- package/dist/shims/thenable-params.js +26 -6
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +3 -14
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/shims/use-merged-ref.d.ts +7 -0
- package/dist/shims/use-merged-ref.js +40 -0
- package/dist/shims/use-merged-ref.js.map +1 -0
- package/dist/utils/base-path.d.ts +7 -1
- package/dist/utils/base-path.js +12 -1
- package/dist/utils/base-path.js.map +1 -1
- package/dist/utils/cache-control-metadata.d.ts +6 -0
- package/dist/utils/cache-control-metadata.js +16 -0
- package/dist/utils/cache-control-metadata.js.map +1 -0
- package/dist/utils/safe-json-file.d.ts +18 -0
- package/dist/utils/safe-json-file.js +25 -0
- package/dist/utils/safe-json-file.js.map +1 -0
- package/dist/utils/text-stream.d.ts +29 -0
- package/dist/utils/text-stream.js +66 -0
- package/dist/utils/text-stream.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { createArtifactCompatibilityEnvelope, parseArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
2
|
+
import { isValidElement } from "react";
|
|
3
|
+
//#region src/server/app-elements-wire.ts
|
|
4
|
+
const APP_INTERCEPTION_SEPARATOR = "\0";
|
|
5
|
+
const APP_ARTIFACT_COMPATIBILITY_KEY = "__artifactCompatibility";
|
|
6
|
+
const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
7
|
+
const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
|
|
8
|
+
const APP_ROUTE_KEY = "__route";
|
|
9
|
+
const APP_ROOT_LAYOUT_KEY = "__rootLayout";
|
|
10
|
+
const APP_UNMATCHED_SLOT_WIRE_VALUE = "__VINEXT_UNMATCHED_SLOT__";
|
|
11
|
+
const UNMATCHED_SLOT = Symbol.for("vinext.unmatchedSlot");
|
|
12
|
+
function appendInterceptionContext(identity, interceptionContext) {
|
|
13
|
+
return interceptionContext === null ? identity : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;
|
|
14
|
+
}
|
|
15
|
+
function createAppPayloadRouteId(routePath, interceptionContext) {
|
|
16
|
+
return appendInterceptionContext(`route:${routePath}`, interceptionContext);
|
|
17
|
+
}
|
|
18
|
+
function createAppPayloadPageId(routePath, interceptionContext) {
|
|
19
|
+
return appendInterceptionContext(`page:${routePath}`, interceptionContext);
|
|
20
|
+
}
|
|
21
|
+
function createAppPayloadLayoutId(treePath) {
|
|
22
|
+
return `layout:${treePath}`;
|
|
23
|
+
}
|
|
24
|
+
function createAppPayloadTemplateId(treePath) {
|
|
25
|
+
return `template:${treePath}`;
|
|
26
|
+
}
|
|
27
|
+
function createAppPayloadSlotId(slotName, treePath) {
|
|
28
|
+
return `slot:${slotName}:${treePath}`;
|
|
29
|
+
}
|
|
30
|
+
function createAppPayloadCacheKey(rscUrl, interceptionContext) {
|
|
31
|
+
return appendInterceptionContext(rscUrl, interceptionContext);
|
|
32
|
+
}
|
|
33
|
+
function parsePathWithInterception(input) {
|
|
34
|
+
const separatorIndex = input.indexOf(APP_INTERCEPTION_SEPARATOR);
|
|
35
|
+
const path = separatorIndex === -1 ? input : input.slice(0, separatorIndex);
|
|
36
|
+
if (!path.startsWith("/")) return null;
|
|
37
|
+
return {
|
|
38
|
+
interceptionContext: separatorIndex === -1 ? null : input.slice(separatorIndex + 1),
|
|
39
|
+
path
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* AppElements tree paths are absolute route-tree paths on the wire.
|
|
44
|
+
* Bare segment names are not valid layout/template/slot tree identities.
|
|
45
|
+
*/
|
|
46
|
+
function parseTreePath(input) {
|
|
47
|
+
return input.startsWith("/") ? input : null;
|
|
48
|
+
}
|
|
49
|
+
function parseAppElementsWireElementKey(key) {
|
|
50
|
+
if (key.startsWith("route:")) {
|
|
51
|
+
const parsed = parsePathWithInterception(key.slice(6));
|
|
52
|
+
if (!parsed) return null;
|
|
53
|
+
return {
|
|
54
|
+
interceptionContext: parsed.interceptionContext,
|
|
55
|
+
kind: "route",
|
|
56
|
+
path: parsed.path
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (key.startsWith("page:")) {
|
|
60
|
+
const parsed = parsePathWithInterception(key.slice(5));
|
|
61
|
+
if (!parsed) return null;
|
|
62
|
+
return {
|
|
63
|
+
interceptionContext: parsed.interceptionContext,
|
|
64
|
+
kind: "page",
|
|
65
|
+
path: parsed.path
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (key.startsWith("layout:")) {
|
|
69
|
+
const treePath = parseTreePath(key.slice(7));
|
|
70
|
+
return treePath ? {
|
|
71
|
+
kind: "layout",
|
|
72
|
+
treePath
|
|
73
|
+
} : null;
|
|
74
|
+
}
|
|
75
|
+
if (key.startsWith("template:")) {
|
|
76
|
+
const treePath = parseTreePath(key.slice(9));
|
|
77
|
+
return treePath ? {
|
|
78
|
+
kind: "template",
|
|
79
|
+
treePath
|
|
80
|
+
} : null;
|
|
81
|
+
}
|
|
82
|
+
if (key.startsWith("slot:")) {
|
|
83
|
+
const body = key.slice(5);
|
|
84
|
+
const separatorIndex = body.indexOf(":");
|
|
85
|
+
if (separatorIndex <= 0) return null;
|
|
86
|
+
const name = body.slice(0, separatorIndex);
|
|
87
|
+
const treePath = parseTreePath(body.slice(separatorIndex + 1));
|
|
88
|
+
return treePath ? {
|
|
89
|
+
kind: "slot",
|
|
90
|
+
name,
|
|
91
|
+
treePath
|
|
92
|
+
} : null;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
function isAppElementsWireSlotId(key) {
|
|
97
|
+
if (!key.startsWith("slot:")) return false;
|
|
98
|
+
const body = key.slice(5);
|
|
99
|
+
const separatorIndex = body.indexOf(":");
|
|
100
|
+
return separatorIndex > 0 && body.charCodeAt(separatorIndex + 1) === 47;
|
|
101
|
+
}
|
|
102
|
+
function createAppElementsWireMetadataEntries(input) {
|
|
103
|
+
return {
|
|
104
|
+
[APP_ROUTE_KEY]: input.routeId,
|
|
105
|
+
[APP_INTERCEPTION_CONTEXT_KEY]: input.interceptionContext,
|
|
106
|
+
[APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function normalizeAppElements(elements) {
|
|
110
|
+
let needsNormalization = false;
|
|
111
|
+
for (const [key, value] of Object.entries(elements)) if (isAppElementsWireSlotId(key) && value === "__VINEXT_UNMATCHED_SLOT__") {
|
|
112
|
+
needsNormalization = true;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
if (!needsNormalization) return elements;
|
|
116
|
+
const normalized = {};
|
|
117
|
+
for (const [key, value] of Object.entries(elements)) normalized[key] = isAppElementsWireSlotId(key) && value === "__VINEXT_UNMATCHED_SLOT__" ? UNMATCHED_SLOT : value;
|
|
118
|
+
return normalized;
|
|
119
|
+
}
|
|
120
|
+
function isLayoutFlagsRecord(value) {
|
|
121
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
122
|
+
for (const v of Object.values(value)) if (v !== "s" && v !== "d") return false;
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
function parseLayoutFlags(value) {
|
|
126
|
+
if (isLayoutFlagsRecord(value)) return value;
|
|
127
|
+
return {};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Type predicate for a plain (non-null, non-array) record of app payload values.
|
|
131
|
+
* Used to distinguish the App Router payload object from bare React elements at
|
|
132
|
+
* the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
|
|
133
|
+
* the outgoing payload carries heterogeneous values (ReactNodes for the rendered
|
|
134
|
+
* tree, plus metadata like `__layoutFlags` which is a plain object). Delegates
|
|
135
|
+
* to React's canonical `isValidElement` so we don't depend on React's internal
|
|
136
|
+
* `$$typeof` marker scheme.
|
|
137
|
+
*/
|
|
138
|
+
function isAppElementsRecord(value) {
|
|
139
|
+
if (typeof value !== "object" || value === null) return false;
|
|
140
|
+
if (Array.isArray(value)) return false;
|
|
141
|
+
if (isValidElement(value)) return false;
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
function withLayoutFlags(elements, layoutFlags) {
|
|
145
|
+
return {
|
|
146
|
+
...elements,
|
|
147
|
+
[APP_LAYOUT_FLAGS_KEY]: layoutFlags
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function buildOutgoingAppPayload(input) {
|
|
151
|
+
if (!isAppElementsRecord(input.element)) return input.element;
|
|
152
|
+
return {
|
|
153
|
+
...input.element,
|
|
154
|
+
[APP_LAYOUT_FLAGS_KEY]: input.layoutFlags,
|
|
155
|
+
[APP_ARTIFACT_COMPATIBILITY_KEY]: input.artifactCompatibility ?? createArtifactCompatibilityEnvelope()
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function readArtifactCompatibilityMetadata(value) {
|
|
159
|
+
if (value === void 0) return createArtifactCompatibilityEnvelope();
|
|
160
|
+
return parseArtifactCompatibilityEnvelope(value) ?? createArtifactCompatibilityEnvelope();
|
|
161
|
+
}
|
|
162
|
+
function readAppElementsMetadata(elements) {
|
|
163
|
+
const routeId = elements[APP_ROUTE_KEY];
|
|
164
|
+
if (typeof routeId !== "string") throw new Error("[vinext] Missing __route string in App Router payload");
|
|
165
|
+
const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];
|
|
166
|
+
if (interceptionContext !== void 0 && interceptionContext !== null && typeof interceptionContext !== "string") throw new Error("[vinext] Invalid __interceptionContext in App Router payload");
|
|
167
|
+
const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];
|
|
168
|
+
if (rootLayoutTreePath === void 0) throw new Error("[vinext] Missing __rootLayout key in App Router payload");
|
|
169
|
+
if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== "string") throw new Error("[vinext] Invalid __rootLayout in App Router payload: expected string or null");
|
|
170
|
+
const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);
|
|
171
|
+
return {
|
|
172
|
+
artifactCompatibility: readArtifactCompatibilityMetadata(elements[APP_ARTIFACT_COMPATIBILITY_KEY]),
|
|
173
|
+
interceptionContext: interceptionContext ?? null,
|
|
174
|
+
layoutFlags,
|
|
175
|
+
routeId,
|
|
176
|
+
rootLayoutTreePath
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const AppElementsWire = {
|
|
180
|
+
keys: {
|
|
181
|
+
artifactCompatibility: APP_ARTIFACT_COMPATIBILITY_KEY,
|
|
182
|
+
interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,
|
|
183
|
+
layoutFlags: APP_LAYOUT_FLAGS_KEY,
|
|
184
|
+
rootLayout: APP_ROOT_LAYOUT_KEY,
|
|
185
|
+
route: APP_ROUTE_KEY
|
|
186
|
+
},
|
|
187
|
+
unmatchedSlotValue: APP_UNMATCHED_SLOT_WIRE_VALUE,
|
|
188
|
+
createMetadataEntries: createAppElementsWireMetadataEntries,
|
|
189
|
+
decode: normalizeAppElements,
|
|
190
|
+
encodeCacheKey: createAppPayloadCacheKey,
|
|
191
|
+
encodeLayoutId: createAppPayloadLayoutId,
|
|
192
|
+
encodeOutgoingPayload: buildOutgoingAppPayload,
|
|
193
|
+
encodePageId: createAppPayloadPageId,
|
|
194
|
+
encodeRouteId: createAppPayloadRouteId,
|
|
195
|
+
encodeSlotId: createAppPayloadSlotId,
|
|
196
|
+
encodeTemplateId: createAppPayloadTemplateId,
|
|
197
|
+
isSlotId: isAppElementsWireSlotId,
|
|
198
|
+
parseElementKey: parseAppElementsWireElementKey,
|
|
199
|
+
readMetadata: readAppElementsMetadata,
|
|
200
|
+
withLayoutFlags
|
|
201
|
+
};
|
|
202
|
+
//#endregion
|
|
203
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, isAppElementsRecord, normalizeAppElements, readAppElementsMetadata, withLayoutFlags };
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=app-elements-wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-elements-wire.js","names":[],"sources":["../../src/server/app-elements-wire.ts"],"sourcesContent":["import { isValidElement, type ReactNode } from \"react\";\nimport {\n createArtifactCompatibilityEnvelope,\n parseArtifactCompatibilityEnvelope,\n type ArtifactCompatibilityEnvelope,\n} from \"./artifact-compatibility.js\";\n\nconst APP_INTERCEPTION_SEPARATOR = \"\\0\";\n\nexport const APP_ARTIFACT_COMPATIBILITY_KEY = \"__artifactCompatibility\";\nexport const APP_INTERCEPTION_CONTEXT_KEY = \"__interceptionContext\";\nexport const APP_LAYOUT_FLAGS_KEY = \"__layoutFlags\";\nexport const APP_ROUTE_KEY = \"__route\";\nexport const APP_ROOT_LAYOUT_KEY = \"__rootLayout\";\nexport const APP_UNMATCHED_SLOT_WIRE_VALUE = \"__VINEXT_UNMATCHED_SLOT__\";\n\nexport const UNMATCHED_SLOT = Symbol.for(\"vinext.unmatchedSlot\");\n\nexport type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null;\ntype AppWireElementValue = ReactNode | string | null;\n\nexport type AppElements = Readonly<Record<string, AppElementValue>>;\nexport type AppWireElements = Readonly<Record<string, AppWireElementValue>>;\n\n/**\n * Per-layout static/dynamic flags. `\"s\"` = static (skippable on next nav);\n * `\"d\"` = dynamic (must always render).\n *\n * Lifecycle (partial — later PRs extend this):\n *\n * 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns\n * LayoutFlags for every layout in the route at render time.\n *\n * 2. ATTACH — AppElementsWire.encodeOutgoingPayload writes `__layoutFlags`\n * into the outgoing App Router payload record.\n *\n * 3. WIRE — renderToReadableStream serializes the record as RSC row 0.\n *\n * 4. PARSE — AppElementsWire.readMetadata extracts layoutFlags from the\n * wire payload on the client side.\n */\nexport type LayoutFlags = Readonly<Record<string, \"s\" | \"d\">>;\n\ntype AppElementsMetadata = {\n artifactCompatibility: ArtifactCompatibilityEnvelope;\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n routeId: string;\n rootLayoutTreePath: string | null;\n};\n\ntype AppElementsWireElementKey =\n | { kind: \"layout\"; treePath: string }\n | { interceptionContext: string | null; kind: \"page\"; path: string }\n | { interceptionContext: string | null; kind: \"route\"; path: string }\n | { kind: \"slot\"; name: string; treePath: string }\n | { kind: \"template\"; treePath: string };\n\ntype AppElementsWireMetadataInput = {\n interceptionContext: string | null;\n routeId: string;\n rootLayoutTreePath: string | null;\n};\n\ntype AppElementsWireMetadataEntries = Readonly<{\n [APP_ROUTE_KEY]: string;\n [APP_INTERCEPTION_CONTEXT_KEY]: string | null;\n [APP_ROOT_LAYOUT_KEY]: string | null;\n}>;\n\n/**\n * The outgoing wire payload shape. Includes ReactNode values for the\n * rendered tree plus metadata values like LayoutFlags attached under\n * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements\n * which only carry render-time values.\n */\nexport type AppOutgoingElements = Readonly<\n Record<string, ReactNode | LayoutFlags | ArtifactCompatibilityEnvelope>\n>;\n\ntype AppElementsWireKeys = {\n readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;\n readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;\n readonly layoutFlags: typeof APP_LAYOUT_FLAGS_KEY;\n readonly rootLayout: typeof APP_ROOT_LAYOUT_KEY;\n readonly route: typeof APP_ROUTE_KEY;\n};\n\ntype AppElementsWireCodec = {\n readonly keys: AppElementsWireKeys;\n readonly unmatchedSlotValue: typeof APP_UNMATCHED_SLOT_WIRE_VALUE;\n createMetadataEntries(input: AppElementsWireMetadataInput): AppElementsWireMetadataEntries;\n decode(elements: AppWireElements): AppElements;\n encodeCacheKey(rscUrl: string, interceptionContext: string | null): string;\n encodeLayoutId(treePath: string): string;\n encodeOutgoingPayload(input: {\n element: ReactNode | Readonly<Record<string, ReactNode>>;\n artifactCompatibility?: ArtifactCompatibilityEnvelope;\n layoutFlags: LayoutFlags;\n }): ReactNode | AppOutgoingElements;\n encodePageId(routePath: string, interceptionContext: string | null): string;\n encodeRouteId(routePath: string, interceptionContext: string | null): string;\n encodeSlotId(slotName: string, treePath: string): string;\n encodeTemplateId(treePath: string): string;\n isSlotId(key: string): boolean;\n parseElementKey(key: string): AppElementsWireElementKey | null;\n readMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;\n withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n ): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags };\n};\n\nfunction appendInterceptionContext(identity: string, interceptionContext: string | null): string {\n return interceptionContext === null\n ? identity\n : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;\n}\n\nfunction createAppPayloadRouteId(routePath: string, interceptionContext: string | null): string {\n return appendInterceptionContext(`route:${routePath}`, interceptionContext);\n}\n\nfunction createAppPayloadPageId(routePath: string, interceptionContext: string | null): string {\n return appendInterceptionContext(`page:${routePath}`, interceptionContext);\n}\n\nfunction createAppPayloadLayoutId(treePath: string): string {\n return `layout:${treePath}`;\n}\n\nfunction createAppPayloadTemplateId(treePath: string): string {\n return `template:${treePath}`;\n}\n\nfunction createAppPayloadSlotId(slotName: string, treePath: string): string {\n return `slot:${slotName}:${treePath}`;\n}\n\nfunction createAppPayloadCacheKey(rscUrl: string, interceptionContext: string | null): string {\n return appendInterceptionContext(rscUrl, interceptionContext);\n}\n\nfunction parsePathWithInterception(input: string): {\n interceptionContext: string | null;\n path: string;\n} | null {\n const separatorIndex = input.indexOf(APP_INTERCEPTION_SEPARATOR);\n const path = separatorIndex === -1 ? input : input.slice(0, separatorIndex);\n if (!path.startsWith(\"/\")) return null;\n\n return {\n interceptionContext: separatorIndex === -1 ? null : input.slice(separatorIndex + 1),\n path,\n };\n}\n\n/**\n * AppElements tree paths are absolute route-tree paths on the wire.\n * Bare segment names are not valid layout/template/slot tree identities.\n */\nfunction parseTreePath(input: string): string | null {\n return input.startsWith(\"/\") ? input : null;\n}\n\nfunction parseAppElementsWireElementKey(key: string): AppElementsWireElementKey | null {\n if (key.startsWith(\"route:\")) {\n const parsed = parsePathWithInterception(key.slice(\"route:\".length));\n if (!parsed) return null;\n return { interceptionContext: parsed.interceptionContext, kind: \"route\", path: parsed.path };\n }\n\n if (key.startsWith(\"page:\")) {\n const parsed = parsePathWithInterception(key.slice(\"page:\".length));\n if (!parsed) return null;\n return { interceptionContext: parsed.interceptionContext, kind: \"page\", path: parsed.path };\n }\n\n if (key.startsWith(\"layout:\")) {\n const treePath = parseTreePath(key.slice(\"layout:\".length));\n return treePath ? { kind: \"layout\", treePath } : null;\n }\n\n if (key.startsWith(\"template:\")) {\n const treePath = parseTreePath(key.slice(\"template:\".length));\n return treePath ? { kind: \"template\", treePath } : null;\n }\n\n if (key.startsWith(\"slot:\")) {\n const body = key.slice(\"slot:\".length);\n const separatorIndex = body.indexOf(\":\");\n if (separatorIndex <= 0) return null;\n const name = body.slice(0, separatorIndex);\n const treePath = parseTreePath(body.slice(separatorIndex + 1));\n return treePath ? { kind: \"slot\", name, treePath } : null;\n }\n\n return null;\n}\n\nfunction isAppElementsWireSlotId(key: string): boolean {\n if (!key.startsWith(\"slot:\")) return false;\n const body = key.slice(\"slot:\".length);\n const separatorIndex = body.indexOf(\":\");\n return separatorIndex > 0 && body.charCodeAt(separatorIndex + 1) === 0x2f;\n}\n\nfunction createAppElementsWireMetadataEntries(\n input: AppElementsWireMetadataInput,\n): AppElementsWireMetadataEntries {\n return {\n [APP_ROUTE_KEY]: input.routeId,\n [APP_INTERCEPTION_CONTEXT_KEY]: input.interceptionContext,\n [APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath,\n };\n}\n\nexport function normalizeAppElements(elements: AppWireElements): AppElements {\n let needsNormalization = false;\n for (const [key, value] of Object.entries(elements)) {\n if (isAppElementsWireSlotId(key) && value === APP_UNMATCHED_SLOT_WIRE_VALUE) {\n needsNormalization = true;\n break;\n }\n }\n\n if (!needsNormalization) {\n return elements;\n }\n\n const normalized: Record<string, AppElementValue> = {};\n for (const [key, value] of Object.entries(elements)) {\n normalized[key] =\n isAppElementsWireSlotId(key) && value === APP_UNMATCHED_SLOT_WIRE_VALUE\n ? UNMATCHED_SLOT\n : value;\n }\n\n return normalized;\n}\n\nfunction isLayoutFlagsRecord(value: unknown): value is LayoutFlags {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n for (const v of Object.values(value)) {\n if (v !== \"s\" && v !== \"d\") return false;\n }\n return true;\n}\n\nfunction parseLayoutFlags(value: unknown): LayoutFlags {\n if (isLayoutFlagsRecord(value)) return value;\n return {};\n}\n\n/**\n * Type predicate for a plain (non-null, non-array) record of app payload values.\n * Used to distinguish the App Router payload object from bare React elements at\n * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because\n * the outgoing payload carries heterogeneous values (ReactNodes for the rendered\n * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates\n * to React's canonical `isValidElement` so we don't depend on React's internal\n * `$$typeof` marker scheme.\n */\nexport function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null) return false;\n if (Array.isArray(value)) return false;\n if (isValidElement(value)) return false;\n return true;\n}\n\nexport function withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags } {\n return { ...elements, [APP_LAYOUT_FLAGS_KEY]: layoutFlags };\n}\n\nexport function buildOutgoingAppPayload(input: {\n element: ReactNode | Readonly<Record<string, ReactNode>>;\n artifactCompatibility?: ArtifactCompatibilityEnvelope;\n layoutFlags: LayoutFlags;\n}): ReactNode | AppOutgoingElements {\n if (!isAppElementsRecord(input.element)) {\n return input.element;\n }\n return {\n ...input.element,\n [APP_LAYOUT_FLAGS_KEY]: input.layoutFlags,\n [APP_ARTIFACT_COMPATIBILITY_KEY]:\n input.artifactCompatibility ?? createArtifactCompatibilityEnvelope(),\n };\n}\n\nfunction readArtifactCompatibilityMetadata(value: unknown): ArtifactCompatibilityEnvelope {\n if (value === undefined) return createArtifactCompatibilityEnvelope();\n\n const artifactCompatibility = parseArtifactCompatibilityEnvelope(value);\n // TODO(#726-COMPAT-04): hard-fail malformed compatibility metadata once\n // cache/skip consumers depend on this proof. During Wave01 the field is\n // emitted as scaffolding, so bad or future-version values degrade like\n // missing __layoutFlags instead of crashing render paths that do not read it.\n return artifactCompatibility ?? createArtifactCompatibilityEnvelope();\n}\n\nexport function readAppElementsMetadata(\n elements: Readonly<Record<string, unknown>>,\n): AppElementsMetadata {\n const routeId = elements[APP_ROUTE_KEY];\n if (typeof routeId !== \"string\") {\n throw new Error(\"[vinext] Missing __route string in App Router payload\");\n }\n\n const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];\n if (\n interceptionContext !== undefined &&\n interceptionContext !== null &&\n typeof interceptionContext !== \"string\"\n ) {\n throw new Error(\"[vinext] Invalid __interceptionContext in App Router payload\");\n }\n\n const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];\n if (rootLayoutTreePath === undefined) {\n throw new Error(\"[vinext] Missing __rootLayout key in App Router payload\");\n }\n if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== \"string\") {\n throw new Error(\"[vinext] Invalid __rootLayout in App Router payload: expected string or null\");\n }\n\n const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);\n const artifactCompatibility = readArtifactCompatibilityMetadata(\n elements[APP_ARTIFACT_COMPATIBILITY_KEY],\n );\n\n return {\n artifactCompatibility,\n interceptionContext: interceptionContext ?? null,\n layoutFlags,\n routeId,\n rootLayoutTreePath,\n };\n}\n\nexport const AppElementsWire: AppElementsWireCodec = {\n // WIRE follow-ups use these stable key names when moving payload readers and writers\n // behind the codec boundary.\n keys: {\n artifactCompatibility: APP_ARTIFACT_COMPATIBILITY_KEY,\n interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,\n layoutFlags: APP_LAYOUT_FLAGS_KEY,\n rootLayout: APP_ROOT_LAYOUT_KEY,\n route: APP_ROUTE_KEY,\n },\n unmatchedSlotValue: APP_UNMATCHED_SLOT_WIRE_VALUE,\n createMetadataEntries: createAppElementsWireMetadataEntries,\n decode: normalizeAppElements,\n encodeCacheKey: createAppPayloadCacheKey,\n encodeLayoutId: createAppPayloadLayoutId,\n encodeOutgoingPayload: buildOutgoingAppPayload,\n encodePageId: createAppPayloadPageId,\n encodeRouteId: createAppPayloadRouteId,\n encodeSlotId: createAppPayloadSlotId,\n encodeTemplateId: createAppPayloadTemplateId,\n isSlotId: isAppElementsWireSlotId,\n parseElementKey: parseAppElementsWireElementKey,\n readMetadata: readAppElementsMetadata,\n withLayoutFlags,\n};\n"],"mappings":"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"}
|
|
@@ -1,91 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, isAppElementsRecord, normalizeAppElements, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
2
2
|
|
|
3
3
|
//#region src/server/app-elements.d.ts
|
|
4
|
-
declare const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
5
|
-
declare const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
|
|
6
|
-
declare const APP_ROUTE_KEY = "__route";
|
|
7
|
-
declare const APP_ROOT_LAYOUT_KEY = "__rootLayout";
|
|
8
|
-
declare const APP_UNMATCHED_SLOT_WIRE_VALUE = "__VINEXT_UNMATCHED_SLOT__";
|
|
9
|
-
declare const UNMATCHED_SLOT: unique symbol;
|
|
10
|
-
type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null;
|
|
11
|
-
type AppWireElementValue = ReactNode | string | null;
|
|
12
|
-
type AppElements = Readonly<Record<string, AppElementValue>>;
|
|
13
|
-
type AppWireElements = Readonly<Record<string, AppWireElementValue>>;
|
|
14
|
-
/**
|
|
15
|
-
* Per-layout static/dynamic flags. `"s"` = static (skippable on next nav);
|
|
16
|
-
* `"d"` = dynamic (must always render).
|
|
17
|
-
*
|
|
18
|
-
* Lifecycle (partial — later PRs extend this):
|
|
19
|
-
*
|
|
20
|
-
* 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns
|
|
21
|
-
* LayoutFlags for every layout in the route at render time.
|
|
22
|
-
*
|
|
23
|
-
* 2. ATTACH — withLayoutFlags (this file) writes `__layoutFlags` into the
|
|
24
|
-
* outgoing App Router payload record.
|
|
25
|
-
*
|
|
26
|
-
* 3. WIRE — renderToReadableStream serializes the record as RSC row 0.
|
|
27
|
-
*
|
|
28
|
-
* 4. PARSE — readAppElementsMetadata (this file) extracts layoutFlags from
|
|
29
|
-
* the wire payload on the client side.
|
|
30
|
-
*/
|
|
31
|
-
type LayoutFlags = Readonly<Record<string, "s" | "d">>;
|
|
32
|
-
type AppElementsMetadata = {
|
|
33
|
-
interceptionContext: string | null;
|
|
34
|
-
layoutFlags: LayoutFlags;
|
|
35
|
-
routeId: string;
|
|
36
|
-
rootLayoutTreePath: string | null;
|
|
37
|
-
};
|
|
38
4
|
declare function getMountedSlotIds(elements: AppElements): string[];
|
|
39
5
|
declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
|
|
40
|
-
declare function createAppPayloadRouteId(routePath: string, interceptionContext: string | null): string;
|
|
41
|
-
declare function createAppPayloadPageId(routePath: string, interceptionContext: string | null): string;
|
|
42
|
-
declare function createAppPayloadCacheKey(rscUrl: string, interceptionContext: string | null): string;
|
|
43
6
|
declare function resolveVisitedResponseInterceptionContext(requestInterceptionContext: string | null, payloadInterceptionContext: string | null): string | null;
|
|
44
|
-
declare function normalizeAppElements(elements: AppWireElements): AppElements;
|
|
45
|
-
/**
|
|
46
|
-
* Type predicate for a plain (non-null, non-array) record of app payload values.
|
|
47
|
-
* Used to distinguish the App Router payload object from bare React elements at
|
|
48
|
-
* the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
|
|
49
|
-
* the outgoing payload carries heterogeneous values (ReactNodes for the rendered
|
|
50
|
-
* tree, plus metadata like `__layoutFlags` which is a plain object). Delegates
|
|
51
|
-
* to React's canonical `isValidElement` so we don't depend on React's internal
|
|
52
|
-
* `$$typeof` marker scheme.
|
|
53
|
-
*/
|
|
54
|
-
declare function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>>;
|
|
55
|
-
/**
|
|
56
|
-
* Pure: returns a new record with `__layoutFlags` attached. Owns the write
|
|
57
|
-
* boundary for the layout flags key so the write side sits next to
|
|
58
|
-
* `readAppElementsMetadata`.
|
|
59
|
-
*
|
|
60
|
-
* See `LayoutFlags` type docblock in this file for lifecycle.
|
|
61
|
-
*/
|
|
62
|
-
declare function withLayoutFlags<T extends Record<string, unknown>>(elements: T, layoutFlags: LayoutFlags): T & {
|
|
63
|
-
[APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* The outgoing wire payload shape. Includes ReactNode values for the
|
|
67
|
-
* rendered tree plus metadata values like LayoutFlags attached under
|
|
68
|
-
* known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements
|
|
69
|
-
* which only carry render-time values.
|
|
70
|
-
*/
|
|
71
|
-
type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags>>;
|
|
72
|
-
/**
|
|
73
|
-
* Pure: builds the outgoing payload for the wire. Non-record inputs (e.g. a
|
|
74
|
-
* bare React element) are returned unchanged. Record inputs get a fresh copy
|
|
75
|
-
* with `__layoutFlags` attached. Never mutates `input.element`.
|
|
76
|
-
*/
|
|
77
|
-
declare function buildOutgoingAppPayload(input: {
|
|
78
|
-
element: ReactNode | Readonly<Record<string, ReactNode>>;
|
|
79
|
-
layoutFlags: LayoutFlags;
|
|
80
|
-
}): ReactNode | AppOutgoingElements;
|
|
81
|
-
/**
|
|
82
|
-
* Parses metadata from the wire payload. Accepts `Record<string, unknown>`
|
|
83
|
-
* because the RSC payload carries heterogeneous values (React elements,
|
|
84
|
-
* strings, and plain objects like layout flags) under the same record type.
|
|
85
|
-
*
|
|
86
|
-
* See `LayoutFlags` type docblock in this file for lifecycle.
|
|
87
|
-
*/
|
|
88
|
-
declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
|
|
89
7
|
//#endregion
|
|
90
|
-
export { APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload,
|
|
8
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
91
9
|
//# sourceMappingURL=app-elements.d.ts.map
|
|
@@ -1,122 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
2
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, isAppElementsRecord, normalizeAppElements, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
2
3
|
//#region src/server/app-elements.ts
|
|
3
|
-
const APP_INTERCEPTION_SEPARATOR = "\0";
|
|
4
|
-
const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
5
|
-
const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
|
|
6
|
-
const APP_ROUTE_KEY = "__route";
|
|
7
|
-
const APP_ROOT_LAYOUT_KEY = "__rootLayout";
|
|
8
|
-
const APP_UNMATCHED_SLOT_WIRE_VALUE = "__VINEXT_UNMATCHED_SLOT__";
|
|
9
|
-
const UNMATCHED_SLOT = Symbol.for("vinext.unmatchedSlot");
|
|
10
|
-
function normalizeMountedSlotsHeader(header) {
|
|
11
|
-
if (!header) return null;
|
|
12
|
-
const slotIds = Array.from(new Set(header.split(/\s+/).filter(Boolean))).sort();
|
|
13
|
-
return slotIds.length > 0 ? slotIds.join(" ") : null;
|
|
14
|
-
}
|
|
15
4
|
function getMountedSlotIds(elements) {
|
|
16
5
|
return Object.keys(elements).filter((key) => {
|
|
17
6
|
const value = elements[key];
|
|
18
|
-
return
|
|
7
|
+
return AppElementsWire.isSlotId(key) && value !== null && value !== void 0 && value !== UNMATCHED_SLOT;
|
|
19
8
|
}).sort();
|
|
20
9
|
}
|
|
21
10
|
function getMountedSlotIdsHeader(elements) {
|
|
22
11
|
return normalizeMountedSlotsHeader(getMountedSlotIds(elements).join(" "));
|
|
23
12
|
}
|
|
24
|
-
function appendInterceptionContext(identity, interceptionContext) {
|
|
25
|
-
return interceptionContext === null ? identity : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;
|
|
26
|
-
}
|
|
27
|
-
function createAppPayloadRouteId(routePath, interceptionContext) {
|
|
28
|
-
return appendInterceptionContext(`route:${routePath}`, interceptionContext);
|
|
29
|
-
}
|
|
30
|
-
function createAppPayloadPageId(routePath, interceptionContext) {
|
|
31
|
-
return appendInterceptionContext(`page:${routePath}`, interceptionContext);
|
|
32
|
-
}
|
|
33
|
-
function createAppPayloadCacheKey(rscUrl, interceptionContext) {
|
|
34
|
-
return appendInterceptionContext(rscUrl, interceptionContext);
|
|
35
|
-
}
|
|
36
13
|
function resolveVisitedResponseInterceptionContext(requestInterceptionContext, payloadInterceptionContext) {
|
|
37
14
|
return payloadInterceptionContext ?? requestInterceptionContext;
|
|
38
15
|
}
|
|
39
|
-
function normalizeAppElements(elements) {
|
|
40
|
-
let needsNormalization = false;
|
|
41
|
-
for (const [key, value] of Object.entries(elements)) if (key.startsWith("slot:") && value === "__VINEXT_UNMATCHED_SLOT__") {
|
|
42
|
-
needsNormalization = true;
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
if (!needsNormalization) return elements;
|
|
46
|
-
const normalized = {};
|
|
47
|
-
for (const [key, value] of Object.entries(elements)) normalized[key] = key.startsWith("slot:") && value === "__VINEXT_UNMATCHED_SLOT__" ? UNMATCHED_SLOT : value;
|
|
48
|
-
return normalized;
|
|
49
|
-
}
|
|
50
|
-
function isLayoutFlagsRecord(value) {
|
|
51
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
52
|
-
for (const v of Object.values(value)) if (v !== "s" && v !== "d") return false;
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
function parseLayoutFlags(value) {
|
|
56
|
-
if (isLayoutFlagsRecord(value)) return value;
|
|
57
|
-
return {};
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Type predicate for a plain (non-null, non-array) record of app payload values.
|
|
61
|
-
* Used to distinguish the App Router payload object from bare React elements at
|
|
62
|
-
* the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
|
|
63
|
-
* the outgoing payload carries heterogeneous values (ReactNodes for the rendered
|
|
64
|
-
* tree, plus metadata like `__layoutFlags` which is a plain object). Delegates
|
|
65
|
-
* to React's canonical `isValidElement` so we don't depend on React's internal
|
|
66
|
-
* `$$typeof` marker scheme.
|
|
67
|
-
*/
|
|
68
|
-
function isAppElementsRecord(value) {
|
|
69
|
-
if (typeof value !== "object" || value === null) return false;
|
|
70
|
-
if (Array.isArray(value)) return false;
|
|
71
|
-
if (isValidElement(value)) return false;
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Pure: returns a new record with `__layoutFlags` attached. Owns the write
|
|
76
|
-
* boundary for the layout flags key so the write side sits next to
|
|
77
|
-
* `readAppElementsMetadata`.
|
|
78
|
-
*
|
|
79
|
-
* See `LayoutFlags` type docblock in this file for lifecycle.
|
|
80
|
-
*/
|
|
81
|
-
function withLayoutFlags(elements, layoutFlags) {
|
|
82
|
-
return {
|
|
83
|
-
...elements,
|
|
84
|
-
[APP_LAYOUT_FLAGS_KEY]: layoutFlags
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Pure: builds the outgoing payload for the wire. Non-record inputs (e.g. a
|
|
89
|
-
* bare React element) are returned unchanged. Record inputs get a fresh copy
|
|
90
|
-
* with `__layoutFlags` attached. Never mutates `input.element`.
|
|
91
|
-
*/
|
|
92
|
-
function buildOutgoingAppPayload(input) {
|
|
93
|
-
if (!isAppElementsRecord(input.element)) return input.element;
|
|
94
|
-
return withLayoutFlags(input.element, input.layoutFlags);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Parses metadata from the wire payload. Accepts `Record<string, unknown>`
|
|
98
|
-
* because the RSC payload carries heterogeneous values (React elements,
|
|
99
|
-
* strings, and plain objects like layout flags) under the same record type.
|
|
100
|
-
*
|
|
101
|
-
* See `LayoutFlags` type docblock in this file for lifecycle.
|
|
102
|
-
*/
|
|
103
|
-
function readAppElementsMetadata(elements) {
|
|
104
|
-
const routeId = elements[APP_ROUTE_KEY];
|
|
105
|
-
if (typeof routeId !== "string") throw new Error("[vinext] Missing __route string in App Router payload");
|
|
106
|
-
const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];
|
|
107
|
-
if (interceptionContext !== void 0 && interceptionContext !== null && typeof interceptionContext !== "string") throw new Error("[vinext] Invalid __interceptionContext in App Router payload");
|
|
108
|
-
const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];
|
|
109
|
-
if (rootLayoutTreePath === void 0) throw new Error("[vinext] Missing __rootLayout key in App Router payload");
|
|
110
|
-
if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== "string") throw new Error("[vinext] Invalid __rootLayout in App Router payload: expected string or null");
|
|
111
|
-
const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);
|
|
112
|
-
return {
|
|
113
|
-
interceptionContext: interceptionContext ?? null,
|
|
114
|
-
layoutFlags,
|
|
115
|
-
routeId,
|
|
116
|
-
rootLayoutTreePath
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
16
|
//#endregion
|
|
120
|
-
export { APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, UNMATCHED_SLOT, buildOutgoingAppPayload,
|
|
17
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_LAYOUT_FLAGS_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
121
18
|
|
|
122
19
|
//# sourceMappingURL=app-elements.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-elements.js","names":[],"sources":["../../src/server/app-elements.ts"],"sourcesContent":["import { isValidElement, type ReactNode } from \"react\";\n\nconst APP_INTERCEPTION_SEPARATOR = \"\\0\";\n\nexport const APP_INTERCEPTION_CONTEXT_KEY = \"__interceptionContext\";\nexport const APP_LAYOUT_FLAGS_KEY = \"__layoutFlags\";\nexport const APP_ROUTE_KEY = \"__route\";\nexport const APP_ROOT_LAYOUT_KEY = \"__rootLayout\";\nexport const APP_UNMATCHED_SLOT_WIRE_VALUE = \"__VINEXT_UNMATCHED_SLOT__\";\n\nexport const UNMATCHED_SLOT = Symbol.for(\"vinext.unmatchedSlot\");\n\nexport type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null;\ntype AppWireElementValue = ReactNode | string | null;\n\nexport type AppElements = Readonly<Record<string, AppElementValue>>;\nexport type AppWireElements = Readonly<Record<string, AppWireElementValue>>;\n\n/**\n * Per-layout static/dynamic flags. `\"s\"` = static (skippable on next nav);\n * `\"d\"` = dynamic (must always render).\n *\n * Lifecycle (partial — later PRs extend this):\n *\n * 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns\n * LayoutFlags for every layout in the route at render time.\n *\n * 2. ATTACH — withLayoutFlags (this file) writes `__layoutFlags` into the\n * outgoing App Router payload record.\n *\n * 3. WIRE — renderToReadableStream serializes the record as RSC row 0.\n *\n * 4. PARSE — readAppElementsMetadata (this file) extracts layoutFlags from\n * the wire payload on the client side.\n */\nexport type LayoutFlags = Readonly<Record<string, \"s\" | \"d\">>;\n\ntype AppElementsMetadata = {\n interceptionContext: string | null;\n layoutFlags: LayoutFlags;\n routeId: string;\n rootLayoutTreePath: string | null;\n};\n\nfunction normalizeMountedSlotsHeader(header: string | null | undefined): string | null {\n if (!header) {\n return null;\n }\n\n const slotIds = Array.from(new Set(header.split(/\\s+/).filter(Boolean))).sort();\n\n return slotIds.length > 0 ? slotIds.join(\" \") : null;\n}\n\nexport function getMountedSlotIds(elements: AppElements): string[] {\n return Object.keys(elements)\n .filter((key) => {\n const value = elements[key];\n return (\n key.startsWith(\"slot:\") && value !== null && value !== undefined && value !== UNMATCHED_SLOT\n );\n })\n .sort();\n}\n\nexport function getMountedSlotIdsHeader(elements: AppElements): string | null {\n return normalizeMountedSlotsHeader(getMountedSlotIds(elements).join(\" \"));\n}\n\nfunction appendInterceptionContext(identity: string, interceptionContext: string | null): string {\n return interceptionContext === null\n ? identity\n : `${identity}${APP_INTERCEPTION_SEPARATOR}${interceptionContext}`;\n}\n\nexport function createAppPayloadRouteId(\n routePath: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(`route:${routePath}`, interceptionContext);\n}\n\nexport function createAppPayloadPageId(\n routePath: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(`page:${routePath}`, interceptionContext);\n}\n\nexport function createAppPayloadCacheKey(\n rscUrl: string,\n interceptionContext: string | null,\n): string {\n return appendInterceptionContext(rscUrl, interceptionContext);\n}\n\nexport function resolveVisitedResponseInterceptionContext(\n requestInterceptionContext: string | null,\n payloadInterceptionContext: string | null,\n): string | null {\n return payloadInterceptionContext ?? requestInterceptionContext;\n}\n\nexport function normalizeAppElements(elements: AppWireElements): AppElements {\n let needsNormalization = false;\n for (const [key, value] of Object.entries(elements)) {\n if (key.startsWith(\"slot:\") && value === APP_UNMATCHED_SLOT_WIRE_VALUE) {\n needsNormalization = true;\n break;\n }\n }\n\n if (!needsNormalization) {\n return elements;\n }\n\n const normalized: Record<string, AppElementValue> = {};\n for (const [key, value] of Object.entries(elements)) {\n normalized[key] =\n key.startsWith(\"slot:\") && value === APP_UNMATCHED_SLOT_WIRE_VALUE ? UNMATCHED_SLOT : value;\n }\n\n return normalized;\n}\n\nfunction isLayoutFlagsRecord(value: unknown): value is LayoutFlags {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n for (const v of Object.values(value)) {\n if (v !== \"s\" && v !== \"d\") return false;\n }\n return true;\n}\n\nfunction parseLayoutFlags(value: unknown): LayoutFlags {\n if (isLayoutFlagsRecord(value)) return value;\n return {};\n}\n\n/**\n * Type predicate for a plain (non-null, non-array) record of app payload values.\n * Used to distinguish the App Router payload object from bare React elements at\n * the render boundary. Narrows to `Readonly<Record<string, unknown>>` because\n * the outgoing payload carries heterogeneous values (ReactNodes for the rendered\n * tree, plus metadata like `__layoutFlags` which is a plain object). Delegates\n * to React's canonical `isValidElement` so we don't depend on React's internal\n * `$$typeof` marker scheme.\n */\nexport function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n if (typeof value !== \"object\" || value === null) return false;\n if (Array.isArray(value)) return false;\n if (isValidElement(value)) return false;\n return true;\n}\n\n/**\n * Pure: returns a new record with `__layoutFlags` attached. Owns the write\n * boundary for the layout flags key so the write side sits next to\n * `readAppElementsMetadata`.\n *\n * See `LayoutFlags` type docblock in this file for lifecycle.\n */\nexport function withLayoutFlags<T extends Record<string, unknown>>(\n elements: T,\n layoutFlags: LayoutFlags,\n): T & { [APP_LAYOUT_FLAGS_KEY]: LayoutFlags } {\n return { ...elements, [APP_LAYOUT_FLAGS_KEY]: layoutFlags };\n}\n\n/**\n * The outgoing wire payload shape. Includes ReactNode values for the\n * rendered tree plus metadata values like LayoutFlags attached under\n * known keys (e.g. __layoutFlags). Distinct from AppElements / AppWireElements\n * which only carry render-time values.\n */\nexport type AppOutgoingElements = Readonly<Record<string, ReactNode | LayoutFlags>>;\n\n/**\n * Pure: builds the outgoing payload for the wire. Non-record inputs (e.g. a\n * bare React element) are returned unchanged. Record inputs get a fresh copy\n * with `__layoutFlags` attached. Never mutates `input.element`.\n */\nexport function buildOutgoingAppPayload(input: {\n element: ReactNode | Readonly<Record<string, ReactNode>>;\n layoutFlags: LayoutFlags;\n}): ReactNode | AppOutgoingElements {\n if (!isAppElementsRecord(input.element)) {\n return input.element;\n }\n return withLayoutFlags(input.element, input.layoutFlags);\n}\n\n/**\n * Parses metadata from the wire payload. Accepts `Record<string, unknown>`\n * because the RSC payload carries heterogeneous values (React elements,\n * strings, and plain objects like layout flags) under the same record type.\n *\n * See `LayoutFlags` type docblock in this file for lifecycle.\n */\nexport function readAppElementsMetadata(\n elements: Readonly<Record<string, unknown>>,\n): AppElementsMetadata {\n const routeId = elements[APP_ROUTE_KEY];\n if (typeof routeId !== \"string\") {\n throw new Error(\"[vinext] Missing __route string in App Router payload\");\n }\n\n const interceptionContext = elements[APP_INTERCEPTION_CONTEXT_KEY];\n if (\n interceptionContext !== undefined &&\n interceptionContext !== null &&\n typeof interceptionContext !== \"string\"\n ) {\n throw new Error(\"[vinext] Invalid __interceptionContext in App Router payload\");\n }\n\n const rootLayoutTreePath = elements[APP_ROOT_LAYOUT_KEY];\n if (rootLayoutTreePath === undefined) {\n throw new Error(\"[vinext] Missing __rootLayout key in App Router payload\");\n }\n if (rootLayoutTreePath !== null && typeof rootLayoutTreePath !== \"string\") {\n throw new Error(\"[vinext] Invalid __rootLayout in App Router payload: expected string or null\");\n }\n\n const layoutFlags = parseLayoutFlags(elements[APP_LAYOUT_FLAGS_KEY]);\n\n return {\n interceptionContext: interceptionContext ?? null,\n layoutFlags,\n routeId,\n rootLayoutTreePath,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"app-elements.js","names":[],"sources":["../../src/server/app-elements.ts"],"sourcesContent":["import { normalizeMountedSlotsHeader } from \"./app-mounted-slots-header.js\";\nimport { AppElementsWire, UNMATCHED_SLOT, type AppElements } from \"./app-elements-wire.js\";\n\nexport {\n AppElementsWire,\n APP_ARTIFACT_COMPATIBILITY_KEY,\n APP_INTERCEPTION_CONTEXT_KEY,\n APP_LAYOUT_FLAGS_KEY,\n APP_ROOT_LAYOUT_KEY,\n APP_ROUTE_KEY,\n APP_UNMATCHED_SLOT_WIRE_VALUE,\n UNMATCHED_SLOT,\n buildOutgoingAppPayload,\n isAppElementsRecord,\n normalizeAppElements,\n readAppElementsMetadata,\n withLayoutFlags,\n type AppElementValue,\n type AppElements,\n type AppOutgoingElements,\n type AppWireElements,\n type LayoutFlags,\n} from \"./app-elements-wire.js\";\n\n// Raw constructor helpers stay private because callers use AppElementsWire codecs.\n\nexport function getMountedSlotIds(elements: AppElements): string[] {\n return Object.keys(elements)\n .filter((key) => {\n const value = elements[key];\n return (\n AppElementsWire.isSlotId(key) &&\n value !== null &&\n value !== undefined &&\n value !== UNMATCHED_SLOT\n );\n })\n .sort();\n}\n\nexport function getMountedSlotIdsHeader(elements: AppElements): string | null {\n return normalizeMountedSlotsHeader(getMountedSlotIds(elements).join(\" \"));\n}\n\nexport function resolveVisitedResponseInterceptionContext(\n requestInterceptionContext: string | null,\n payloadInterceptionContext: string | null,\n): string | null {\n return payloadInterceptionContext ?? requestInterceptionContext;\n}\n"],"mappings":";;;AA0BA,SAAgB,kBAAkB,UAAiC;AACjE,QAAO,OAAO,KAAK,SAAS,CACzB,QAAQ,QAAQ;EACf,MAAM,QAAQ,SAAS;AACvB,SACE,gBAAgB,SAAS,IAAI,IAC7B,UAAU,QACV,UAAU,KAAA,KACV,UAAU;GAEZ,CACD,MAAM;;AAGX,SAAgB,wBAAwB,UAAsC;AAC5E,QAAO,4BAA4B,kBAAkB,SAAS,CAAC,KAAK,IAAI,CAAC;;AAG3E,SAAgB,0CACd,4BACA,4BACe;AACf,QAAO,8BAA8B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { MetadataFileRoute } from "./metadata-routes.js";
|
|
2
|
+
import { AppElements } from "./app-elements-wire.js";
|
|
3
|
+
import { AppPageParams } from "./app-page-boundary.js";
|
|
4
|
+
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
5
|
+
import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
6
|
+
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
7
|
+
import { AppPageBoundaryRoute } from "./app-page-boundary-render.js";
|
|
8
|
+
import * as _$react from "react";
|
|
9
|
+
import { ReactNode } from "react";
|
|
10
|
+
|
|
11
|
+
//#region src/server/app-fallback-renderer.d.ts
|
|
12
|
+
type AppPageComponent = _$react.ComponentType<any>;
|
|
13
|
+
type AppPageModule = Record<string, unknown> & {
|
|
14
|
+
default?: AppPageComponent | null | undefined;
|
|
15
|
+
};
|
|
16
|
+
type AppPageBoundaryOnError = (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
|
|
17
|
+
type AppFallbackRendererRootBoundaries<TModule extends AppPageModule = AppPageModule> = {
|
|
18
|
+
rootForbiddenModule?: TModule | null;
|
|
19
|
+
rootLayouts: readonly (TModule | null | undefined)[];
|
|
20
|
+
rootNotFoundModule?: TModule | null;
|
|
21
|
+
rootUnauthorizedModule?: TModule | null;
|
|
22
|
+
};
|
|
23
|
+
type AppFallbackRendererFontProviders = {
|
|
24
|
+
buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;
|
|
25
|
+
getFontLinks: () => string[];
|
|
26
|
+
getFontPreloads: () => AppPageFontPreload[];
|
|
27
|
+
getFontStyles: () => string[];
|
|
28
|
+
};
|
|
29
|
+
type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> = {
|
|
30
|
+
clearRequestContext: () => void;
|
|
31
|
+
createRscOnErrorHandler: (request: Request, pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
32
|
+
fontProviders: AppFallbackRendererFontProviders;
|
|
33
|
+
getNavigationContext: () => unknown;
|
|
34
|
+
globalErrorModule?: TModule | null;
|
|
35
|
+
makeThenableParams: (params: AppPageParams) => unknown;
|
|
36
|
+
metadataRoutes: MetadataFileRoute[];
|
|
37
|
+
resolveChildSegments: (routeSegments: readonly string[], treePosition: number, params: AppPageParams) => string[];
|
|
38
|
+
rootBoundaries: AppFallbackRendererRootBoundaries<TModule>;
|
|
39
|
+
rscRenderer: (element: ReactNode | AppElements, options: {
|
|
40
|
+
onError: AppPageBoundaryOnError;
|
|
41
|
+
}) => ReadableStream<Uint8Array>;
|
|
42
|
+
sanitizer: (error: Error) => Error;
|
|
43
|
+
ssrLoader: () => Promise<AppPageSsrHandler>;
|
|
44
|
+
};
|
|
45
|
+
type AppFallbackRenderer<TModule extends AppPageModule = AppPageModule> = {
|
|
46
|
+
renderErrorBoundary: (route: AppPageBoundaryRoute<TModule> | null, error: unknown, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext) => Promise<Response | null>;
|
|
47
|
+
renderHttpAccessFallback: (route: AppPageBoundaryRoute<TModule> | null, statusCode: number, isRscRequest: boolean, request: Request, opts: {
|
|
48
|
+
boundaryComponent?: AppPageComponent | null;
|
|
49
|
+
layouts?: readonly (TModule | null | undefined)[] | null;
|
|
50
|
+
matchedParams?: AppPageParams;
|
|
51
|
+
}, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext) => Promise<Response | null>;
|
|
52
|
+
renderNotFound: (route: AppPageBoundaryRoute<TModule> | null, isRscRequest: boolean, request: Request, matchedParams: AppPageParams | undefined, scriptNonce: string | undefined, middlewareContext: AppPageMiddlewareContext) => Promise<Response | null>;
|
|
53
|
+
};
|
|
54
|
+
declare function createAppFallbackRenderer<TModule extends AppPageModule>(options: AppFallbackRendererOptions<TModule>): AppFallbackRenderer<TModule>;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { createAppFallbackRenderer };
|
|
57
|
+
//# sourceMappingURL=app-fallback-renderer.d.ts.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./app-page-boundary-render.js";
|
|
2
|
+
//#region src/server/app-fallback-renderer.ts
|
|
3
|
+
const EMPTY_MW_CTX = {
|
|
4
|
+
headers: null,
|
|
5
|
+
status: null
|
|
6
|
+
};
|
|
7
|
+
function createAppFallbackRenderer(options) {
|
|
8
|
+
const { clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader } = options;
|
|
9
|
+
const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } = rootBoundaries;
|
|
10
|
+
return {
|
|
11
|
+
renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, middlewareContext) {
|
|
12
|
+
return renderAppPageHttpAccessFallback({
|
|
13
|
+
boundaryComponent: opts?.boundaryComponent ?? null,
|
|
14
|
+
buildFontLinkHeader: fontProviders.buildFontLinkHeader,
|
|
15
|
+
clearRequestContext,
|
|
16
|
+
createRscOnErrorHandler(pathname, routePath) {
|
|
17
|
+
return buildRscOnErrorHandler(request, pathname, routePath);
|
|
18
|
+
},
|
|
19
|
+
getFontLinks: fontProviders.getFontLinks,
|
|
20
|
+
getFontPreloads: fontProviders.getFontPreloads,
|
|
21
|
+
getFontStyles: fontProviders.getFontStyles,
|
|
22
|
+
getNavigationContext,
|
|
23
|
+
globalErrorModule,
|
|
24
|
+
isRscRequest,
|
|
25
|
+
layoutModules: opts?.layouts ?? null,
|
|
26
|
+
loadSsrHandler: ssrLoader,
|
|
27
|
+
makeThenableParams,
|
|
28
|
+
matchedParams: opts?.matchedParams ?? route?.params ?? {},
|
|
29
|
+
middlewareContext: middlewareContext ?? EMPTY_MW_CTX,
|
|
30
|
+
metadataRoutes,
|
|
31
|
+
requestUrl: request.url,
|
|
32
|
+
resolveChildSegments,
|
|
33
|
+
rootForbiddenModule,
|
|
34
|
+
rootLayouts,
|
|
35
|
+
rootNotFoundModule,
|
|
36
|
+
rootUnauthorizedModule,
|
|
37
|
+
route,
|
|
38
|
+
renderToReadableStream: rscRenderer,
|
|
39
|
+
scriptNonce,
|
|
40
|
+
statusCode
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
renderNotFound(route, isRscRequest, request, matchedParams, scriptNonce, middlewareContext) {
|
|
44
|
+
return this.renderHttpAccessFallback(route, 404, isRscRequest, request, { matchedParams }, scriptNonce, middlewareContext);
|
|
45
|
+
},
|
|
46
|
+
renderErrorBoundary(route, error, isRscRequest, request, matchedParams, scriptNonce, middlewareContext) {
|
|
47
|
+
return renderAppPageErrorBoundary({
|
|
48
|
+
buildFontLinkHeader: fontProviders.buildFontLinkHeader,
|
|
49
|
+
clearRequestContext,
|
|
50
|
+
createRscOnErrorHandler(pathname, routePath) {
|
|
51
|
+
return buildRscOnErrorHandler(request, pathname, routePath);
|
|
52
|
+
},
|
|
53
|
+
error,
|
|
54
|
+
getFontLinks: fontProviders.getFontLinks,
|
|
55
|
+
getFontPreloads: fontProviders.getFontPreloads,
|
|
56
|
+
getFontStyles: fontProviders.getFontStyles,
|
|
57
|
+
getNavigationContext,
|
|
58
|
+
globalErrorModule,
|
|
59
|
+
isRscRequest,
|
|
60
|
+
loadSsrHandler: ssrLoader,
|
|
61
|
+
makeThenableParams,
|
|
62
|
+
matchedParams: matchedParams ?? route?.params ?? {},
|
|
63
|
+
middlewareContext: middlewareContext ?? EMPTY_MW_CTX,
|
|
64
|
+
metadataRoutes,
|
|
65
|
+
requestUrl: request.url,
|
|
66
|
+
resolveChildSegments,
|
|
67
|
+
rootLayouts,
|
|
68
|
+
route,
|
|
69
|
+
renderToReadableStream: rscRenderer,
|
|
70
|
+
sanitizeErrorForClient: sanitizer,
|
|
71
|
+
scriptNonce
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { createAppFallbackRenderer };
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=app-fallback-renderer.js.map
|