@rangojs/router 0.17.0 → 0.19.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 +3 -2
- package/dist/types/browser/cookie-name.d.ts +6 -0
- package/dist/types/browser/event-controller.d.ts +3 -3
- package/dist/types/browser/history-state.d.ts +18 -0
- package/dist/types/browser/navigation-transaction.d.ts +20 -2
- package/dist/types/browser/partial-update.d.ts +16 -1
- package/dist/types/browser/prefetch/cache.d.ts +6 -6
- package/dist/types/browser/react/Link.d.ts +19 -9
- package/dist/types/browser/react/context.d.ts +2 -2
- package/dist/types/browser/react/location-state-shared.d.ts +95 -56
- package/dist/types/browser/react/location-state.d.ts +1 -1
- package/dist/types/browser/transition-when.d.ts +80 -0
- package/dist/types/browser/types.d.ts +104 -9
- package/dist/types/build/generate-manifest.d.ts +8 -0
- package/dist/types/cache/background-task.d.ts +24 -2
- package/dist/types/cache/cache-exec-scope.d.ts +31 -0
- package/dist/types/cache/cache-key-utils.d.ts +48 -2
- package/dist/types/cache/cache-policy.d.ts +18 -1
- package/dist/types/cache/cache-runtime.d.ts +7 -0
- package/dist/types/cache/cache-scope.d.ts +192 -26
- package/dist/types/cache/cache-tag.d.ts +116 -11
- package/dist/types/cache/cf/cf-base64.d.ts +6 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +11 -0
- package/dist/types/cache/cf/cf-cache-store.d.ts +224 -72
- package/dist/types/cache/cf/cf-cache-types.d.ts +31 -4
- package/dist/types/cache/cf/cf-shell-frame.d.ts +95 -0
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +19 -0
- package/dist/types/cache/document-cache.d.ts +10 -0
- package/dist/types/cache/handle-snapshot.d.ts +41 -8
- package/dist/types/cache/index.d.ts +1 -0
- package/dist/types/cache/invalidation-order.d.ts +23 -0
- package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
- package/dist/types/cache/request-tag-mask.d.ts +54 -0
- package/dist/types/cache/shell-memo.d.ts +178 -0
- package/dist/types/cache/shell-snapshot.d.ts +141 -105
- package/dist/types/cache/tag-invalidation.d.ts +54 -3
- package/dist/types/cache/types.d.ts +267 -96
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +123 -18
- package/dist/types/client-urls/navigation.d.ts +28 -2
- package/dist/types/client-urls/server-projection.d.ts +5 -2
- package/dist/types/client-urls/types.d.ts +5 -5
- package/dist/types/client.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +1 -1
- package/dist/types/prerender/build-shell-capture.d.ts +11 -4
- package/dist/types/route-definition/helpers-types.d.ts +11 -11
- package/dist/types/route-name.d.ts +7 -0
- package/dist/types/router/error-handling.d.ts +1 -1
- package/dist/types/router/instrument.d.ts +8 -0
- package/dist/types/router/intercept-resolution.d.ts +2 -0
- package/dist/types/router/match-context.d.ts +5 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +0 -4
- package/dist/types/router/middleware-types.d.ts +6 -1
- package/dist/types/router/router-options.d.ts +4 -1
- package/dist/types/router/segment-resolution/loader-cache.d.ts +58 -12
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +33 -48
- package/dist/types/router/segment-resolution/mask-nested.d.ts +73 -24
- package/dist/types/router/segment-resolution/view-transition-default.d.ts +7 -5
- package/dist/types/router/transition-when.d.ts +24 -10
- package/dist/types/rsc/attach-transition-when.d.ts +18 -0
- package/dist/types/rsc/full-payload.d.ts +21 -0
- package/dist/types/rsc/handler.d.ts +1 -1
- package/dist/types/rsc/response-cache-serve.d.ts +15 -12
- package/dist/types/rsc/shell-build-manifest.d.ts +12 -3
- package/dist/types/rsc/shell-capture-constants.d.ts +116 -12
- package/dist/types/rsc/shell-capture.d.ts +202 -74
- package/dist/types/rsc/shell-serve.d.ts +144 -50
- package/dist/types/rsc/types.d.ts +9 -0
- package/dist/types/segment-system.d.ts +7 -0
- package/dist/types/server/context.d.ts +155 -33
- package/dist/types/server/cookie-store.d.ts +33 -0
- package/dist/types/server/handle-store.d.ts +52 -1
- package/dist/types/server/request-context.d.ts +210 -63
- package/dist/types/server/request-headers.d.ts +44 -0
- package/dist/types/server.d.ts +1 -0
- package/dist/types/ssr/index.d.ts +9 -0
- package/dist/types/ssr/ssr-root.d.ts +9 -8
- package/dist/types/testing/e2e/index.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +7 -0
- package/dist/types/testing/index.d.ts +3 -2
- package/dist/types/testing/internal/action-id.d.ts +7 -0
- package/dist/types/testing/location-state-key.d.ts +24 -0
- package/dist/types/testing/render-route.d.ts +17 -1
- package/dist/types/testing/run-loader.d.ts +18 -3
- package/dist/types/testing/run-transition-when.d.ts +44 -69
- package/dist/types/testing/serve-shell-request.d.ts +133 -0
- package/dist/types/testing/shell-status.d.ts +44 -19
- package/dist/types/transition-when-ref.d.ts +79 -0
- package/dist/types/types/cache-types.d.ts +15 -3
- package/dist/types/types/handler-context.d.ts +14 -1
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/segments.d.ts +86 -71
- package/dist/types/urls/path-helper-types.d.ts +3 -4
- package/dist/types/urls/pattern-types.d.ts +21 -18
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
- package/dist/types/vite/router-discovery.d.ts +29 -2
- package/dist/vite/index.js +1005 -105
- package/package.json +1 -1
- package/skills/breadcrumbs/SKILL.md +17 -7
- package/skills/cache-guide/SKILL.md +175 -76
- package/skills/caching/SKILL.md +361 -33
- package/skills/catalog.json +1 -1
- package/skills/client-urls/SKILL.md +12 -7
- package/skills/cloudflare/SKILL.md +15 -0
- package/skills/comparison/references/framework-comparison.md +52 -37
- package/skills/defer-hydration/SKILL.md +50 -30
- package/skills/deployment-caching/SKILL.md +5 -2
- package/skills/document-cache/SKILL.md +32 -2
- package/skills/handler-use/SKILL.md +2 -0
- package/skills/hooks/SKILL.md +3 -1
- package/skills/hooks/handle-and-actions.md +3 -1
- package/skills/hooks/navigation.md +23 -2
- package/skills/hooks/state.md +101 -7
- package/skills/intercept/SKILL.md +29 -12
- package/skills/loader/SKILL.md +197 -44
- package/skills/middleware/SKILL.md +34 -9
- package/skills/migrate-nextjs/SKILL.md +68 -37
- package/skills/migrate-react-router/SKILL.md +2 -1
- package/skills/migrate-react-router/component-migration.md +3 -1
- package/skills/migrate-react-router/data-and-actions.md +3 -1
- package/skills/migrate-react-router/route-mapping.md +7 -4
- package/skills/observability/SKILL.md +65 -0
- package/skills/parallel/SKILL.md +13 -8
- package/skills/ppr/SKILL.md +715 -371
- package/skills/prerender/SKILL.md +30 -17
- package/skills/rango/SKILL.md +72 -34
- package/skills/route/SKILL.md +14 -7
- package/skills/router-setup/SKILL.md +4 -2
- package/skills/scripts/SKILL.md +8 -1
- package/skills/server-actions/SKILL.md +11 -0
- package/skills/shell-manifest/SKILL.md +21 -12
- package/skills/testing/SKILL.md +49 -43
- package/skills/testing/cache-prerender.md +15 -14
- package/skills/testing/client-components.md +45 -3
- package/skills/testing/loader.md +19 -1
- package/skills/testing/middleware.md +1 -0
- package/skills/testing/predicates.md +49 -49
- package/skills/testing/render-handler.md +1 -0
- package/skills/testing/serve-shell-request.md +202 -0
- package/skills/testing/server-actions.md +9 -3
- package/skills/theme/SKILL.md +56 -4
- package/skills/typesafety/env-and-bindings.md +18 -2
- package/skills/use-cache/SKILL.md +91 -23
- package/skills/vercel/SKILL.md +14 -2
- package/skills/view-transitions/SKILL.md +150 -29
- package/src/__augment-tests__/augmented.check.ts +23 -0
- package/src/browser/cookie-name.ts +23 -0
- package/src/browser/event-controller.ts +4 -4
- package/src/browser/history-state.ts +75 -1
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +77 -18
- package/src/browser/navigation-client.ts +4 -3
- package/src/browser/navigation-store.ts +43 -1
- package/src/browser/navigation-transaction.ts +31 -11
- package/src/browser/partial-update.ts +146 -35
- package/src/browser/prefetch/cache.ts +6 -6
- package/src/browser/prefetch/fetch.ts +2 -2
- package/src/browser/react/Link.tsx +38 -33
- package/src/browser/react/NavigationProvider.tsx +2 -2
- package/src/browser/react/context.ts +2 -2
- package/src/browser/react/location-state-shared.ts +241 -49
- package/src/browser/react/location-state.ts +5 -2
- package/src/browser/rsc-router.tsx +9 -0
- package/src/browser/server-action-bridge.ts +84 -15
- package/src/browser/transition-when.ts +205 -0
- package/src/browser/types.ts +124 -10
- package/src/build/generate-manifest.ts +77 -1
- package/src/cache/background-task.ts +55 -2
- package/src/cache/cache-exec-scope.ts +48 -1
- package/src/cache/cache-key-utils.ts +62 -2
- package/src/cache/cache-policy.ts +31 -4
- package/src/cache/cache-runtime.ts +209 -129
- package/src/cache/cache-scope.ts +573 -69
- package/src/cache/cache-tag.ts +475 -19
- package/src/cache/cf/cf-base64.ts +36 -4
- package/src/cache/cf/cf-cache-constants.ts +12 -0
- package/src/cache/cf/cf-cache-store.ts +1094 -376
- package/src/cache/cf/cf-cache-types.ts +32 -4
- package/src/cache/cf/cf-shell-frame.ts +258 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +55 -40
- package/src/cache/document-cache.ts +53 -7
- package/src/cache/handle-snapshot.ts +53 -9
- package/src/cache/index.ts +2 -0
- package/src/cache/invalidation-order.ts +84 -0
- package/src/cache/isolate-tag-memo.ts +308 -0
- package/src/cache/request-tag-mask.ts +147 -0
- package/src/cache/shell-memo.ts +341 -0
- package/src/cache/shell-snapshot.ts +249 -277
- package/src/cache/tag-invalidation.ts +109 -18
- package/src/cache/types.ts +274 -102
- package/src/cache/vercel/vercel-cache-store.ts +561 -74
- package/src/client-urls/client-root.tsx +8 -4
- package/src/client-urls/client-urls.ts +8 -6
- package/src/client-urls/navigation.ts +55 -4
- package/src/client-urls/server-projection.ts +31 -10
- package/src/client-urls/types.ts +12 -5
- package/src/client.tsx +2 -0
- package/src/host/cookie-handler.ts +2 -1
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +3 -0
- package/src/loader-redirect.tsx +7 -3
- package/src/prerender/build-shell-capture.ts +173 -110
- package/src/route-definition/dsl-helpers.ts +6 -3
- package/src/route-definition/helpers-types.ts +11 -11
- package/src/route-name.ts +12 -0
- package/src/router/content-negotiation.ts +4 -1
- package/src/router/error-handling.ts +5 -2
- package/src/router/handler-context.ts +42 -5
- package/src/router/instrument.ts +54 -2
- package/src/router/intercept-resolution.ts +30 -8
- package/src/router/loader-resolution.ts +89 -33
- package/src/router/logging.ts +5 -3
- package/src/router/match-api.ts +89 -42
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +14 -29
- package/src/router/match-middleware/background-revalidation.ts +3 -5
- package/src/router/match-middleware/cache-lookup.ts +52 -19
- package/src/router/match-middleware/cache-store.ts +36 -10
- package/src/router/match-result.ts +1 -0
- package/src/router/middleware-types.ts +6 -1
- package/src/router/middleware.ts +20 -4
- package/src/router/navigation-snapshot.ts +6 -5
- package/src/router/prerender-match.ts +10 -0
- package/src/router/request-classification.ts +7 -4
- package/src/router/router-options.ts +4 -1
- package/src/router/segment-resolution/fresh.ts +18 -13
- package/src/router/segment-resolution/helpers.ts +4 -2
- package/src/router/segment-resolution/loader-cache.ts +366 -70
- package/src/router/segment-resolution/loader-mask.ts +3 -4
- package/src/router/segment-resolution/loader-snapshot.ts +215 -126
- package/src/router/segment-resolution/mask-nested.ts +161 -42
- package/src/router/segment-resolution/revalidation.ts +27 -13
- package/src/router/segment-resolution/view-transition-default.ts +6 -21
- package/src/router/telemetry.ts +6 -3
- package/src/router/transition-when.ts +34 -52
- package/src/router.ts +2 -1
- package/src/rsc/attach-transition-when.ts +47 -0
- package/src/rsc/full-payload.ts +47 -3
- package/src/rsc/handler.ts +24 -10
- package/src/rsc/loader-fetch.ts +2 -1
- package/src/rsc/manifest-init.ts +4 -0
- package/src/rsc/origin-guard.ts +8 -5
- package/src/rsc/progressive-enhancement.ts +10 -32
- package/src/rsc/response-cache-serve.ts +69 -78
- package/src/rsc/response-route-handler.ts +2 -2
- package/src/rsc/rsc-rendering.ts +712 -338
- package/src/rsc/server-action.ts +8 -20
- package/src/rsc/shell-build-manifest.ts +49 -29
- package/src/rsc/shell-capture-constants.ts +182 -12
- package/src/rsc/shell-capture.ts +1126 -612
- package/src/rsc/shell-serve.ts +331 -85
- package/src/rsc/ssr-setup.ts +3 -2
- package/src/rsc/types.ts +9 -0
- package/src/segment-system.tsx +40 -7
- package/src/server/context.ts +328 -72
- package/src/server/cookie-store.ts +184 -133
- package/src/server/handle-store.ts +245 -27
- package/src/server/request-context.ts +364 -100
- package/src/server/request-headers.ts +134 -0
- package/src/server.ts +4 -0
- package/src/ssr/index.tsx +96 -37
- package/src/ssr/ssr-root.tsx +9 -8
- package/src/testing/dispatch.ts +4 -7
- package/src/testing/e2e/index.ts +1 -0
- package/src/testing/flight.entry.ts +14 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/internal/action-id.ts +25 -0
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/location-state-key.ts +45 -0
- package/src/testing/render-handler.ts +1 -1
- package/src/testing/render-route.tsx +109 -16
- package/src/testing/run-client-revalidate.ts +3 -19
- package/src/testing/run-loader.ts +67 -5
- package/src/testing/run-transition-when.ts +109 -172
- package/src/testing/serve-shell-request.ts +381 -0
- package/src/testing/shell-status.ts +73 -47
- package/src/theme/ThemeProvider.tsx +7 -6
- package/src/transition-when-ref.ts +220 -0
- package/src/types/cache-types.ts +15 -3
- package/src/types/handler-context.ts +14 -1
- package/src/types/index.ts +3 -0
- package/src/types/segments.ts +94 -91
- package/src/urls/path-helper-types.ts +3 -4
- package/src/urls/pattern-types.ts +21 -18
- package/src/vite/discovery/discover-routers.ts +3 -0
- package/src/vite/discovery/shell-prerender-phase.ts +9 -2
- package/src/vite/discovery/virtual-module-codegen.ts +16 -6
- package/src/vite/plugins/transition-when-hoist.ts +1064 -0
- package/src/vite/rango.ts +2 -0
- package/src/vite/router-discovery.ts +89 -9
- package/dist/types/rsc/transition-gate.d.ts +0 -23
- package/src/rsc/transition-gate.ts +0 -86
|
@@ -4,30 +4,27 @@
|
|
|
4
4
|
*
|
|
5
5
|
* A bake-lane loader (lane rule: see resolveLoaderData, loader-cache.ts)
|
|
6
6
|
* executes during shell capture; its settled container bakes into the prelude
|
|
7
|
-
* while nested promises postpone as holes. To keep a HIT's fresh
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* while nested promises postpone as holes. To keep a HIT's fresh payload in
|
|
8
|
+
* agreement with that frozen prelude, the capture pins the container in the
|
|
9
|
+
* shell snapshot. Everything outside a hole is pinned; the one exception is a
|
|
10
|
+
* server-component element holding a promise, which is a hole as a whole (see
|
|
11
|
+
* elideLoaderContainer):
|
|
10
12
|
*
|
|
11
|
-
* - elide: deep-walk the settled container; a
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* elide anyway, and the overlay keeps decoding SETTLED markers
|
|
18
|
-
* from pre-mask snapshots. The result is promise-free and
|
|
19
|
-
* Flight-serializable.
|
|
13
|
+
* - elide: deep-walk the settled container; a nested promise is a hole,
|
|
14
|
+
* replaced by {@link LOADER_HOLE_KEY}. loader-cache masks every
|
|
15
|
+
* nested thenable at capture ({@link maskNestedContainerThenables},
|
|
16
|
+
* a never-settling promise), so the promise shape alone decides:
|
|
17
|
+
* a value that settled in time does not bake (#692). The result
|
|
18
|
+
* is promise-free and Flight-serializable.
|
|
20
19
|
* - overlay: on a HIT the loader runs fresh (only the loader body can mint
|
|
21
20
|
* the live nested promises), then the recorded container is laid
|
|
22
21
|
* over it: recorded paths win (they are what the prelude froze),
|
|
23
22
|
* hole-marker paths take the fresh run's value (the live hole),
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* handing them the raw value throws React #438 on every HIT (the
|
|
27
|
-
* storefront PDP regression) — and fresh-only paths pass through
|
|
28
|
-
* (they cannot contradict prelude bytes that never rendered them).
|
|
23
|
+
* and fresh-only paths pass through (they cannot contradict
|
|
24
|
+
* prelude bytes that never rendered them).
|
|
29
25
|
*/
|
|
30
|
-
|
|
26
|
+
import { maskNestedContainerThenables } from "./mask-nested.js";
|
|
27
|
+
export { maskNestedContainerThenables };
|
|
31
28
|
/**
|
|
32
29
|
* Marker object standing in for a pending nested promise in a recorded loader
|
|
33
30
|
* container. Shape-checked (not identity-checked) because the record round-trips
|
|
@@ -38,26 +35,6 @@ export interface LoaderHoleMarker {
|
|
|
38
35
|
[LOADER_HOLE_KEY]: 1;
|
|
39
36
|
}
|
|
40
37
|
export declare function isLoaderHoleMarker(value: unknown): value is LoaderHoleMarker;
|
|
41
|
-
/**
|
|
42
|
-
* Marker wrapping the inlined value of a NESTED promise that settled during
|
|
43
|
-
* capture. The value baked (physics), but the container key was a promise —
|
|
44
|
-
* the overlay must hand consumers a Promise.resolve(value), not the raw value,
|
|
45
|
-
* or an unconditional use(data.x) throws React #438 on every HIT. The ROOT
|
|
46
|
-
* container is never wrapped: loader-cache overlays against the awaited fresh
|
|
47
|
-
* container value.
|
|
48
|
-
*/
|
|
49
|
-
export declare const LOADER_SETTLED_KEY: "$rangoLoaderSettled";
|
|
50
|
-
export interface LoaderSettledMarker {
|
|
51
|
-
[LOADER_SETTLED_KEY]: 1;
|
|
52
|
-
value: unknown;
|
|
53
|
-
/**
|
|
54
|
-
* Present when the pinned subtree contains hole markers. Computed once at
|
|
55
|
-
* capture (elide already visits every node) so the per-HIT overlay never
|
|
56
|
-
* rescans the pinned structure to pick its rehydration path.
|
|
57
|
-
*/
|
|
58
|
-
holes?: 1;
|
|
59
|
-
}
|
|
60
|
-
export declare function isLoaderSettledMarker(value: unknown): value is LoaderSettledMarker;
|
|
61
38
|
export type ElideResult = {
|
|
62
39
|
state: "ok";
|
|
63
40
|
value: unknown;
|
|
@@ -66,25 +43,33 @@ export type ElideResult = {
|
|
|
66
43
|
state: "rejected";
|
|
67
44
|
};
|
|
68
45
|
/**
|
|
69
|
-
* Deep-elide a settled bake-lane container for recording.
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
46
|
+
* Deep-elide a settled bake-lane container for recording. Nested promises
|
|
47
|
+
* become hole markers: the capture masked each of them (never settles), so
|
|
48
|
+
* it postponed as a hole. A REJECTED container poisons the record (error UI
|
|
49
|
+
* must never bake into a shared shell) — the caller refuses the capture.
|
|
50
|
+
* Plain data objects, arrays and the props of host, Suspense/Fragment and
|
|
51
|
+
* client-reference elements are
|
|
52
|
+
* traversed copy-on-write (an element through cloneElementWithProps); a shared
|
|
53
|
+
* subtree or a cycle resolves to the same elided result. An element Flight
|
|
54
|
+
* renders by calling user code (see rendersOnServer) is a leaf, or ONE hole
|
|
55
|
+
* marker when a thenable sits anywhere in its props: the pin encode calls that
|
|
56
|
+
* component, so a marker inside its props would reach it. Anything else
|
|
57
|
+
* (Date, Map, class instance, lazy node) is a pinned leaf.
|
|
77
58
|
*
|
|
78
59
|
* The ROOT container promise-chain unwraps with NO marker: loader-cache
|
|
79
60
|
* overlays against the AWAITED fresh container, so the recorded root must be
|
|
80
61
|
* the unwrapped structure. Everything below it goes through elideNested.
|
|
81
62
|
*/
|
|
82
|
-
export declare function elideLoaderContainer(value: unknown, seen?:
|
|
63
|
+
export declare function elideLoaderContainer(value: unknown, seen?: Map<object, ElideResult>): Promise<ElideResult>;
|
|
83
64
|
/**
|
|
84
65
|
* Overlay a recorded (elided) container onto the fresh run's container for a
|
|
85
66
|
* shell HIT. Recorded wins per path; hole markers take the fresh value (the
|
|
86
67
|
* live nested promise); fresh-only object keys pass through. Where the shapes
|
|
87
68
|
* disagree structurally, recorded wins wholesale — it is what the prelude
|
|
88
|
-
* froze, and parity beats freshness inside the shell.
|
|
69
|
+
* froze, and parity beats freshness inside the shell. Copy-on-write: a
|
|
70
|
+
* recorded subtree without markers comes back by identity. A recorded element
|
|
71
|
+
* is rebuilt through cloneElementWithProps only at its marker paths, so its
|
|
72
|
+
* other props stay pinned; props the fresh element adds do not pass through
|
|
73
|
+
* (the prelude rendered the element without them).
|
|
89
74
|
*/
|
|
90
75
|
export declare function overlayLoaderContainer(fresh: unknown, recorded: unknown): unknown;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Capture-side nested
|
|
3
|
-
* shape is the liveness declaration" for
|
|
4
|
-
* (loader-cache.ts) and
|
|
5
|
-
* push wrap in rsc/shell-capture.ts).
|
|
2
|
+
* Capture-side nested thenables. Masking is the mechanism behind "nested-
|
|
3
|
+
* promise shape is the liveness declaration" for the loader lane: bake-lane
|
|
4
|
+
* loader containers (loader-cache.ts) and DSL loader handle pushes (the
|
|
5
|
+
* capture handle store's push wrap in rsc/shell-capture.ts). Handler handle
|
|
6
|
+
* pushes are handler output and bake: the capture waits for their nested
|
|
7
|
+
* promises instead (settleNestedThenables).
|
|
6
8
|
*
|
|
7
9
|
* Deliberately a LEAF module: loader-mask (the other natural home) imports
|
|
8
10
|
* request-context, so any funnel importing the mask from there inherits that
|
|
9
|
-
* graph. This module imports only is-thenable.
|
|
11
|
+
* graph. This module imports only is-thenable and react.
|
|
10
12
|
*/
|
|
13
|
+
import { type ReactElement } from "react";
|
|
11
14
|
/**
|
|
12
15
|
* A promise that never settles — the masked stand-in for a per-request value
|
|
13
16
|
* during shell capture. The consuming Suspense subtree suspends forever, so
|
|
@@ -18,11 +21,63 @@
|
|
|
18
21
|
*/
|
|
19
22
|
export declare function createMaskedLoaderPromise<T = unknown>(): Promise<T>;
|
|
20
23
|
/**
|
|
21
|
-
*
|
|
24
|
+
* A data object the container walks descend into: prototype Object.prototype
|
|
25
|
+
* or null, and no symbol `$$typeof`. React elements, lazy nodes and references
|
|
26
|
+
* are plain objects too, told apart by that symbol (Flight switches on it).
|
|
27
|
+
* They are React's, not data: an element's dev-only fields (`_debugStack`,
|
|
28
|
+
* `_debugTask`, `_debugInfo`, `ref`) are non-enumerable, so a key-by-key copy
|
|
29
|
+
* drops them and dev Flight refuses it ("Attempted to render <x> without
|
|
30
|
+
* development properties", issue #942).
|
|
31
|
+
*/
|
|
32
|
+
export declare function isPlainDataObject(value: unknown): value is Record<string, unknown>;
|
|
33
|
+
/**
|
|
34
|
+
* cloneElement with only the given props replaced, keeping React's dev key
|
|
35
|
+
* validation. React 19 dev cloneElement resets `_store.validated`, so a
|
|
36
|
+
* keyless child of a static children list (validated at creation) would warn
|
|
37
|
+
* "Each child in a list should have a unique key" once cloned. Pass only the
|
|
38
|
+
* props that change: cloneElement re-parents the element (owner) when its
|
|
39
|
+
* config carries `ref`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function cloneElementWithProps(element: ReactElement, props: Record<string, unknown>): ReactElement;
|
|
42
|
+
/**
|
|
43
|
+
* Resolves once `value` and every thenable reachable from it through plain
|
|
44
|
+
* data objects, arrays and React element props has settled, following what
|
|
45
|
+
* each thenable resolves to. A rejection counts as settled: the consumer that
|
|
46
|
+
* encodes the value reports it. Other objects are leaves (the same walk as
|
|
47
|
+
* maskNestedContainerThenables), so a promise inside a Map is not waited for.
|
|
48
|
+
* An element is walked through its props only (`<X data={promise} />` in a
|
|
49
|
+
* handle value is handler output too), never its owner or type, and is never
|
|
50
|
+
* rebuilt: nothing is copied, only awaited.
|
|
51
|
+
*
|
|
52
|
+
* The capture waits on this for HANDLER handle pushes (shell-capture.ts):
|
|
53
|
+
* handler output is baked, so its promises must settle before the doc record
|
|
54
|
+
* encodes the handles every HIT replays.
|
|
55
|
+
*/
|
|
56
|
+
export declare function settleNestedThenables(value: unknown): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* True when `value` is a thenable or holds one where the capture's loader
|
|
59
|
+
* push funnel masks it (maskNestedContainerThenables): through plain data
|
|
60
|
+
* objects, arrays and React element props. Such a push stays out of a shell's
|
|
61
|
+
* record and reaches a HIT only from a run of its loader there, so a HIT
|
|
62
|
+
* keeps it; a push without one is the record's (HandleStore.pushRestored).
|
|
63
|
+
*/
|
|
64
|
+
export declare function holdsThenable(value: unknown): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Optional single-walk report for maskNestedContainerThenables: `thenable`
|
|
67
|
+
* flips true when the walk masked at least one thenable. The capture push
|
|
68
|
+
* funnel reads it for a loader push: a container with a masked nested
|
|
69
|
+
* promise keeps its loader tag, so the handle encode never waits on a mask.
|
|
70
|
+
* Same single-pass shape as elideLoaderContainer's `hasHole`.
|
|
71
|
+
*/
|
|
72
|
+
export interface MaskReport {
|
|
73
|
+
thenable: boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Copy a container with every NESTED thenable replaced by a masked
|
|
22
77
|
* (never-resolving) promise. Applied during shell capture to (a) bake-lane
|
|
23
|
-
* loader containers (loader-cache.ts) and (b)
|
|
24
|
-
* (shell-capture.ts capture store push wrap) — the
|
|
25
|
-
*
|
|
78
|
+
* loader containers (loader-cache.ts) and (b) DSL loader handle pushes
|
|
79
|
+
* (shell-capture.ts capture store push wrap) — the rango-owned funnels where
|
|
80
|
+
* a loader declares per-request data by promise SHAPE.
|
|
26
81
|
*
|
|
27
82
|
* Why: a nested promise that happened to SETTLE before the capture's quiet
|
|
28
83
|
* window closed used to bake its value into the SHARED shell (and, for
|
|
@@ -34,20 +89,14 @@ export declare function createMaskedLoaderPromise<T = unknown>(): Promise<T>;
|
|
|
34
89
|
* Masking makes the consuming subtree postpone as a hole no matter when the
|
|
35
90
|
* promise settles: liveness by declaration, not by racing the window.
|
|
36
91
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
92
|
+
* Plain data objects, arrays and React element props are traversed: JSX
|
|
93
|
+
* carrying a promise (`<Reviews data={fetchReviews()} />`) declares
|
|
94
|
+
* per-request data the same way a plain container does. Other values, lazy
|
|
95
|
+
* nodes included, are leaves. Copy-on-write: a subtree without a thenable
|
|
96
|
+
* comes back by identity, so an element is rebuilt only when its props hold
|
|
97
|
+
* one, and then through cloneElementWithProps, which keeps its type, key,
|
|
98
|
+
* owner, dev fields and key validation. The INPUT IS NEVER MUTATED: a handler
|
|
99
|
+
* that reads the loader (`ctx.use`) reads the raw container and must keep
|
|
100
|
+
* real values. Cycles are preserved as cycles in the copy.
|
|
41
101
|
*/
|
|
42
|
-
/**
|
|
43
|
-
* Optional single-walk report for maskNestedContainerThenables: `thenable`
|
|
44
|
-
* flips true when the walk masked at least one thenable. The shell fast path
|
|
45
|
-
* reads it at handle-push time — a pushed container with a nested thenable
|
|
46
|
-
* declares per-request data, and a shell entry whose HANDLER layer made such
|
|
47
|
-
* a declaration cannot be served handler-free (the hole would never fill).
|
|
48
|
-
* Same single-pass shape as elideLoaderContainer's `hasHole`.
|
|
49
|
-
*/
|
|
50
|
-
export interface MaskReport {
|
|
51
|
-
thenable: boolean;
|
|
52
|
-
}
|
|
53
102
|
export declare function maskNestedContainerThenables(value: unknown, seen?: Map<object, unknown>, report?: MaskReport): unknown;
|
|
@@ -19,9 +19,11 @@ import type { EntryData } from "../../server/context";
|
|
|
19
19
|
* (or "auto") value is left untouched because it already means "wrap" at the
|
|
20
20
|
* gate, which also avoids needless object allocation and payload growth.
|
|
21
21
|
*
|
|
22
|
-
* `when`: a server
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* `when`: a client reference the server never calls. It is STRIPPED here so no
|
|
23
|
+
* segment record (segment cache, prerender artifact, shell snapshot) carries
|
|
24
|
+
* it: those stores JSON-serialize the config and would silently drop it on
|
|
25
|
+
* some stores and keep it on others. rsc/attach-transition-when.ts attaches it
|
|
26
|
+
* from the route definition right before Flight instead. Used by both fresh
|
|
27
|
+
* and revalidation resolution.
|
|
26
28
|
*/
|
|
27
|
-
export declare function applyViewTransitionDefault(transition: EntryData["transition"], viewTransitionDefault: "auto" | false | undefined
|
|
29
|
+
export declare function applyViewTransitionDefault(transition: EntryData["transition"], viewTransitionDefault: "auto" | false | undefined): EntryData["transition"];
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
import { type EntryData } from "../server/context.js";
|
|
2
2
|
import type { RequestContext } from "../server/request-context.js";
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import type { TransitionWhenSite } from "../transition-when-ref.js";
|
|
4
|
+
import type { TransitionWhenFn } from "../types/segments.js";
|
|
5
|
+
/** A matched entry's transition({ when }) and where it was declared. */
|
|
6
|
+
export interface TransitionWhenRecord {
|
|
7
|
+
readonly when: TransitionWhenFn;
|
|
8
|
+
readonly site: TransitionWhenSite;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Record the transition({ when }) references of a matched entry chain, keyed
|
|
12
|
+
* by the segment id each entry resolves to. The server never calls them:
|
|
13
|
+
* rsc/attach-transition-when.ts attaches them to the payload's segments right
|
|
14
|
+
* before Flight, and the browser decides (browser/transition-when.ts).
|
|
15
|
+
*
|
|
16
|
+
* Recorded from the static route definition on EVERY match (fresh, cache hit,
|
|
17
|
+
* prerender, PPR replay) because stored segments never carry them:
|
|
18
|
+
* applyViewTransitionDefault strips `when` at resolution, since segment stores
|
|
19
|
+
* JSON-serialize the transition config (dropping a function on some stores,
|
|
20
|
+
* keeping it by reference on others). Segment ids follow resolution: an
|
|
21
|
+
* entry's shortCode, and `${owner.shortCode}.${slot}` for a rendered parallel
|
|
22
|
+
* slot.
|
|
23
|
+
*/
|
|
24
|
+
export declare function recordTransitionWhenRefs<TEnv>(entries: readonly EntryData[] | undefined, ctx: RequestContext<TEnv>, route?: {
|
|
7
25
|
routeName?: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export declare function evaluatePprTransitionWhen<TEnv>(entries: EntryData[], ctx: RequestContext<TEnv>, target: {
|
|
11
|
-
params: Record<string, string>;
|
|
12
|
-
routeName?: string;
|
|
13
|
-
}, reportError: TransitionWhenErrorReporter): void;
|
|
26
|
+
pattern?: string;
|
|
27
|
+
}): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { MatchResult } from "../types.js";
|
|
2
|
+
import type { getRequestContext } from "../server/request-context.js";
|
|
3
|
+
/**
|
|
4
|
+
* Attach transition({ when }) references to a payload's segments, right before
|
|
5
|
+
* Flight. Returns a copy for every segment it changes: the input segments may
|
|
6
|
+
* be the records a cache, prerender, or shell snapshot holds.
|
|
7
|
+
*
|
|
8
|
+
* Only a segment that carries `transition` gets its predicate. The config
|
|
9
|
+
* itself never varies per request, so the segment key and the <ViewTransition>
|
|
10
|
+
* wrapper depend only on the route definition (#995); the browser decides for
|
|
11
|
+
* every committed segment, kept ones included (#989).
|
|
12
|
+
*
|
|
13
|
+
* Render-time backstop for an invalid `when` that route discovery did not see
|
|
14
|
+
* (a route evaluated lazily at runtime): it throws the discovery error. A
|
|
15
|
+
* plain function reaching Flight would otherwise fail with React's generic
|
|
16
|
+
* "Functions cannot be passed directly to Client Components", or be dropped.
|
|
17
|
+
*/
|
|
18
|
+
export declare function attachTransitionWhen(segments: MatchResult["segments"], ctx: ReturnType<typeof getRequestContext>): MatchResult["segments"];
|
|
@@ -12,6 +12,7 @@ import type { RscPayload } from "./types.js";
|
|
|
12
12
|
import type { HandlerContext } from "./handler-context.js";
|
|
13
13
|
import type { RequestContext } from "../server/request-context.js";
|
|
14
14
|
import type { HandleStore } from "../server/handle-store.js";
|
|
15
|
+
import type { Theme } from "../theme/types.js";
|
|
15
16
|
/**
|
|
16
17
|
* Build the metadata payload for a full (non-partial) document render.
|
|
17
18
|
*
|
|
@@ -20,3 +21,23 @@ import type { HandleStore } from "../server/handle-store.js";
|
|
|
20
21
|
* derived-context store.
|
|
21
22
|
*/
|
|
22
23
|
export declare function buildFullPayload(m: MatchResult, ctx: HandlerContext<any>, url: URL, reqCtx: RequestContext<any>, handleStore: HandleStore): RscPayload;
|
|
24
|
+
/**
|
|
25
|
+
* The theme a document payload carries as `metadata.initialTheme` (the
|
|
26
|
+
* ThemeProvider's first state), read with no identity guard: it is the
|
|
27
|
+
* router's own read, not handler code (#971).
|
|
28
|
+
*
|
|
29
|
+
* A render other visitors may be served carries the no-cookie default, not
|
|
30
|
+
* the rendering visitor's theme: a shell capture, and a render the document
|
|
31
|
+
* cache runs whose response opted in before next() (documentCacheStoresRender,
|
|
32
|
+
* #978). The shell, its ShellCacheEntry.initialTheme and the stored document
|
|
33
|
+
* serve every visitor, and ThemeProvider re-syncs only from an explicitly
|
|
34
|
+
* stored theme, so a visitor with none kept the first visitor's
|
|
35
|
+
* `useTheme().theme` for the page's lifetime. A visitor with a stored theme
|
|
36
|
+
* gets it pre-paint (theme script) and in the provider after mount.
|
|
37
|
+
*
|
|
38
|
+
* Any other render carries the visitor's theme (the unmatched-route 404 reads
|
|
39
|
+
* it without this function, rsc/handler.ts); when that differs from the
|
|
40
|
+
* default it marks `_payloadVisitorTheme`, and the document cache does not
|
|
41
|
+
* store the response.
|
|
42
|
+
*/
|
|
43
|
+
export declare function payloadInitialTheme(reqCtx: Pick<RequestContext<any>, "_themeConfig" | "_shellCaptureRun" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "res">): Theme | undefined;
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { CreateRSCHandlerOptions } from "./types.js";
|
|
8
8
|
import type { RouterRequestInput } from "../router/router-interfaces.js";
|
|
9
|
-
export declare function createRSCHandler<TEnv = unknown, TRoutes extends Record<string, string> = Record<string, string>>(options: CreateRSCHandlerOptions<TEnv, TRoutes>): (
|
|
9
|
+
export declare function createRSCHandler<TEnv = unknown, TRoutes extends Record<string, string> = Record<string, string>>(options: CreateRSCHandlerOptions<TEnv, TRoutes>): (incomingRequest: Request, input?: RouterRequestInput<TEnv>) => Promise<Response>;
|
|
@@ -3,28 +3,27 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Owns the single response-cache contract — cache-scope resolution from the
|
|
5
5
|
* matched entry tree, condition eval, key resolution (route key() > store
|
|
6
|
-
* keyGenerator > default), tag resolution,
|
|
7
|
-
* fresh-hit / SWR-revalidate /
|
|
6
|
+
* keyGenerator > default, CacheScope.resolveKeyFrom), tag resolution,
|
|
7
|
+
* pre-handler-callback timing, and the fresh-hit / SWR-revalidate /
|
|
8
|
+
* miss-write branches — for BOTH the production
|
|
8
9
|
* response-route handler (rsc/response-route-handler.ts) and the dispatch testing
|
|
9
10
|
* primitive (testing/dispatch.ts), so the two can never drift.
|
|
10
11
|
*
|
|
11
12
|
* Plugin-rsc hazard: cache-scope.ts pulls @vitejs/plugin-rsc (via segment-codec),
|
|
12
13
|
* which the non-Vite unit-test runner cannot resolve, and this module is on the
|
|
13
|
-
* testing barrel's EAGER graph (dispatch imports it). So `createCacheScope`
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* testing barrel's EAGER graph (dispatch imports it). So `createCacheScope` is
|
|
15
|
+
* NOT imported here at runtime — it is INJECTED by the caller (production
|
|
16
|
+
* imports it statically; dispatch lazy-imports it only once a response route
|
|
17
|
+
* matches). The only runtime imports here are plugin-rsc-free
|
|
17
18
|
* (helpers' isCacheableStatus/finalizeResponse, traverseBack); cache-scope is a
|
|
18
19
|
* type-only import (erased at build).
|
|
19
20
|
*/
|
|
20
21
|
import type { CacheScope } from "../cache/cache-scope.js";
|
|
21
|
-
import type
|
|
22
|
-
import type { RequestContext } from "../server/request-context.js";
|
|
22
|
+
import { type RequestContext } from "../server/request-context.js";
|
|
23
23
|
import type { EntryCacheConfig, EntryData } from "../server/context.js";
|
|
24
|
-
/** Injected cache-scope
|
|
24
|
+
/** Injected cache-scope builder (kept off this module's runtime import graph). */
|
|
25
25
|
export interface CacheScopeDeps {
|
|
26
26
|
createCacheScope: (config: EntryCacheConfig | undefined, parent?: CacheScope | null) => CacheScope | null;
|
|
27
|
-
resolveCacheTags: (config: PartialCacheOptions | false, ctx: RequestContext | undefined) => string[] | undefined;
|
|
28
27
|
}
|
|
29
28
|
export interface ServeResponseRouteWithCacheArgs {
|
|
30
29
|
reqCtx: RequestContext;
|
|
@@ -40,7 +39,11 @@ export interface ServeResponseRouteWithCacheArgs {
|
|
|
40
39
|
* applies (no scope, disabled, condition false, or store lacks get/putResponse)
|
|
41
40
|
* so the caller falls through to a plain `executeHandler()` run.
|
|
42
41
|
*
|
|
43
|
-
* Must run inside runWithRequestContext (reads the ambient
|
|
44
|
-
* the helpers and reqCtx.waitUntil for background writes).
|
|
42
|
+
* Must run inside runWithRequestContext for `reqCtx` (reads the ambient
|
|
43
|
+
* request context via the helpers and reqCtx.waitUntil for background writes).
|
|
44
|
+
* Outside it, the route runs uncached: the scope resolves `key()`, a store
|
|
45
|
+
* keyGenerator and `condition()` against the ambient context, and without
|
|
46
|
+
* it a keyGenerator was skipped and the entry landed on the broad default
|
|
47
|
+
* key.
|
|
45
48
|
*/
|
|
46
49
|
export declare function serveResponseRouteWithCache(args: ServeResponseRouteWithCacheArgs): Promise<Response | undefined>;
|
|
@@ -31,10 +31,8 @@ export interface BuildShellEntry {
|
|
|
31
31
|
entry: ShellCacheEntry;
|
|
32
32
|
/** Resolved ppr ttl (seconds) — drives staleness/recapture, never expiry. */
|
|
33
33
|
ttl: number;
|
|
34
|
-
swr?: number;
|
|
35
34
|
/** The putShell-barrier tag union baked at build (static + recorded). */
|
|
36
35
|
tags?: string[];
|
|
37
|
-
routeName: string;
|
|
38
36
|
}
|
|
39
37
|
interface ShellManifestModule {
|
|
40
38
|
/** Manifest key (pathname — see shell-manifest-key.ts) -> asset specifier. */
|
|
@@ -46,7 +44,10 @@ interface ShellManifestModule {
|
|
|
46
44
|
declare global {
|
|
47
45
|
var __loadShellManifestModule: (() => Promise<ShellManifestModule>) | undefined;
|
|
48
46
|
}
|
|
49
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Reset the memoized manifest (unit tests swap the global loader) and the
|
|
49
|
+
* shell path's once-per-key warnings, the tag-check one included.
|
|
50
|
+
*/
|
|
50
51
|
export declare function resetBuildShellManifestForTests(): void;
|
|
51
52
|
export interface BuildShellHit {
|
|
52
53
|
entry: DocumentShellCacheEntry;
|
|
@@ -73,6 +74,14 @@ export interface DevShellLookup {
|
|
|
73
74
|
/** Resolved `ppr.captureTimeout` (ms) — the endpoint's capture honors it. */
|
|
74
75
|
captureTimeout?: number;
|
|
75
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Whether a build-time shell exists for `pathname` (the caller checks the
|
|
79
|
+
* request is search-less, like the entries lookupBuildShell serves): a
|
|
80
|
+
* manifest entry for the path in production, a Prerender route in dev. No
|
|
81
|
+
* asset load and no dev capture: it only decides whether a request that
|
|
82
|
+
* cannot read the build shell deserves a warning.
|
|
83
|
+
*/
|
|
84
|
+
export declare function hasBuildShell(pathname: string, dev?: DevShellLookup): Promise<boolean>;
|
|
76
85
|
/**
|
|
77
86
|
* Look up the baked shell entry for a request, applying every serve gate:
|
|
78
87
|
* search-less requests only (the build captured the bare pathname; a
|
|
@@ -1,30 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React-free leaf of the PPR shell path: its constants, the shell key
|
|
3
|
+
* builders, the status header names and bypass reasons, and the once-per-key
|
|
4
|
+
* warning registry. The ssr graph (ssr/index.tsx), the testing barrels
|
|
5
|
+
* (testing/shell-status.ts) and cookie-store.ts import from here without
|
|
6
|
+
* pulling the capture orchestration module or shell-serve.ts (React).
|
|
7
|
+
*/
|
|
8
|
+
import type { SearchParamsFilter } from "../cache/search-params-filter.js";
|
|
1
9
|
/**
|
|
2
10
|
* Default upper bound on the capture prerender wait before forcing the abort
|
|
3
11
|
* that freezes the shell — the ONLY wall-clock on the capture path, and a
|
|
4
12
|
* pathological guard: it should never fire once the caller's `quiesce` is a
|
|
5
13
|
* task-quantized, frozen-byte signal (the capture gate in shell-capture.ts).
|
|
6
|
-
*
|
|
7
|
-
* Leaf module on purpose (imports nothing): shell-capture.ts re-exports it
|
|
8
|
-
* (single import site for the rsc graph — shell-build-manifest.ts sizes the
|
|
9
|
-
* dev fetch envelope from that re-export) and ssr/index.tsx uses it as
|
|
10
|
-
* captureShellHTML's own fallback; the ssr graph must not pull the capture
|
|
11
|
-
* orchestration module for one number.
|
|
14
|
+
* ssr/index.tsx uses it as captureShellHTML's own fallback.
|
|
12
15
|
*
|
|
13
16
|
* 15s, raised from 5s: captures are background work (waitUntil), so the budget
|
|
14
17
|
* costs latency-to-HIT only — never a served response — and 5s spuriously
|
|
15
18
|
* refused legitimately-slow deferred shell material (a real storefront's meta
|
|
16
19
|
* chains settle at ~7s). Ceiling math: workerd's waitUntil lifetime is ~30s
|
|
17
|
-
* past response completion
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* past response completion. An attempt that consumed the whole budget is not
|
|
21
|
+
* retried in place (shell-capture.ts CaptureAttemptStats.noShellCause), so
|
|
22
|
+
* the envelope is one budget plus store I/O; the retry follows only an
|
|
23
|
+
* attempt that ended early (a cold-module abort). Past the ceiling the
|
|
24
|
+
* platform kill degrades to the existing best-effort contract (the key stays
|
|
25
|
+
* MISS; a later request re-captures).
|
|
23
26
|
* Node/dev and build-time captures have no waitUntil ceiling. The per-route
|
|
24
27
|
* `ppr.captureTimeout` knob remains for tightening below the default. See
|
|
25
28
|
* docs/design/ppr-shell-resume.md (Cost model).
|
|
26
29
|
*/
|
|
27
30
|
export declare const SHELL_CAPTURE_MAX_WAIT_MS = 15000;
|
|
31
|
+
/** Debug/status header on a ppr document response: `HIT` | `MISS`. */
|
|
32
|
+
export declare const SHELL_STATUS_HEADER: string;
|
|
33
|
+
/**
|
|
34
|
+
* Partial-navigation replay status header, set only after the captured
|
|
35
|
+
* segment record was consumed (`HIT`) or with the reason it was not.
|
|
36
|
+
*/
|
|
37
|
+
export declare const PPR_REPLAY_STATUS_HEADER: string;
|
|
38
|
+
/**
|
|
39
|
+
* Bounded reasons a partial request to a ppr route falls open to the ordinary
|
|
40
|
+
* match (`x-rango-ppr-replay: BYPASS; reason=<reason>`). One list for the
|
|
41
|
+
* producer (rsc-rendering.ts) and the parser (testing/shell-status.ts): a
|
|
42
|
+
* reason the parser does not list parses as null.
|
|
43
|
+
*/
|
|
44
|
+
export declare const PPR_REPLAY_BYPASS_REASONS: readonly ["method", "dynamic", "nonce", "store-unavailable", "passive-read-unsupported", "no-navigation-context", "prerender-store", "intercept", "cache-disabled", "read-error", "no-entry", "invalid-version", "corrupt-entry", "no-segment-snapshot", "snapshot-miss", "explicit-cache-hit"];
|
|
45
|
+
/** One of {@link PPR_REPLAY_BYPASS_REASONS}. */
|
|
46
|
+
export type PprReplayBypassReason = (typeof PPR_REPLAY_BYPASS_REASONS)[number];
|
|
47
|
+
/**
|
|
48
|
+
* The shell key's search portion (`?`-prefixed sorted search with the
|
|
49
|
+
* cache.searchParams filter applied, or "") — ALSO the string the capture and
|
|
50
|
+
* resume SSR renders seed their store location with (SSRRenderOptions.search
|
|
51
|
+
* / ShellCaptureOptions.search / ShellResumeOptions.search). Search is part
|
|
52
|
+
* of shell identity, so static-part `useSearchParams` reads render exactly
|
|
53
|
+
* what the key names; deriving seed and key from this one helper is what
|
|
54
|
+
* keeps capture, resume, and lookup byte-agreed (drift = replay mismatch or
|
|
55
|
+
* permanent MISS).
|
|
56
|
+
*/
|
|
57
|
+
export declare function shellSearchSeed(url: URL, filter?: SearchParamsFilter): string;
|
|
58
|
+
/**
|
|
59
|
+
* Shell cache key: host + pathname + sorted search + a `:shell` namespace suffix
|
|
60
|
+
* (so it can never collide with a document-cache key; the store further isolates
|
|
61
|
+
* the shell family internally).
|
|
62
|
+
*
|
|
63
|
+
* The key includes the request HOST: in a multi-tenant host-router deployment
|
|
64
|
+
* (one worker, one shared KV/runtime-cache store) a host-less key would serve
|
|
65
|
+
* tenant A's captured shell to tenant B's users.
|
|
66
|
+
*
|
|
67
|
+
* `filter` is the request's compiled `cache.searchParams` config
|
|
68
|
+
* (ctx._searchParamsFilter): excluded params collapse onto one shell slot.
|
|
69
|
+
* Callers on the serve/capture path MUST pass it -- key drift between capture
|
|
70
|
+
* and lookup makes every shell request a permanent miss. The testing helper
|
|
71
|
+
* `shellCacheKey` (testing/shell-status.ts) builds its key with it too.
|
|
72
|
+
*/
|
|
73
|
+
export declare function buildShellKey(url: URL, filter?: SearchParamsFilter): string;
|
|
74
|
+
/**
|
|
75
|
+
* The shell key for one request partition (cache-scope.ts
|
|
76
|
+
* resolveShellPartition): the route cache() `key()` or store keyGenerator
|
|
77
|
+
* result that partitions the route's record partitions its shell too, so
|
|
78
|
+
* each partition captures and serves its own.
|
|
79
|
+
*
|
|
80
|
+
* The partition is URI-encoded: it is request-derived, and raw it could end
|
|
81
|
+
* in a suffix another key is built with (navigationShellKey), so a partition
|
|
82
|
+
* `gold:navigation` named gold's navigation entry and its document shell
|
|
83
|
+
* replayed to gold's navigations. Encoded, it holds no `:` or `|`.
|
|
84
|
+
*/
|
|
85
|
+
export declare function partitionShellKey(key: string, partition: string): string;
|
|
86
|
+
/**
|
|
87
|
+
* The navigation-only entry beside a document shell key (a cold partial
|
|
88
|
+
* request's capture, rsc-rendering.ts). A suffix after the (encoded)
|
|
89
|
+
* partition: partitionShellKey keeps the two unambiguous.
|
|
90
|
+
*/
|
|
91
|
+
export declare function navigationShellKey(key: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* Fixed number of macrotask hops between `quiesce` resolving and the abort. These
|
|
94
|
+
* give React's fizz worker turns to flush the settled shell into the prelude and
|
|
95
|
+
* mark still-pending boundaries as POSTPONED (rather than errored) before
|
|
96
|
+
* controller.abort() lands. Not a wall-clock wait. Taken by captureShellHTML
|
|
97
|
+
* (ssr/index.tsx) and by the testing SSR stub (testing/serve-shell-request.ts),
|
|
98
|
+
* so the stub freezes the same Flight the real capture would.
|
|
99
|
+
*
|
|
100
|
+
* Why 16 and not 2: the capture's Flight input is the doc record's stored
|
|
101
|
+
* fragments (settleCaptureRecord, shell-capture.ts), already serialized, so the
|
|
102
|
+
* render emits the whole shell payload in the first tick and the gate declares
|
|
103
|
+
* quiesce within a few ms, before fizz has rendered the shell to <body>. When
|
|
104
|
+
* the capture Flight dribbled out as handlers ran, Flight-quiet meant "the shell
|
|
105
|
+
* has rendered" and 2 hops sufficed.
|
|
106
|
+
*
|
|
107
|
+
* Hops alone are NOT render-readiness: fizz cannot emit even <html> until the
|
|
108
|
+
* payload root settles, nor complete a shell whose client components are
|
|
109
|
+
* still loading — real module-runner I/O in dev (100ms+ cold), which no fixed
|
|
110
|
+
* count of near-zero-cost task hops can buy. captureShellHTML therefore
|
|
111
|
+
* awaits the payload-settled signal (SsrRootOptions.onPayloadSettled) and
|
|
112
|
+
* then the client-reference loads in flight in the isolate (captureClientLoads),
|
|
113
|
+
* deadline-bounded, between quiesce and these hops; the hops then only flush
|
|
114
|
+
* the settled tree and mark pending boundaries POSTPONED. Still task-based
|
|
115
|
+
* (masked loaders never emit, so more hops never lets a hole settle). Bounded
|
|
116
|
+
* by maxWaitMs end to end.
|
|
117
|
+
*/
|
|
118
|
+
export declare const POST_QUIESCE_TASK_HOPS = 16;
|
|
28
119
|
/**
|
|
29
120
|
* Hard cap on one capture TASK — runShellCapture end to end (both attempts +
|
|
30
121
|
* the in-place retry delay). SHELL_CAPTURE_MAX_WAIT_MS arms only inside
|
|
@@ -50,3 +141,16 @@ export declare const SHELL_CAPTURE_TASK_HARD_CAP_MS = 25000;
|
|
|
50
141
|
* rule: resolveLoaderData (router/segment-resolution/loader-cache.ts).
|
|
51
142
|
*/
|
|
52
143
|
export declare const PPR_LANE_HINT: string;
|
|
144
|
+
/** Whether {@link warnOnce} already warned for `scope` and `key`. */
|
|
145
|
+
export declare function hasWarnedOnce(scope: string, key: string): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* `console.warn(message())` once per `scope` and `key`; `message` is built only
|
|
148
|
+
* when it prints. Returns true when it warned.
|
|
149
|
+
*/
|
|
150
|
+
export declare function warnOnce(scope: string, key: string, message: () => string): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* @internal Forget every once-per-key shell warning. Tests only: the capture,
|
|
153
|
+
* serve and build-shell resets (testing/serve-shell-request.ts
|
|
154
|
+
* resetShellTestState) call it.
|
|
155
|
+
*/
|
|
156
|
+
export declare function resetShellWarningsForTests(): void;
|