@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
|
@@ -16,12 +16,8 @@
|
|
|
16
16
|
* intent cannot be honored — unlike an undeclared route, which is silent).
|
|
17
17
|
*/
|
|
18
18
|
import { type EntryData } from "../server/context.js";
|
|
19
|
-
import type {
|
|
20
|
-
|
|
21
|
-
/** Debug/status header the browser (and e2e assertions) can read: HIT | MISS. */
|
|
22
|
-
export declare const SHELL_STATUS_HEADER = "x-rango-shell";
|
|
23
|
-
/** Partial-navigation status header set only after captured PPR segments are consumed. */
|
|
24
|
-
export declare const PPR_REPLAY_STATUS_HEADER = "x-rango-ppr-replay";
|
|
19
|
+
import type { DocumentShellCacheEntry, ShellCacheEntry, ShellDocumentRead, ShellEntryHead, ShellReadStats, ShellSnapshotFailure, ShellSnapshotRecord, SegmentCacheStore } from "../cache/types.js";
|
|
20
|
+
export { PPR_REPLAY_STATUS_HEADER, SHELL_STATUS_HEADER, buildShellKey, navigationShellKey, partitionShellKey, shellSearchSeed, } from "./shell-capture-constants.js";
|
|
25
21
|
/**
|
|
26
22
|
* Default shell ttl (seconds) for `ppr: true` and for a PartialPrerenderProps
|
|
27
23
|
* that omits `ttl`.
|
|
@@ -80,53 +76,56 @@ export declare function normalizeCaptureTimeout(value: unknown): number | undefi
|
|
|
80
76
|
*/
|
|
81
77
|
export declare function resolvePprConfig(entry: EntryData | undefined | null): ResolvedPprConfig | null;
|
|
82
78
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
79
|
+
* The forced-MISS query marker. A document HIT that cannot finish its tail
|
|
80
|
+
* reloads the page with it (shellReloadScript); the serve gate renders a
|
|
81
|
+
* request carrying it on axis 1, with no shell read and no capture, so the
|
|
82
|
+
* reload can never be a HIT that degrades again. The handler drops it from
|
|
83
|
+
* the request on entry (withoutShellMissMarker) and keeps only the flag
|
|
84
|
+
* (RequestContext._shellForcedMiss), so nothing else sees it.
|
|
85
|
+
*/
|
|
86
|
+
export declare const SHELL_MISS_PARAM: string;
|
|
87
|
+
/**
|
|
88
|
+
* The request without the forced-MISS marker, or undefined when it carries
|
|
89
|
+
* none. The handler calls it before anything reads the request: left in, the
|
|
90
|
+
* marker reached `ctx.request.url`, `originalUrl`, middleware, and the SSR
|
|
91
|
+
* search seed (so `useSearchParams` rendered it), and a `"use cache"` key
|
|
92
|
+
* built from the request URL was never read again. GET and HEAD only: the
|
|
93
|
+
* reload is a navigation, and a request with a body cannot be re-created
|
|
94
|
+
* without re-streaming it. The substring test keeps the URL parse off every
|
|
95
|
+
* other request.
|
|
95
96
|
*/
|
|
96
|
-
export declare function
|
|
97
|
+
export declare function withoutShellMissMarker(request: Request): Request | undefined;
|
|
97
98
|
/**
|
|
98
|
-
* The
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* permanent MISS).
|
|
99
|
+
* The inline script a degraded document HIT ends with: reload once into a
|
|
100
|
+
* forced MISS. The marker in the URL is the loop bound — a request carrying
|
|
101
|
+
* it is never a HIT, so this script never runs on the reload, and if it ever
|
|
102
|
+
* did (a server that ignores the marker) it would return without touching
|
|
103
|
+
* the page. window.stop() runs only when it reloads: it keeps the half-sent
|
|
104
|
+
* Flight stream from being closed by DOMContentLoaded, which would throw
|
|
105
|
+
* React's "Connection closed" (#412) before the reload lands.
|
|
106
106
|
*/
|
|
107
|
-
export declare function
|
|
107
|
+
export declare function shellReloadScript(): string;
|
|
108
|
+
/**
|
|
109
|
+
* An inline script a shell HIT's tail appends. It carries no CSP nonce: a
|
|
110
|
+
* request with an active per-request nonce never reaches a HIT
|
|
111
|
+
* (rsc-rendering.ts shellServePlan serves it on axis 1).
|
|
112
|
+
*/
|
|
113
|
+
export declare function inlineShellScript(body: string): string;
|
|
108
114
|
/**
|
|
109
115
|
* Version gates for a stored shell: reactVersion AND buildVersion must both
|
|
110
116
|
* match the running server. The postponed blob encodes hole positions against
|
|
111
117
|
* one exact tree, so resuming it under a different React OR a different app
|
|
112
118
|
* build tree-mismatches inside resume() — after the 200 + prelude committed,
|
|
113
119
|
* with no recovery. Either mismatch is a miss: the recapture overwrites the
|
|
114
|
-
* same key (self-healing) and the entry otherwise ages out via TTL.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* full static prelude flushed (`serveShellHit` decodes at stream construction,
|
|
124
|
-
* `resumeShellHTML` parses in the tail) — the client gets a visually complete
|
|
125
|
-
* page that never hydrates, re-served on every request until the entry ages
|
|
126
|
-
* out (no eviction path exists; failure schedules no recapture by itself).
|
|
127
|
-
* Checking here turns a corrupt entry (store-layer fault) into a plain MISS
|
|
128
|
-
* the recapture overwrites. Cost: one duplicate decode/parse per HIT, sub-ms
|
|
129
|
-
* against a prelude flush that dominates the path.
|
|
120
|
+
* same key (self-healing) and the entry otherwise ages out via TTL.
|
|
121
|
+
*/
|
|
122
|
+
export declare function isValidShellHit(entry: Pick<ShellCacheEntry, "reactVersion" | "buildVersion">, buildVersion: string): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* DOCUMENT-half structural gate and type narrowing, without decoding the
|
|
125
|
+
* prelude: the prelude is a string and the postponed blob parses. Partial
|
|
126
|
+
* replay (which never serves the prelude) and the build-manifest read-through
|
|
127
|
+
* use it as-is; the document HIT path runs it inside
|
|
128
|
+
* {@link openShellDocument}, whose single decode is the prelude's check.
|
|
130
129
|
*
|
|
131
130
|
* navigationOnly entries store no document half (prelude/postponed absent) and
|
|
132
131
|
* therefore never pass. The partial-replay path skips this gate for them
|
|
@@ -135,8 +134,47 @@ export declare function isValidShellHit(entry: ShellCacheEntry, buildVersion: st
|
|
|
135
134
|
* capture).
|
|
136
135
|
*/
|
|
137
136
|
export declare function hasIntactShellPayload(entry: ShellCacheEntry): entry is DocumentShellCacheEntry;
|
|
138
|
-
/**
|
|
139
|
-
export
|
|
137
|
+
/** A document shell ready to serve: its prelude decoded exactly once. */
|
|
138
|
+
export interface ShellDocument {
|
|
139
|
+
entry: ShellEntryHead;
|
|
140
|
+
prelude: Uint8Array;
|
|
141
|
+
/** React's postponed state, parse-checked (null = DATA variant). */
|
|
142
|
+
postponed: string | null;
|
|
143
|
+
/**
|
|
144
|
+
* The capture snapshot: on the entry, or still arriving on its own promise
|
|
145
|
+
* after a prelude-first read (SegmentCacheStore.readShellDocument), which
|
|
146
|
+
* only the tail awaits.
|
|
147
|
+
*/
|
|
148
|
+
snapshot: ShellSnapshotRecord[] | Promise<ShellSnapshotRecord[] | undefined>;
|
|
149
|
+
/** Why a prelude-first read's snapshot is missing (ShellDocumentRead). */
|
|
150
|
+
snapshotFailure?: Promise<ShellSnapshotFailure | undefined>;
|
|
151
|
+
/** The prelude-first read's stats, when perf metrics are on. */
|
|
152
|
+
stats?: ShellReadStats;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Pre-commit integrity gate for a document HIT, and its only prelude decode.
|
|
156
|
+
* A stored entry whose prelude is not decodable base64 or whose postponed blob
|
|
157
|
+
* is not parseable JSON would otherwise throw AFTER the 200 + full static
|
|
158
|
+
* prelude flushed (`resumeShellHTML` parses in the tail) — the client gets a
|
|
159
|
+
* visually complete page that never hydrates, re-served on every request
|
|
160
|
+
* until the entry ages out. Returning null here turns a corrupt entry
|
|
161
|
+
* (store-layer fault) into a plain MISS the recapture overwrites. The decoded
|
|
162
|
+
* bytes are what serveShellHit enqueues, so the check costs no second decode.
|
|
163
|
+
* A prelude-first `read` (SegmentCacheStore.readShellDocument) already carries
|
|
164
|
+
* the raw bytes and a pending snapshot, so only its postponed blob is checked.
|
|
165
|
+
*/
|
|
166
|
+
export declare function openShellDocument(entry: ShellCacheEntry): ShellDocument | null;
|
|
167
|
+
export declare function openShellDocument(entry: ShellEntryHead, read: Pick<ShellDocumentRead, "prelude" | "snapshot" | "snapshotFailure" | "stats">): ShellDocument | null;
|
|
168
|
+
/**
|
|
169
|
+
* Prelude enqueue granularity. A streaming compressor in front of the worker
|
|
170
|
+
* emits its first byte only after compressing the whole write it was handed:
|
|
171
|
+
* one 629 KB enqueue delayed the first compressed byte by the full prelude's
|
|
172
|
+
* compression time (brotli-6 5.1 ms, gzip-6 1.1 ms in Node zlib with a flush
|
|
173
|
+
* per write; workerd's CompressionStream emits nothing until the whole write is
|
|
174
|
+
* compressed), while 32 KB chunks emit within 0.1 ms and cost slightly more
|
|
175
|
+
* in total compression (0.55-0.70 ms) than one write (issue #941).
|
|
176
|
+
*/
|
|
177
|
+
export declare const SHELL_PRELUDE_CHUNK_BYTES: number;
|
|
140
178
|
/** True when the store implements the shell entry family. */
|
|
141
179
|
export declare function hasShellFamily(store: SegmentCacheStore | undefined): store is SegmentCacheStore & {
|
|
142
180
|
getShell: NonNullable<SegmentCacheStore["getShell"]>;
|
|
@@ -152,8 +190,22 @@ export declare function hasShellFamily(store: SegmentCacheStore | undefined): st
|
|
|
152
190
|
export interface ShellTailTiming {
|
|
153
191
|
key: string;
|
|
154
192
|
outcome: "complete" | "redirect" | "error";
|
|
193
|
+
/** The capture snapshot available to the tail (read and parsed). */
|
|
194
|
+
snapshotMs?: number;
|
|
195
|
+
/** Snapshot bytes read after the commit (prelude-first stores). */
|
|
196
|
+
snapshotBytes?: number;
|
|
197
|
+
/** Snapshot bytes read after the commit, excluding the parse. */
|
|
198
|
+
snapshotReadMs?: number;
|
|
199
|
+
/** Snapshot JSON.parse CPU (reads 0 on a deployed worker: see bytes). */
|
|
200
|
+
snapshotParseMs?: number;
|
|
201
|
+
/** Snapshot records by family, e.g. `segment:1/loader:2` (no commas: it rides a Server-Timing desc). */
|
|
202
|
+
snapshotRecords?: string;
|
|
203
|
+
/** Records the capture pruned from the snapshot, same format (ShellCacheEntry.prunedRecords). */
|
|
204
|
+
snapshotPruned?: string;
|
|
155
205
|
/** Loader-family seed decode (only when the entry carried a snapshot). */
|
|
156
206
|
seedMs?: number;
|
|
207
|
+
/** The seed decode's own duration: Flight deserialization, CPU only. */
|
|
208
|
+
seedCpuMs?: number;
|
|
157
209
|
/** Tail router.match() settled. */
|
|
158
210
|
matchMs?: number;
|
|
159
211
|
/** Tail stream (resume output) handed to the response stream. */
|
|
@@ -168,12 +220,13 @@ export interface ShellTailTiming {
|
|
|
168
220
|
tailBytes?: number;
|
|
169
221
|
}
|
|
170
222
|
/**
|
|
171
|
-
* Compact single-line form for the console log and the
|
|
172
|
-
*
|
|
173
|
-
* escaping needed.
|
|
223
|
+
* Compact single-line form for the console log and the Server-Timing mirror's
|
|
224
|
+
* `desc`: alphanumerics and `=`, `-`, `:`, `/` only (records=segment:1/loader:2 pruned=loader:1),
|
|
225
|
+
* so no quoted-string escaping is needed. Offsets are from the commit; the
|
|
226
|
+
* `-cpu` fields are CPU-only durations.
|
|
174
227
|
*/
|
|
175
228
|
export declare function describeShellTailTiming(timing: ShellTailTiming): string;
|
|
176
|
-
/** Buffer one terminal tail timing for the
|
|
229
|
+
/** Buffer one terminal tail timing for the Server-Timing mirror. */
|
|
177
230
|
export declare function publishShellTailTiming(timing: ShellTailTiming): void;
|
|
178
231
|
/**
|
|
179
232
|
* Consume (read-and-clear) the buffered tail timing for `key`, so one tail
|
|
@@ -198,3 +251,44 @@ export declare function warnShellStoreMissingOnce(key: string): void;
|
|
|
198
251
|
* the missing-store warning above (an undeclared route stays silent).
|
|
199
252
|
*/
|
|
200
253
|
export declare function warnPprNonceActiveOnce(key: string): void;
|
|
254
|
+
/**
|
|
255
|
+
* Dev only (the caller gates on NODE_ENV): warn once per route that the
|
|
256
|
+
* route's cache() entry reduces an explicit `ppr.ttl` or `ppr.swr`. `shell`
|
|
257
|
+
* is what the capture stores for a record written just now
|
|
258
|
+
* (shell-capture.ts capShellWindow), so the message states the values the
|
|
259
|
+
* shell actually gets. A ppr value the cap leaves whole (or raises: the
|
|
260
|
+
* cap can move a record's stale time into the shell's swr) is silent, and
|
|
261
|
+
* so is a ppr config that sets no ttl/swr.
|
|
262
|
+
*/
|
|
263
|
+
export declare function warnPprWindowCappedOnce(routeName: string, ppr: {
|
|
264
|
+
ttl?: number;
|
|
265
|
+
swr?: number;
|
|
266
|
+
}, shell: {
|
|
267
|
+
ttl: number;
|
|
268
|
+
swr: number;
|
|
269
|
+
}, cache: {
|
|
270
|
+
ttl: number;
|
|
271
|
+
swr: number;
|
|
272
|
+
}): void;
|
|
273
|
+
/**
|
|
274
|
+
* Whether a partitioned request needs no build-shell probe: its route was
|
|
275
|
+
* already warned, or its path was already found without one.
|
|
276
|
+
*/
|
|
277
|
+
export declare function partitionBuildShellCheckDone(pathname: string, routeName: string | undefined): boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Record a partitioned request's build-shell probe, and warn once per route
|
|
280
|
+
* when it found one: the route has a build-time shell its requests cannot
|
|
281
|
+
* read. The route's request partition (a `cache({ key })` enclosing it, at
|
|
282
|
+
* any depth (#970), or the store's keyGenerator) keys the shell per
|
|
283
|
+
* partition, and the build captured only
|
|
284
|
+
* the default one, so each partition captures at runtime. Same
|
|
285
|
+
* declared-intent-cannot-be-honored doctrine as the warnings above; a path
|
|
286
|
+
* with no build shell stays silent.
|
|
287
|
+
*/
|
|
288
|
+
export declare function notePartitionBuildShellCheck(pathname: string, routeName: string | undefined, found: boolean): void;
|
|
289
|
+
/**
|
|
290
|
+
* @internal Reset the serve path's once-per-key warnings (the shell path's
|
|
291
|
+
* one registry), its build-shell probe memo and buffered tail timings. Tests
|
|
292
|
+
* only (testing/serve-shell-request.ts resetShellTestState).
|
|
293
|
+
*/
|
|
294
|
+
export declare function resetShellServeStateForTests(): void;
|
|
@@ -32,6 +32,8 @@ export interface RscPayload {
|
|
|
32
32
|
resolvedIds?: string[];
|
|
33
33
|
/** Merged route params from the matched route */
|
|
34
34
|
params?: Record<string, string>;
|
|
35
|
+
/** Matched route name, when named (transition({ when }) route names). */
|
|
36
|
+
routeName?: string;
|
|
35
37
|
slots?: Record<string, SlotState>;
|
|
36
38
|
/**
|
|
37
39
|
* Intercept TARGET route names reachable from this location as a
|
|
@@ -208,6 +210,13 @@ export interface SSRModule {
|
|
|
208
210
|
origin?: string;
|
|
209
211
|
/** Each component error the prerender reports (never the capture's own abort). */
|
|
210
212
|
onError?: (error: unknown) => void;
|
|
213
|
+
/**
|
|
214
|
+
* React's errorInfo for each task still pending at the capture's abort
|
|
215
|
+
* (its componentStack is computed when read).
|
|
216
|
+
*/
|
|
217
|
+
onAbortedTask?: (errorInfo: {
|
|
218
|
+
componentStack?: string;
|
|
219
|
+
} | undefined) => void;
|
|
211
220
|
}) => Promise<{
|
|
212
221
|
prelude: Uint8Array;
|
|
213
222
|
postponed: string | null;
|
|
@@ -19,6 +19,13 @@ export interface RenderSegmentsOptions {
|
|
|
19
19
|
forceAwait?: boolean;
|
|
20
20
|
/** Seeded descendant client-route pending state for testing. */
|
|
21
21
|
outletPending?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* This commit's transition({ when }) decision was false
|
|
24
|
+
* (browser/transition-when.ts): the navigation is urgent, so no segment
|
|
25
|
+
* animates. Every router <ViewTransition> stays in the tree with each class
|
|
26
|
+
* "none", so the element type never changes; keys never read this (#995).
|
|
27
|
+
*/
|
|
28
|
+
transitionGatedOff?: boolean;
|
|
22
29
|
/**
|
|
23
30
|
* Intercept segments to inject into the tree.
|
|
24
31
|
* These are parallel segments from intercept routes that need to be
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { ServerRouteLocation } from "../types/segments.js";
|
|
1
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
3
|
import type { ReactNode } from "react";
|
|
3
4
|
import type { PartialCacheOptions, ErrorBoundaryHandler, Handler, LoaderDefinition, MiddlewareFn, NotFoundBoundaryHandler, ShouldRevalidateFn, TransitionConfig } from "../types";
|
|
4
|
-
import type { DefaultRouteName } from "../types/global-namespace.js";
|
|
5
5
|
import type { ContextVar } from "../context-var.js";
|
|
6
6
|
/**
|
|
7
7
|
* Performance metric entry for a single measured operation
|
|
@@ -106,6 +106,15 @@ export type LoaderEntry = {
|
|
|
106
106
|
* appears on navigation-lane entries.
|
|
107
107
|
*/
|
|
108
108
|
awaitBeforeFlush?: true;
|
|
109
|
+
/**
|
|
110
|
+
* loader(Def, { ssr: false }) on every DSL evaluation, document and
|
|
111
|
+
* navigation: the loader's PPR bake lane (loader-cache.ts
|
|
112
|
+
* resolveLoaderData). The bake/seed key rides on it, so a client
|
|
113
|
+
* navigation's shell replay pins exactly the loaders a document HIT pins,
|
|
114
|
+
* whatever the entry's loading(). awaitBeforeFlush cannot carry that: a
|
|
115
|
+
* navigation evaluation never has it.
|
|
116
|
+
*/
|
|
117
|
+
bake?: true;
|
|
109
118
|
};
|
|
110
119
|
/**
|
|
111
120
|
* Segments state for intercept context
|
|
@@ -123,20 +132,22 @@ export type InterceptSegmentsState = {
|
|
|
123
132
|
* Context passed to intercept selector functions (when())
|
|
124
133
|
* Contains navigation context to determine if interception should occur.
|
|
125
134
|
*
|
|
135
|
+
* `from` / `to` have the shape transition({ when }) sees, without `state`:
|
|
136
|
+
* history state never reaches the server.
|
|
137
|
+
*
|
|
126
138
|
* Note: when() is evaluated during route matching, BEFORE middleware runs.
|
|
127
139
|
* So ctx.get()/ctx.use() are not available, but env (platform bindings) is.
|
|
128
140
|
*
|
|
129
141
|
* @internal This type is an implementation detail and may change without notice.
|
|
130
142
|
*/
|
|
131
143
|
export type InterceptSelectorContext<TEnv = any> = {
|
|
132
|
-
from:
|
|
133
|
-
|
|
134
|
-
|
|
144
|
+
/** Where the navigation comes from: the intercept source while one is open. */
|
|
145
|
+
from: ServerRouteLocation;
|
|
146
|
+
/** The navigation target. */
|
|
147
|
+
to: ServerRouteLocation;
|
|
135
148
|
request: Request;
|
|
136
149
|
env: TEnv;
|
|
137
150
|
segments: InterceptSegmentsState;
|
|
138
|
-
fromRouteName?: DefaultRouteName;
|
|
139
|
-
toRouteName?: DefaultRouteName;
|
|
140
151
|
};
|
|
141
152
|
/**
|
|
142
153
|
* Selector function for conditional interception
|
|
@@ -408,24 +419,130 @@ export declare function getParallelSlotCount(parallels: ParallelEntries | EntryD
|
|
|
408
419
|
export declare function track(label: string, depth?: number): () => void;
|
|
409
420
|
/**
|
|
410
421
|
* Check if the current execution is inside a cache() DSL boundary.
|
|
411
|
-
* Returns false inside loader execution
|
|
412
|
-
*
|
|
422
|
+
* Returns false inside loader execution: a route cache() does not store
|
|
423
|
+
* loader values, so non-cacheable reads are safe. A loader bound with its own
|
|
424
|
+
* cache() stores its value; recordLoaderIdentityRead guards that.
|
|
413
425
|
*/
|
|
414
426
|
export declare function isInsideCacheScope(): boolean;
|
|
415
427
|
/**
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
428
|
+
* What a refused identity read says (guardIdentityRead): its `verb`, and per
|
|
429
|
+
* refusing scope the text after "<surface> cannot be <verb> ...": why the
|
|
430
|
+
* value must not reach that scope, and what to do instead. `fix.warning` is
|
|
431
|
+
* the fix the capture's refusal warning gives (shell-capture.ts
|
|
432
|
+
* refuseOnCaptureGuard).
|
|
433
|
+
*/
|
|
434
|
+
export interface IdentityReadWording {
|
|
435
|
+
/** "called" for a function (cookies(), ctx.get()), "read" for a property (the theme getters). */
|
|
436
|
+
verb: LoaderIdentityReadVerb;
|
|
437
|
+
fix: {
|
|
438
|
+
useCache: string;
|
|
439
|
+
cacheScope: string;
|
|
440
|
+
capture: string;
|
|
441
|
+
warning: string;
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* False when the read is recorded later, by the returned view's read
|
|
445
|
+
* methods (cookies(), headers()): a view taken outside a loader and read
|
|
446
|
+
* inside one still counts, and a cookie write alone is not a read.
|
|
447
|
+
*/
|
|
448
|
+
record?: false;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* The one guard every request-identity read goes through: cookies(),
|
|
452
|
+
* headers(), the theme reads (cookie-store.ts readGuardedTheme), a
|
|
453
|
+
* non-cacheable ctx.get() (assertNonCacheableReadAllowed), and the raw reads
|
|
454
|
+
* `ctx.request.headers` and `getRequestContext().cookie()` / `.cookies()`
|
|
455
|
+
* (cookie-store.ts guardRequestHeaders, guardRawCookieRead; #976). Each surface keeps
|
|
456
|
+
* its own wording; the ladder and its exemptions are shared, so the surfaces
|
|
457
|
+
* refuse in exactly the same places:
|
|
419
458
|
*
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
425
|
-
*
|
|
426
|
-
*
|
|
459
|
+
* 0. A cache's own key(), store keyGenerator, condition() and tags(), and
|
|
460
|
+
* onError, read freely and record nothing (runIdentityExempt,
|
|
461
|
+
* cache/cache-exec-scope.ts): the value picks or labels the entry, or is
|
|
462
|
+
* only observed; it is never rendered. A cached body, loader body or
|
|
463
|
+
* funnel they start is guarded again.
|
|
464
|
+
* 1. A PPR shell capture (`ctx` is the capture's derived context,
|
|
465
|
+
* `_shellCaptureRun`) trips first: the capture context is flagged (so a
|
|
466
|
+
* caught throw still refuses the capture) and the read throws. The shell is
|
|
467
|
+
* shared per host+URL, and every HIT replays what the capture read. There
|
|
468
|
+
* is no loader-body exemption here: a bake-lane loader and a loader a
|
|
469
|
+
* handler awaits both bake.
|
|
470
|
+
* 2. A "use cache" body throws: the key does not include the value, so the
|
|
471
|
+
* first caller's would be stored and served to later callers. That holds
|
|
472
|
+
* for a loader body entered inside the cached function too (`await
|
|
473
|
+
* ctx.use(Loader)` there): its value is part of what the function returns.
|
|
474
|
+
* Before, a non-cacheable ctx.get() there was exempt while cookies() threw,
|
|
475
|
+
* and the entry stored the first request's value.
|
|
476
|
+
* 3. A cache() boundary throws, except inside a loader body
|
|
477
|
+
* (isInsideCacheScope): a route cache() never stores loader values.
|
|
478
|
+
* 4. The read is allowed, and recorded on the current loader execution for a
|
|
479
|
+
* loader cache() fill without key() (#972, recordLoaderIdentityRead)
|
|
480
|
+
* unless `wording.record` defers it to the returned view.
|
|
481
|
+
*
|
|
482
|
+
* Outside these scopes every read is allowed, a live loader's included. The
|
|
483
|
+
* response directives (invalidateClientCache(), keepClientCache()) record
|
|
484
|
+
* nothing and are not captured reads: they take refuseInCacheScope alone.
|
|
485
|
+
*/
|
|
486
|
+
export declare function guardIdentityRead(ctx: unknown, surface: string, wording: IdentityReadWording): void;
|
|
487
|
+
/**
|
|
488
|
+
* Steps 2 and 3 of guardIdentityRead: throw when a "use cache" body or a
|
|
489
|
+
* cache() boundary would store what `surface` produces.
|
|
490
|
+
*/
|
|
491
|
+
export declare function refuseInCacheScope(surface: string, { verb, fix }: IdentityReadWording): void;
|
|
492
|
+
/**
|
|
493
|
+
* The capture refusal for a request-scoped read (cookies(), headers(), a
|
|
494
|
+
* { cache: false } variable): the message after the surface, and the fix the
|
|
495
|
+
* refusal warning gives. `what` names the data that would leak.
|
|
427
496
|
*/
|
|
428
|
-
export declare function
|
|
497
|
+
export declare function requestReadCaptureFix(what: string): Pick<IdentityReadWording["fix"], "capture" | "warning">;
|
|
498
|
+
/**
|
|
499
|
+
* Read guard for a non-cacheable variable (`createVar({ cache: false })` or a
|
|
500
|
+
* `ctx.set(..., { cache: false })` write), through guardIdentityRead.
|
|
501
|
+
* Callers check isNonCacheable() first so ordinary reads never reach the
|
|
502
|
+
* scope lookups. `requestCtx` is the ambient request context, whose capture
|
|
503
|
+
* flag the guard reads.
|
|
504
|
+
*/
|
|
505
|
+
export declare function assertNonCacheableReadAllowed(keyOrVar: string | ContextVar<unknown>, requestCtx?: unknown): void;
|
|
506
|
+
/** How the identity error words a read: a function call or a property read. */
|
|
507
|
+
export type LoaderIdentityReadVerb = "called" | "read";
|
|
508
|
+
/** A request-identity read a loader execution made (recordLoaderIdentityRead). */
|
|
509
|
+
export interface LoaderIdentityRead {
|
|
510
|
+
/**
|
|
511
|
+
* The read as the error names it: "cookies()", "headers()",
|
|
512
|
+
* `ctx.get() for a non-cacheable variable "x"`, "ctx.theme" or
|
|
513
|
+
* "getRequestContext().theme".
|
|
514
|
+
*/
|
|
515
|
+
surface: string;
|
|
516
|
+
/** "called" for a function, "read" for a property (the theme getters). */
|
|
517
|
+
verb: LoaderIdentityReadVerb;
|
|
518
|
+
/** The loader body that made the read. */
|
|
519
|
+
bodyId: string | undefined;
|
|
520
|
+
/**
|
|
521
|
+
* The cached loader whose value carries a read another loader made
|
|
522
|
+
* (loader-cache.ts identity mark): its readers read it through `via`.
|
|
523
|
+
*/
|
|
524
|
+
via?: string;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Record a request-identity read (cookies(), headers(), a non-cacheable
|
|
528
|
+
* ctx.get()) on the current loader execution (#972).
|
|
529
|
+
*
|
|
530
|
+
* isInsideCacheScope() exempts loader bodies because a route cache() never
|
|
531
|
+
* stores their values. A loader bound with its own cache() does: with no key()
|
|
532
|
+
* and no store keyGenerator its entry is keyed by loader, host, path and
|
|
533
|
+
* params only, and an enclosing route cache() key does not partition it
|
|
534
|
+
* (#974). A cookies() read there stored the first visitor's session and served
|
|
535
|
+
* it to everyone for the TTL. The read is recorded on the execution, not
|
|
536
|
+
* thrown at the call: a reader that starts the loader before its binding does
|
|
537
|
+
* runs it outside any fill, and the binding's MISS then reuses that run. The
|
|
538
|
+
* fill checks what its execution recorded, through the same links as its tags
|
|
539
|
+
* (cache-tag.ts recordedIdentityRead), so both orders fail the same way.
|
|
540
|
+
* Response directives do not record: a key cannot make a skipped body's side
|
|
541
|
+
* effect reach a HIT.
|
|
542
|
+
*/
|
|
543
|
+
export declare function recordLoaderIdentityRead(surface: string, verb?: LoaderIdentityReadVerb): void;
|
|
544
|
+
/** The error a loader cache() fill with no declared key fails with (#972). */
|
|
545
|
+
export declare function loaderCacheIdentityError(read: LoaderIdentityRead, cachedLoaderId: string): Error;
|
|
429
546
|
/**
|
|
430
547
|
* Check if the current execution is inside a DSL loader scope
|
|
431
548
|
* (wrapped by runInsideLoaderScope). Used by rendered() barrier
|
|
@@ -439,6 +556,10 @@ export declare function isInsideLoaderScope(): boolean;
|
|
|
439
556
|
* Takes scalars so the already-latched path allocates nothing.
|
|
440
557
|
*/
|
|
441
558
|
export declare function latchCachedHeaderScope(kind: CachedHeaderScope["kind"], routeKey?: string): void;
|
|
559
|
+
/** True inside ANY loader execution — DSL loader scope or a loader body
|
|
560
|
+
* (however invoked). The "loaders always re-run fresh" exemptions key off
|
|
561
|
+
* this. */
|
|
562
|
+
export declare function isInsideAnyLoaderScope(): boolean;
|
|
442
563
|
/**
|
|
443
564
|
* The one ppr opt-in predicate: a page route entry that DECLARED `ppr`
|
|
444
565
|
* (`false` and undefined mean plain axis 1). Shared by the serve path
|
|
@@ -506,21 +627,32 @@ export declare function assertCachedHeaderWriteAllowed(surface: string, surfaceP
|
|
|
506
627
|
export declare function runInsideLoaderScope<T>(fn: () => T): T;
|
|
507
628
|
/**
|
|
508
629
|
* Run `fn` inside a loader BODY scope. Marks loader-function execution for the
|
|
509
|
-
* cache
|
|
630
|
+
* cache() purity guard only (isInsideCacheScope), WITHOUT affecting
|
|
510
631
|
* isInsideLoaderScope()/rendered() gating. Applied to every loader body (DSL
|
|
511
632
|
* and handler-invoked via ctx.use) so request-scoped reads inside a loader
|
|
512
|
-
* never trip the cache
|
|
633
|
+
* never trip the cache() guard — a route cache() never stores loader values.
|
|
634
|
+
* A "use cache" body the loader was entered in still refuses them
|
|
635
|
+
* (guardIdentityRead).
|
|
513
636
|
*/
|
|
514
|
-
export declare function runInsideLoaderBodyScope<T>(fn: () => T, loaderId?: string,
|
|
637
|
+
export declare function runInsideLoaderBodyScope<T>(fn: () => T, loaderId?: string, tags?: Set<string>): T;
|
|
638
|
+
/** The innermost loader body's execution tag set (runInsideLoaderBodyScope). */
|
|
639
|
+
export declare function getLoaderBodyTags(): Set<string> | undefined;
|
|
515
640
|
/**
|
|
516
641
|
* The $$id of the loader whose body is currently executing, or undefined
|
|
517
642
|
* outside any loader body. Used by the shell-capture identity guard
|
|
518
|
-
* (
|
|
643
|
+
* (guardIdentityRead) so its refusal warning can name the loader that read
|
|
519
644
|
* cookies()/headers() instead of blaming a lane it cannot see — the old
|
|
520
645
|
* hardcoded "bake-lane loader" text misled a live-lane debugging session
|
|
521
646
|
* (issue #672, secondary).
|
|
522
647
|
*/
|
|
523
648
|
export declare function getCurrentLoaderBodyId(): string | undefined;
|
|
649
|
+
/**
|
|
650
|
+
* The innermost loader body running here, or around it through the
|
|
651
|
+
* ctx.use(Loader) chain, whose id `match` accepts (HandleStore.push, the
|
|
652
|
+
* shell capture's push funnel). A body `stop` accepts, and `match` does not,
|
|
653
|
+
* ends the walk: nothing around it is returned.
|
|
654
|
+
*/
|
|
655
|
+
export declare function findEnclosingLoaderBody(match: (loaderId: string) => boolean, stop?: (loaderId: string) => boolean): string | undefined;
|
|
524
656
|
/**
|
|
525
657
|
* True while `loaderId`'s body, or a loader it awaits via ctx.use at any
|
|
526
658
|
* depth, is executing. The loader-level cache records these pushes
|
|
@@ -528,16 +660,6 @@ export declare function getCurrentLoaderBodyId(): string | undefined;
|
|
|
528
660
|
* reader runs in that request only reaches the page through the replay.
|
|
529
661
|
*/
|
|
530
662
|
export declare function isInsideLoaderBody(loaderId: string): boolean;
|
|
531
|
-
/**
|
|
532
|
-
* True while a HANDLER-invoked loader body (`await ctx.use(Loader)` from a
|
|
533
|
-
* handler, not the DSL segment funnel) is executing. The consumption-lane
|
|
534
|
-
* rule keys off this: handler consumption yields a BAKED copy in every shared
|
|
535
|
-
* artifact — cache(), "use cache", and the PPR shell — so the shell-capture
|
|
536
|
-
* identity guard (cookie-store.ts) permits cookies()/headers() here, exactly
|
|
537
|
-
* like the cache-purity guards do. DSL segment loaders (live lane masked at
|
|
538
|
-
* capture, bake lane guarded) never set the flag.
|
|
539
|
-
*/
|
|
540
|
-
export declare function isInsideHandlerInvokedLoaderBody(): boolean;
|
|
541
663
|
/**
|
|
542
664
|
* Check if the current execution is inside a handle push callback (sync or an
|
|
543
665
|
* async callback's continuation). Used by the handler-to-loader deadlock guard
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* Writes append Set-Cookie to the response stub.
|
|
8
8
|
*/
|
|
9
9
|
import type { CookieOptions } from "../router/middleware-types.js";
|
|
10
|
+
import type { Theme } from "../theme/types.js";
|
|
11
|
+
import { type RequestContext } from "./request-context.js";
|
|
10
12
|
/**
|
|
11
13
|
* A single cookie entry returned by get() and getAll().
|
|
12
14
|
*/
|
|
@@ -63,6 +65,37 @@ export interface ReadonlyHeaders {
|
|
|
63
65
|
[Symbol.iterator](): HeadersIterator<[string, string]>;
|
|
64
66
|
}
|
|
65
67
|
type HeadersIterator<T> = IterableIterator<T>;
|
|
68
|
+
/**
|
|
69
|
+
* Run the identity guard for a raw cookie read on `ctx`
|
|
70
|
+
* (request-context.ts `cookie()` / `cookies()`). Before #976 they were plain
|
|
71
|
+
* reads of the Cookie header that no shared scope refused. The guard reads
|
|
72
|
+
* the ambient context, as cookies() does, and falls back to `ctx`.
|
|
73
|
+
*/
|
|
74
|
+
export declare function guardRawCookieRead(ctx: RequestContext<any>, surface: "getRequestContext().cookie()" | "getRequestContext().cookies()"): void;
|
|
75
|
+
/**
|
|
76
|
+
* Guard `request.headers` like headers() (#976): the request every ctx
|
|
77
|
+
* exposes (request context, handler, middleware and loader `ctx.request`)
|
|
78
|
+
* gets an own getter that runs guardIdentityRead against the ambient request
|
|
79
|
+
* context, so a read inside a ppr capture, a cache() boundary, a "use cache"
|
|
80
|
+
* body or an unkeyed loader cache() fill refuses as cookies() does. A Request
|
|
81
|
+
* argument keys a "use cache" entry by its URL only (cache-runtime.ts), so a
|
|
82
|
+
* header read there baked the first caller's value into the shared entry.
|
|
83
|
+
* The router's own reads go through requestHeaders() (request-headers.ts).
|
|
84
|
+
* Idempotent; returns `request`.
|
|
85
|
+
*/
|
|
86
|
+
export declare function guardRequestHeaders(request: Request): Request;
|
|
87
|
+
/** The public reads of the visitor's theme cookie that readGuardedTheme guards. */
|
|
88
|
+
export type ThemeReadSurface = "ctx.theme" | "getRequestContext().theme";
|
|
89
|
+
/**
|
|
90
|
+
* `ctx`'s theme through guardIdentityRead: the one body of every public theme
|
|
91
|
+
* read (the handler and middleware `ctx.theme`, handler-context.ts and
|
|
92
|
+
* middleware.ts, and `getRequestContext().theme`, request-context.ts). The
|
|
93
|
+
* guard reads the ambient context, as cookies() does, and falls back to
|
|
94
|
+
* `ctx`; the value is `ctx`'s unguarded `_readTheme()`, which the router's
|
|
95
|
+
* own payload read (payloadInitialTheme, rsc/full-payload.ts) calls directly.
|
|
96
|
+
* Undefined without a theme config.
|
|
97
|
+
*/
|
|
98
|
+
export declare function readGuardedTheme(ctx: RequestContext<any> | undefined, surface: ThemeReadSurface): Theme | undefined;
|
|
66
99
|
/**
|
|
67
100
|
* Get the original request headers (read-only).
|
|
68
101
|
*
|