@rangojs/router 0.18.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/dist/types/browser/event-controller.d.ts +3 -3
- package/dist/types/browser/history-state.d.ts +2 -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 +44 -13
- package/dist/types/cache/cache-policy.d.ts +1 -1
- package/dist/types/cache/cache-runtime.d.ts +7 -0
- package/dist/types/cache/cache-scope.d.ts +117 -35
- package/dist/types/cache/cache-tag.d.ts +24 -4
- package/dist/types/cache/cf/cf-cache-store.d.ts +55 -44
- package/dist/types/cache/cf/cf-shell-frame.d.ts +1 -1
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +0 -15
- package/dist/types/cache/document-cache.d.ts +10 -0
- package/dist/types/cache/handle-snapshot.d.ts +40 -8
- package/dist/types/cache/invalidation-order.d.ts +23 -0
- package/dist/types/cache/request-tag-mask.d.ts +54 -0
- package/dist/types/cache/shell-snapshot.d.ts +88 -141
- package/dist/types/cache/tag-invalidation.d.ts +38 -14
- package/dist/types/cache/types.d.ts +68 -61
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +23 -16
- 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/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/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/router-options.d.ts +4 -1
- package/dist/types/router/segment-resolution/loader-cache.d.ts +18 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -4
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +14 -40
- package/dist/types/router/segment-resolution/mask-nested.d.ts +11 -3
- 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 +14 -7
- package/dist/types/rsc/response-cache-serve.d.ts +15 -12
- package/dist/types/rsc/shell-build-manifest.d.ts +4 -3
- package/dist/types/rsc/shell-capture-constants.d.ts +77 -20
- package/dist/types/rsc/shell-capture.d.ts +78 -81
- package/dist/types/rsc/shell-serve.d.ts +19 -48
- package/dist/types/rsc/types.d.ts +2 -0
- package/dist/types/segment-system.d.ts +7 -0
- package/dist/types/server/context.d.ts +89 -61
- package/dist/types/server/cookie-store.d.ts +30 -18
- package/dist/types/server/handle-store.d.ts +52 -1
- package/dist/types/server/request-context.d.ts +66 -45
- package/dist/types/server/request-headers.d.ts +44 -0
- package/dist/types/server.d.ts +1 -0
- package/dist/types/testing/e2e/index.d.ts +1 -1
- 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-transition-when.d.ts +44 -69
- package/dist/types/testing/serve-shell-request.d.ts +7 -6
- package/dist/types/testing/shell-status.d.ts +34 -22
- package/dist/types/transition-when-ref.d.ts +79 -0
- package/dist/types/types/cache-types.d.ts +15 -3
- 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 +3 -4
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +45 -0
- package/dist/vite/index.js +960 -97
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +76 -49
- package/skills/caching/SKILL.md +167 -69
- package/skills/client-urls/SKILL.md +1 -1
- package/skills/comparison/references/framework-comparison.md +8 -5
- package/skills/document-cache/SKILL.md +24 -0
- package/skills/hooks/SKILL.md +3 -1
- package/skills/hooks/navigation.md +23 -2
- package/skills/hooks/state.md +98 -6
- package/skills/intercept/SKILL.md +29 -12
- package/skills/loader/SKILL.md +52 -21
- package/skills/middleware/SKILL.md +18 -0
- package/skills/migrate-nextjs/SKILL.md +3 -3
- package/skills/observability/SKILL.md +6 -5
- package/skills/parallel/SKILL.md +1 -1
- package/skills/ppr/SKILL.md +129 -77
- package/skills/prerender/SKILL.md +3 -3
- package/skills/rango/SKILL.md +25 -6
- package/skills/route/SKILL.md +2 -0
- package/skills/testing/SKILL.md +27 -25
- package/skills/testing/cache-prerender.md +9 -9
- package/skills/testing/client-components.md +45 -3
- package/skills/testing/loader.md +3 -2
- 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 +14 -0
- package/skills/testing/server-actions.md +9 -3
- package/skills/theme/SKILL.md +8 -4
- package/skills/typesafety/env-and-bindings.md +8 -0
- package/skills/use-cache/SKILL.md +64 -19
- package/skills/view-transitions/SKILL.md +150 -29
- package/src/__augment-tests__/augmented.check.ts +23 -0
- package/src/browser/event-controller.ts +4 -4
- package/src/browser/history-state.ts +52 -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 +4 -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 +56 -16
- package/src/cache/cache-policy.ts +9 -4
- package/src/cache/cache-runtime.ts +197 -144
- package/src/cache/cache-scope.ts +304 -112
- package/src/cache/cache-tag.ts +105 -13
- package/src/cache/cf/cf-cache-store.ts +152 -76
- package/src/cache/cf/cf-shell-frame.ts +2 -2
- package/src/cache/cf/cf-tag-marker-memo.ts +11 -100
- package/src/cache/document-cache.ts +53 -7
- package/src/cache/handle-snapshot.ts +52 -9
- package/src/cache/invalidation-order.ts +84 -0
- package/src/cache/request-tag-mask.ts +147 -0
- package/src/cache/shell-snapshot.ts +130 -348
- package/src/cache/tag-invalidation.ts +57 -51
- package/src/cache/types.ts +71 -67
- package/src/cache/vercel/vercel-cache-store.ts +61 -58
- 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 +155 -146
- package/src/route-definition/dsl-helpers.ts +2 -0
- 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 +10 -7
- package/src/router/intercept-resolution.ts +11 -1
- package/src/router/loader-resolution.ts +28 -3
- package/src/router/logging.ts +5 -3
- package/src/router/match-api.ts +62 -34
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +9 -29
- package/src/router/match-middleware/background-revalidation.ts +3 -5
- package/src/router/match-middleware/cache-lookup.ts +35 -19
- package/src/router/match-middleware/cache-store.ts +15 -9
- package/src/router/match-result.ts +1 -0
- package/src/router/middleware.ts +2 -5
- package/src/router/navigation-snapshot.ts +6 -5
- package/src/router/prerender-match.ts +4 -0
- package/src/router/request-classification.ts +7 -4
- package/src/router/router-options.ts +4 -1
- package/src/router/segment-resolution/fresh.ts +0 -4
- package/src/router/segment-resolution/loader-cache.ts +150 -25
- package/src/router/segment-resolution/loader-mask.ts +3 -4
- package/src/router/segment-resolution/loader-snapshot.ts +15 -78
- package/src/router/segment-resolution/mask-nested.ts +47 -22
- package/src/router/segment-resolution/revalidation.ts +0 -3
- 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 +30 -10
- package/src/rsc/handler.ts +12 -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 +7 -30
- package/src/rsc/response-cache-serve.ts +68 -80
- package/src/rsc/response-route-handler.ts +2 -2
- package/src/rsc/rsc-rendering.ts +206 -252
- package/src/rsc/server-action.ts +8 -20
- package/src/rsc/shell-build-manifest.ts +22 -20
- package/src/rsc/shell-capture-constants.ts +136 -20
- package/src/rsc/shell-capture.ts +352 -589
- package/src/rsc/shell-serve.ts +73 -109
- package/src/rsc/ssr-setup.ts +3 -2
- package/src/rsc/types.ts +2 -0
- package/src/segment-system.tsx +40 -7
- package/src/server/context.ts +189 -124
- package/src/server/cookie-store.ts +153 -127
- package/src/server/handle-store.ts +245 -27
- package/src/server/request-context.ts +123 -84
- package/src/server/request-headers.ts +134 -0
- package/src/server.ts +4 -0
- package/src/testing/dispatch.ts +4 -7
- package/src/testing/e2e/index.ts +1 -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 +5 -1
- package/src/testing/run-transition-when.ts +109 -172
- package/src/testing/serve-shell-request.ts +10 -7
- package/src/testing/shell-status.ts +60 -56
- package/src/transition-when-ref.ts +220 -0
- package/src/types/cache-types.ts +15 -3
- 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 +3 -4
- package/src/vite/discovery/discover-routers.ts +3 -0
- package/src/vite/discovery/shell-prerender-phase.ts +0 -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 +75 -5
- package/dist/types/rsc/transition-gate.d.ts +0 -23
- package/src/rsc/transition-gate.ts +0 -86
|
@@ -5,88 +5,72 @@
|
|
|
5
5
|
* that must agree with them byte for byte. The handler layer's part of that
|
|
6
6
|
* payload is the capture's own doc segment record: the capture writes it
|
|
7
7
|
* first, renders its prelude from it, and every HIT replays it (no handler
|
|
8
|
-
* runs on a HIT).
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* runs on a HIT). The loader layer's part is the bake-lane (`ssr: false`)
|
|
9
|
+
* loader pins: a promise-free bake-lane loader is served from its pin and
|
|
10
|
+
* does not run; one whose return carries promises (`holes`), or whose pushes
|
|
11
|
+
* the record could not keep (`runs`), runs on the HIT. See
|
|
12
|
+
* docs/design/ppr-shell-resume.md.
|
|
12
13
|
*
|
|
13
|
-
* The
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* The invariant, verbatim: the snapshot is the doc record plus the cache-store
|
|
22
|
-
* reads the capture's loaders performed; replaying them on a HIT reproduces
|
|
23
|
-
* the shell content byte-identically; everything not recorded stays live.
|
|
24
|
-
* {@link pruneShellSnapshot} drops the rest.
|
|
14
|
+
* The invariant, verbatim: the snapshot is the doc record and the bake-lane
|
|
15
|
+
* loader pins; replaying them on a HIT reproduces the shell content
|
|
16
|
+
* byte-identically; everything else a HIT reads comes from the store. A hole
|
|
17
|
+
* (a live-lane loader, or a promise nested in a bake-lane return) never reads
|
|
18
|
+
* the capture's copy of a value: it is dynamic or has its own cache. A
|
|
19
|
+
* bake-lane loader body that runs on a HIT reads the store too; its pinned
|
|
20
|
+
* container paths stay the pin's (overlayLoaderContainer), and its settled
|
|
21
|
+
* pushes stay the record's (HandleStore.pushRestored).
|
|
25
22
|
*/
|
|
26
23
|
import type { SegmentCacheStore, CacheGetResult, CacheItemResult, CacheItemOptions, CachedEntryData, ShellCacheEntry, ShellSnapshotRecord, CacheReadError } from "./types.js";
|
|
27
24
|
/**
|
|
28
|
-
* A store wrapper the CAPTURE render reads through. Every call passes through
|
|
29
|
-
* the underlying store unchanged;
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* The shell family (getShell/putShell) is never recorded (the snapshot rides
|
|
35
|
-
* inside a shell entry). Reads that MISS are not recorded (a miss produced no
|
|
36
|
-
* shell content; if the render then computed and wrote, that write is recorded).
|
|
25
|
+
* A store wrapper the CAPTURE render reads through. Every call passes through
|
|
26
|
+
* to the underlying store unchanged; the one thing it records is the doc
|
|
27
|
+
* segment record ({@link recordSegmentWrite}). No cache read is recorded: a
|
|
28
|
+
* HIT replays the handler layer from the doc record and serves a promise-free
|
|
29
|
+
* bake-lane loader from its pin, and everything else a HIT reads (a hole, a
|
|
30
|
+
* bake-lane loader body that runs there) comes from the store.
|
|
37
31
|
*
|
|
38
32
|
* Deferred writes: cache writes run under waitUntil (fire-and-forget on Node,
|
|
39
|
-
* executionContext on workerd), so
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* Loader attribution: every item/response access made inside a loader scope
|
|
45
|
-
* (hit, miss or write) marks its key in {@link loaderKeys}. A loader re-runs
|
|
46
|
-
* on every HIT, so those records stay pinned when the snapshot is pruned. A
|
|
47
|
-
* miss counts too: a loader that joins a handler's in-flight "use cache" call
|
|
48
|
-
* reads the store first (cache-runtime.ts) and finds nothing, and the record
|
|
49
|
-
* then comes from the handler's write.
|
|
33
|
+
* executionContext on workerd), so the doc record's write may land after the
|
|
34
|
+
* capture's match returns. The capture collects those write promises via
|
|
35
|
+
* {@link trackWrite} and awaits them ({@link settleWrites}) before reading the
|
|
36
|
+
* record and draining.
|
|
50
37
|
*/
|
|
51
38
|
export declare class RecordingShellStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
52
39
|
private readonly inner;
|
|
40
|
+
/** The recorded segment records by key, last write wins. */
|
|
53
41
|
private readonly records;
|
|
54
42
|
private readonly writes;
|
|
55
|
-
/** Record keys ({@link recordKey}) a loader read or wrote during the capture. */
|
|
56
|
-
readonly loaderKeys: Set<string>;
|
|
57
43
|
constructor(inner: SegmentCacheStore<TEnv>);
|
|
58
44
|
get defaults(): SegmentCacheStore<TEnv>["defaults"];
|
|
59
45
|
get keyGenerator(): SegmentCacheStore<TEnv>["keyGenerator"];
|
|
60
46
|
get supportsPassiveShellReads(): true | undefined;
|
|
61
|
-
|
|
62
|
-
private noteLoaderAccess;
|
|
47
|
+
get isTagsInvalidatedSince(): SegmentCacheStore<TEnv>["isTagsInvalidatedSince"];
|
|
63
48
|
/** Track a deferred cache-write promise so the capture can await it pre-drain. */
|
|
64
49
|
trackWrite(p: Promise<unknown>): void;
|
|
65
50
|
/**
|
|
66
|
-
* Record
|
|
67
|
-
* store. The
|
|
68
|
-
* (via {@link SnapshotOnlySegmentStore}): the
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
51
|
+
* Record the doc segment record into the snapshot WITHOUT touching the
|
|
52
|
+
* inner store. The capture's implicit doc-cache scope writes through this
|
|
53
|
+
* (via {@link SnapshotOnlySegmentStore}): the record must ride ONLY inside
|
|
54
|
+
* the shell entry — a passthrough write would leave a doc-keyed entry in the
|
|
55
|
+
* real store that the NEXT capture's lookup would hit, replaying the
|
|
56
|
+
* previous generation's segments instead of re-running handlers (breaking
|
|
72
57
|
* SWR recapture freshness).
|
|
73
58
|
*/
|
|
74
59
|
recordSegmentWrite(key: string, data: CachedEntryData): void;
|
|
75
60
|
/**
|
|
76
|
-
* Await the tracked deferred writes so their records are present before
|
|
77
|
-
*
|
|
78
|
-
* cacheRoute path schedules its actual store.set in a second waitUntil
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* when the doc record is among the writes still pending).
|
|
61
|
+
* Await the tracked deferred writes so their records are present before
|
|
62
|
+
* drain, including a NESTED write a settled one scheduled (the ring-3
|
|
63
|
+
* cacheRoute path schedules its actual store.set in a second waitUntil).
|
|
64
|
+
* Bounded: a pathologically slow write must never stall the capture task.
|
|
65
|
+
* Resolves true when every tracked write settled, false at the deadline
|
|
66
|
+
* (settleCaptureRecord then fails the capture when the doc record is among
|
|
67
|
+
* the writes still pending); a later call still waits for what is pending.
|
|
84
68
|
*/
|
|
85
69
|
settleWrites(timeoutMs: number): Promise<boolean>;
|
|
86
|
-
/** The recorded
|
|
70
|
+
/** The recorded segment records, or undefined if none. */
|
|
87
71
|
drainSnapshot(): ShellSnapshotRecord[] | undefined;
|
|
88
|
-
/** One recorded
|
|
89
|
-
getRecord(
|
|
72
|
+
/** One recorded segment record, by key. */
|
|
73
|
+
getRecord(key: string): CachedEntryData | undefined;
|
|
90
74
|
get(key: string): Promise<CacheGetResult | null | CacheReadError>;
|
|
91
75
|
set(key: string, data: CachedEntryData, ttl: number, swr?: number): Promise<void>;
|
|
92
76
|
delete(key: string): Promise<boolean>;
|
|
@@ -107,36 +91,23 @@ export declare class RecordingShellStore<TEnv = unknown> implements SegmentCache
|
|
|
107
91
|
putShell(key: string, entry: ShellCacheEntry, ttlSeconds?: number, swrSeconds?: number, tags?: string[]): Promise<"stored" | "invalidated" | "uncacheable" | void>;
|
|
108
92
|
invalidateTags(tags: string[]): Promise<void>;
|
|
109
93
|
}
|
|
110
|
-
/**
|
|
94
|
+
/** `store` when it is a RecordingShellStore (an instanceof check). */
|
|
111
95
|
export declare function getRecordingStore<TEnv>(store: SegmentCacheStore<TEnv> | undefined): RecordingShellStore<TEnv> | undefined;
|
|
112
96
|
/**
|
|
113
97
|
* True when `snapshot` carries the canonical doc segment record `docKey`
|
|
114
|
-
* names, with at least one segment: the record partial replay and a
|
|
115
|
-
*
|
|
98
|
+
* names, with at least one segment: the record partial replay and a document
|
|
99
|
+
* HIT tail consume.
|
|
116
100
|
*/
|
|
117
101
|
export declare function hasDocRecord(snapshot: readonly ShellSnapshotRecord[] | undefined, docKey: string | undefined): boolean;
|
|
118
102
|
/**
|
|
119
|
-
*
|
|
120
|
-
* (docs/design/shell-entry-layout.md §2):
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
* the handler layer from the doc record and never runs a handler, so the
|
|
126
|
-
* records only handler code read are dead weight.
|
|
127
|
-
*/
|
|
128
|
-
export type ShellSnapshotReaders = "segments" | "loaders";
|
|
129
|
-
/**
|
|
130
|
-
* Split a capture's snapshot into what its readers consume and the rest: the
|
|
131
|
-
* doc record (`docKey`) always; with "loaders", the loader-family records and
|
|
132
|
-
* the item/response records a loader touched during the capture
|
|
133
|
-
* (RecordingShellStore.loaderKeys). Every other segment record goes: an
|
|
134
|
-
* explicit cache() tier's reads and writes are keyed where no HIT tail and no
|
|
135
|
-
* partial replay looks (both consult only the doc record). The doc record
|
|
136
|
-
* stays a copy inside the entry: a reference to a separately stored record
|
|
137
|
-
* could be evicted on its own, and the HIT would have nothing to replay.
|
|
103
|
+
* Split a capture's snapshot into what a HIT or a partial replay reads and
|
|
104
|
+
* the rest (docs/design/shell-entry-layout.md §2). Kept: the doc record
|
|
105
|
+
* (`docKey`), as a copy inside the entry (a separately stored record could be
|
|
106
|
+
* evicted on its own, and the HIT would have nothing to replay), and the
|
|
107
|
+
* loader-family pins unless the entry is navigation-only (partial replay of
|
|
108
|
+
* such an entry seeds the doc record alone). Every other record goes.
|
|
138
109
|
*/
|
|
139
|
-
export declare function pruneShellSnapshot(snapshot: readonly ShellSnapshotRecord[],
|
|
110
|
+
export declare function pruneShellSnapshot(snapshot: readonly ShellSnapshotRecord[], navigationOnly: boolean, docKey: string | undefined): {
|
|
140
111
|
kept: ShellSnapshotRecord[];
|
|
141
112
|
pruned: ShellSnapshotRecord[];
|
|
142
113
|
};
|
|
@@ -165,16 +136,16 @@ export declare function estimateShellEntryBytes(parts: {
|
|
|
165
136
|
docKey: string | undefined;
|
|
166
137
|
prunedRecords: string | undefined;
|
|
167
138
|
}): number;
|
|
168
|
-
/** Snapshot records by family, e.g. `segment:1/
|
|
139
|
+
/** Snapshot records by family, e.g. `segment:1/loader:2` (no commas: it rides a Server-Timing desc). */
|
|
169
140
|
export declare function countSnapshotFamilies(snapshot: readonly ShellSnapshotRecord[]): string;
|
|
170
141
|
/**
|
|
171
|
-
* The store the
|
|
172
|
-
*
|
|
173
|
-
* recorded
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
142
|
+
* The store the capture's IMPLICIT doc-cache scope resolves: reads pass
|
|
143
|
+
* through the recording store to the real one, but segment WRITES are
|
|
144
|
+
* recorded into the snapshot only — see
|
|
145
|
+
* {@link RecordingShellStore.recordSegmentWrite} for why passthrough would
|
|
146
|
+
* break SWR recapture. A route with its OWN cache() scope keeps that scope's
|
|
147
|
+
* real-store reads and writes; recordShellCaptureDocRecord (cache-store.ts)
|
|
148
|
+
* writes its doc record through this store too.
|
|
178
149
|
*/
|
|
179
150
|
export declare class SnapshotOnlySegmentStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
180
151
|
private readonly recording;
|
|
@@ -185,28 +156,14 @@ export declare class SnapshotOnlySegmentStore<TEnv = unknown> implements Segment
|
|
|
185
156
|
set(key: string, data: CachedEntryData): Promise<void>;
|
|
186
157
|
delete(key: string): Promise<boolean>;
|
|
187
158
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Materialize the loader-family seed from a shell snapshot for a HIT's tail
|
|
190
|
-
* render: Flight-deserialize each recorded (promise-elided) bake-lane
|
|
191
|
-
* container into a segment-key -> container Map, which serveShellHit assigns
|
|
192
|
-
* to the tail context's `_shellLoaderSeed` for the resolveLoaderData overlay.
|
|
193
|
-
* Lives here so every snapshot family is decoded in this module (the
|
|
194
|
-
* item/segment/response families via {@link SeededShellStore}); the loader
|
|
195
|
-
* family is not a store read, so it seeds the context instead of a store.
|
|
196
|
-
*
|
|
197
|
-
* Deserializations run in parallel; a record that fails to decode is skipped
|
|
198
|
-
* (that loader drifts — the pre-snapshot behavior — instead of failing the
|
|
199
|
-
* HIT). Returns undefined when the snapshot carries no loader records, without
|
|
200
|
-
* touching the Flight codec (kept lazy for cold paths and non-RSC configs).
|
|
201
|
-
*/
|
|
159
|
+
/** One decoded loader-family pin (buildShellLoaderSeed). */
|
|
202
160
|
export interface ShellLoaderSeedEntry {
|
|
203
161
|
/** The Flight-deserialized elided container (recorded paths + markers). */
|
|
204
162
|
container: unknown;
|
|
205
163
|
/**
|
|
206
|
-
* True when the record carries hole markers
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* from the pin (loader-cache.ts pin-first path).
|
|
164
|
+
* True when the record carries hole markers: the HIT overlay must gate on
|
|
165
|
+
* the fresh run. False = fully pinned; the payload promise resolves
|
|
166
|
+
* immediately from the pin (loader-cache.ts pin-first path).
|
|
210
167
|
*/
|
|
211
168
|
holes: boolean;
|
|
212
169
|
/**
|
|
@@ -216,51 +173,41 @@ export interface ShellLoaderSeedEntry {
|
|
|
216
173
|
*/
|
|
217
174
|
runs: boolean;
|
|
218
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Materialize the loader-family seed from a shell snapshot for a HIT's tail
|
|
178
|
+
* render: Flight-deserialize each recorded (promise-elided) bake-lane
|
|
179
|
+
* container into a segment-key -> container Map, which serveShellHit assigns
|
|
180
|
+
* to the tail context's `_shellLoaderSeed` for the resolveLoaderData overlay.
|
|
181
|
+
* Lives here so every snapshot family is decoded in this module (the segment
|
|
182
|
+
* family via {@link SeededShellStore}); the loader family is not a store
|
|
183
|
+
* read, so it seeds the context instead of a store.
|
|
184
|
+
*
|
|
185
|
+
* Deserializations run in parallel; a record that fails to decode is skipped
|
|
186
|
+
* (that loader drifts — the pre-snapshot behavior — instead of failing the
|
|
187
|
+
* HIT). Returns undefined when the snapshot carries no loader records, without
|
|
188
|
+
* touching the Flight codec (kept lazy for cold paths and non-RSC configs).
|
|
189
|
+
*/
|
|
219
190
|
export declare function buildShellLoaderSeed(snapshot: ShellSnapshotRecord[]): Promise<Map<string, ShellLoaderSeedEntry> | undefined>;
|
|
220
191
|
/**
|
|
221
|
-
*
|
|
222
|
-
* the snapshot
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* partial navigation cannot freeze captured data or write a partial result into
|
|
231
|
-
* the canonical document namespace.
|
|
192
|
+
* The implicit doc scope's store on a HIT tail and on a partial replay: it
|
|
193
|
+
* serves the snapshot's segment records, the doc record among them, and
|
|
194
|
+
* fully isolates the segment family. Misses do not fall through, and writes
|
|
195
|
+
* or deletes stay local to the overlay, so a partial navigation cannot write
|
|
196
|
+
* a partial result into the canonical document namespace. It carries nothing
|
|
197
|
+
* else: every other read on a HIT (a hole, a bake-lane loader body that runs
|
|
198
|
+
* there) resolves the request's own store. Loader-family records are not
|
|
199
|
+
* store reads: serveShellHit seeds them onto the tail context
|
|
200
|
+
* (_shellLoaderSeed) for the resolveLoaderData overlay instead.
|
|
232
201
|
*/
|
|
233
202
|
export declare class SeededShellStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
234
203
|
private readonly inner;
|
|
235
|
-
private readonly items;
|
|
236
204
|
private readonly segments;
|
|
237
|
-
|
|
238
|
-
private readonly segmentsOnly;
|
|
239
|
-
constructor(inner: SegmentCacheStore<TEnv>, snapshot: ShellSnapshotRecord[], options?: {
|
|
240
|
-
segmentsOnly?: boolean;
|
|
241
|
-
});
|
|
205
|
+
constructor(inner: SegmentCacheStore<TEnv>, snapshot: readonly ShellSnapshotRecord[]);
|
|
242
206
|
get defaults(): SegmentCacheStore<TEnv>["defaults"];
|
|
243
207
|
get keyGenerator(): SegmentCacheStore<TEnv>["keyGenerator"];
|
|
244
|
-
get supportsPassiveShellReads(): true | undefined;
|
|
245
208
|
get(key: string): Promise<CacheGetResult | null | CacheReadError>;
|
|
246
|
-
set(key: string, data: CachedEntryData
|
|
209
|
+
set(key: string, data: CachedEntryData): Promise<void>;
|
|
247
210
|
delete(key: string): Promise<boolean>;
|
|
248
|
-
clear(): Promise<void>;
|
|
249
|
-
getResponse(key: string): Promise<{
|
|
250
|
-
response: Response;
|
|
251
|
-
shouldRevalidate: boolean;
|
|
252
|
-
} | null>;
|
|
253
|
-
putResponse(key: string, response: Response, ttl: number, swr?: number, tags?: string[]): Promise<void>;
|
|
254
|
-
getItem(key: string): Promise<CacheItemResult | null>;
|
|
255
|
-
setItem(key: string, value: string, options?: CacheItemOptions): Promise<void>;
|
|
256
|
-
getShell(key: string, options?: {
|
|
257
|
-
claimRevalidation?: boolean;
|
|
258
|
-
}): Promise<{
|
|
259
|
-
entry: ShellCacheEntry;
|
|
260
|
-
shouldRevalidate?: boolean;
|
|
261
|
-
} | null>;
|
|
262
|
-
putShell(key: string, entry: ShellCacheEntry, ttlSeconds?: number, swrSeconds?: number, tags?: string[]): Promise<"stored" | "invalidated" | "uncacheable" | void>;
|
|
263
|
-
invalidateTags(tags: string[]): Promise<void>;
|
|
264
211
|
}
|
|
265
212
|
/**
|
|
266
213
|
* Thrown by a document HIT tail's match when its doc record cannot supply the
|
|
@@ -30,23 +30,47 @@
|
|
|
30
30
|
* Invariant: the mask only turns the invalidating request's hits into misses.
|
|
31
31
|
* If the durable write then fails, that request paid extra misses, never a
|
|
32
32
|
* stale read, and other requests read the durable state. Both also record
|
|
33
|
-
* the tags
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* entry (#980), for this gate as for eviction. Not covered (#977): such an
|
|
38
|
-
* execution in another request, or a loader cache() write, still lands, and
|
|
39
|
-
* the store accepts it (docs/design/caching.md "Read-your-own-writes").
|
|
33
|
+
* the tags in the isolate's invalidation order (markInvalidated), so a cache
|
|
34
|
+
* execution that started before one of its tags was invalidated, in any
|
|
35
|
+
* request, is neither joined nor written (#973, #977): see
|
|
36
|
+
* predatesInvalidation, and docs/design/caching.md "Read-your-own-writes".
|
|
40
37
|
*/
|
|
41
|
-
import {
|
|
42
|
-
|
|
43
|
-
export
|
|
38
|
+
import type { SegmentCacheStore } from "./types.js";
|
|
39
|
+
import { type ExecutionStart } from "./invalidation-order.js";
|
|
40
|
+
export { executionStart, invalidatedSince, type ExecutionStart, } from "./invalidation-order.js";
|
|
44
41
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
42
|
+
* The write gate of every cache execution (#977): whether one of `tags` was
|
|
43
|
+
* invalidated after the execution that produced the value started.
|
|
44
|
+
*
|
|
45
|
+
* Every built-in store stamps an entry when it is written (CFCacheStore's
|
|
46
|
+
* `taggedAt`, VercelCacheStore's `ta`) or checks nothing on write
|
|
47
|
+
* (MemorySegmentCacheStore), so a value read before an invalidation and
|
|
48
|
+
* written after it would be served as newer than the invalidation until it
|
|
49
|
+
* expires. Two answers, either one skips the write:
|
|
50
|
+
*
|
|
51
|
+
* - this isolate's order (invalidatedSince), which sees every request's
|
|
52
|
+
* updateTag()/revalidateTag() here, the calling one included;
|
|
53
|
+
* - the store's markers (isTagsInvalidatedSince), for another isolate's
|
|
54
|
+
* invalidation, as far as the store can tell: KV markers on CFCacheStore
|
|
55
|
+
* (KV-less, only this request's own), `tm` markers on VercelCacheStore,
|
|
56
|
+
* the process markers on MemorySegmentCacheStore. Asked about the
|
|
57
|
+
* milliseconds after the start's: this isolate's own invalidation that
|
|
58
|
+
* preceded the start usually shares its millisecond (Workers freeze
|
|
59
|
+
* Date.now() between I/O), and `>=` would skip every write started right
|
|
60
|
+
* after it. Another isolate's invalidation in the start's own millisecond
|
|
61
|
+
* is not caught. Asked fail-closed: a marker the store cannot read
|
|
62
|
+
* counts as an invalidation.
|
|
63
|
+
*
|
|
64
|
+
* The order is read again once the store answers: its read can be in flight
|
|
65
|
+
* while this isolate invalidates (an action awaits a "use cache" miss, whose
|
|
66
|
+
* write waits on the read, then runs updateTag()), and it then answers with
|
|
67
|
+
* the markers from before. markInvalidated is synchronous, so this second
|
|
68
|
+
* look sees every invalidation made before the answer.
|
|
69
|
+
*
|
|
70
|
+
* Invariant: a skipped write only costs a later miss, never a stale read.
|
|
71
|
+
* The caller still returns the value it computed.
|
|
48
72
|
*/
|
|
49
|
-
export declare function
|
|
73
|
+
export declare function predatesInvalidation(store: SegmentCacheStore, tags: readonly string[] | undefined, start: ExecutionStart): Promise<boolean>;
|
|
50
74
|
/**
|
|
51
75
|
* Immediately expire every cache entry tagged with any of `tags`, resolving
|
|
52
76
|
* once in-process invalidation across all configured stores completes.
|
|
@@ -67,6 +67,12 @@ export interface SegmentCacheStore<TEnv = unknown> {
|
|
|
67
67
|
* 2. Store-level `keyGenerator` (modifies default key)
|
|
68
68
|
* 3. Default key generation (prefix:pathname:params)
|
|
69
69
|
*
|
|
70
|
+
* Return `defaultKey` unchanged to leave a request unpartitioned. An empty
|
|
71
|
+
* string is not a key: where the result partitions a nested cache() on
|
|
72
|
+
* another store, or a ppr shell, it fails key resolution, so the request
|
|
73
|
+
* renders uncached (as when the keyGenerator throws), and the router warns
|
|
74
|
+
* once naming the store.
|
|
75
|
+
*
|
|
70
76
|
* @example Using headers for cache segmentation
|
|
71
77
|
* ```typescript
|
|
72
78
|
* keyGenerator: (ctx, defaultKey) => {
|
|
@@ -277,12 +283,25 @@ export interface SegmentCacheStore<TEnv = unknown> {
|
|
|
277
283
|
* freshness). Consulted by build-shell read-through and runtime shell stores:
|
|
278
284
|
* "was it evicted" is answered by tag markers against the entry's createdAt,
|
|
279
285
|
* including when invalidation races a capture that has not been written yet.
|
|
286
|
+
* Also the store's half of every cache write's gate (#977,
|
|
287
|
+
* tag-invalidation.ts predatesInvalidation): a "use cache", loader cache(),
|
|
288
|
+
* route cache() or document-cache write whose execution started before an
|
|
289
|
+
* invalidation another isolate made is skipped when this answers true, so
|
|
290
|
+
* it must reflect invalidations made after this request started reading
|
|
291
|
+
* (not a value memoized earlier in the request).
|
|
280
292
|
* Optional: without it, TAGGED build entries are not served (untagged ones
|
|
281
|
-
* are unaffected — they are evictable only by deploy/buildVersion anyway)
|
|
293
|
+
* are unaffected — they are evictable only by deploy/buildVersion anyway),
|
|
294
|
+
* and writes are gated by this isolate's invalidations only.
|
|
282
295
|
* Fail open to `false` on marker-read errors: a transient store fault must
|
|
283
296
|
* degrade to "still valid", the same posture as the envelope tag checks.
|
|
284
|
-
|
|
285
|
-
|
|
297
|
+
* The write gate passes `{ failClosed: true }` instead: a marker it cannot
|
|
298
|
+
* read (an error, a timed-out read) answers `true`, since a skipped write
|
|
299
|
+
* only costs a later miss. A store that ignores the option still works;
|
|
300
|
+
* its fault then lets that write through.
|
|
301
|
+
*/
|
|
302
|
+
isTagsInvalidatedSince?(tags: string[], sinceMs: number, options?: {
|
|
303
|
+
failClosed?: boolean;
|
|
304
|
+
}): Promise<boolean>;
|
|
286
305
|
}
|
|
287
306
|
/**
|
|
288
307
|
* Result from getItem() for function-level caching ("use cache").
|
|
@@ -347,11 +366,10 @@ export interface ShellCacheEntry {
|
|
|
347
366
|
* on dev RSC-module edits). The second read-time gate: a persistent shared
|
|
348
367
|
* store (KV/runtime-cache) survives deploys, and an app-code change that
|
|
349
368
|
* keeps the same React version would otherwise leave a stale-build
|
|
350
|
-
* prelude+postponed live under the same key.
|
|
351
|
-
*
|
|
352
|
-
* recapture re-stamps them (pre-release, no compat shim).
|
|
369
|
+
* prelude+postponed live under the same key. A custom store returns it as
|
|
370
|
+
* putShell received it.
|
|
353
371
|
*/
|
|
354
|
-
buildVersion
|
|
372
|
+
buildVersion: string;
|
|
355
373
|
/**
|
|
356
374
|
* The initialTheme the CAPTURE render was built with: the no-cookie default
|
|
357
375
|
* (payloadInitialTheme, rsc/full-payload.ts), never the capturing visitor's
|
|
@@ -366,22 +384,20 @@ export interface ShellCacheEntry {
|
|
|
366
384
|
*/
|
|
367
385
|
initialTheme?: string;
|
|
368
386
|
/**
|
|
369
|
-
* The CAPTURE DATA SNAPSHOT
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
* shell-baked cached value that drifted mismatches the prelude). Recapture
|
|
379
|
-
* heals it. See docs/design/ppr-shell-resume.md ("the capture data snapshot").
|
|
387
|
+
* The CAPTURE DATA SNAPSHOT, in stored/serialized form: the doc segment
|
|
388
|
+
* record every HIT replays the handler layer from (`docKey`) and the
|
|
389
|
+
* bake-lane loader pins (pruned to what a HIT reads, issue #941). Replaying
|
|
390
|
+
* them on a HIT keeps the freshly rendered hydration payload equal to the
|
|
391
|
+
* frozen prelude after the underlying cache entries have drifted; every
|
|
392
|
+
* other read on a HIT, a hole's included, reads the store. Empty when the capture
|
|
393
|
+
* recorded nothing (a prerender-served capture without bake-lane loaders,
|
|
394
|
+
* a tombstone). A custom store returns it as putShell received it. See
|
|
395
|
+
* docs/design/ppr-shell-resume.md ("the capture data snapshot").
|
|
380
396
|
*/
|
|
381
|
-
snapshot
|
|
397
|
+
snapshot: ShellSnapshotRecord[];
|
|
382
398
|
/**
|
|
383
399
|
* Records the capture dropped from `snapshot` because no reader of this
|
|
384
|
-
* entry consumes them, by family (`
|
|
400
|
+
* entry consumes them, by family (`loader:1`). Diagnostic only: the
|
|
385
401
|
* HIT tail timing reports it next to the kept records. See
|
|
386
402
|
* docs/design/shell-entry-layout.md ("Record only what a HIT reads").
|
|
387
403
|
*/
|
|
@@ -406,6 +422,12 @@ export interface ShellCacheEntry {
|
|
|
406
422
|
/** Capture-generation start time; tag invalidations at or after it win. */
|
|
407
423
|
createdAt: number;
|
|
408
424
|
}
|
|
425
|
+
/**
|
|
426
|
+
* @internal A shell entry without its prelude and snapshot: what a
|
|
427
|
+
* prelude-first read (SegmentCacheStore.readShellDocument) resolves with
|
|
428
|
+
* before the snapshot bytes arrive.
|
|
429
|
+
*/
|
|
430
|
+
export type ShellEntryHead = Omit<ShellCacheEntry, "prelude" | "snapshot">;
|
|
409
431
|
/**
|
|
410
432
|
* A shell entry whose document half is present — what the document HIT path
|
|
411
433
|
* (serveShellHit / lookupBuildShell) consumes. hasIntactShellPayload
|
|
@@ -437,7 +459,7 @@ export type ShellSnapshotFailure = "unavailable" | "corrupt";
|
|
|
437
459
|
*/
|
|
438
460
|
export interface ShellDocumentRead {
|
|
439
461
|
/** The entry without its prelude and snapshot (delivered separately). */
|
|
440
|
-
entry:
|
|
462
|
+
entry: ShellEntryHead;
|
|
441
463
|
/** Raw prelude bytes (empty for a navigationOnly entry). */
|
|
442
464
|
prelude: Uint8Array;
|
|
443
465
|
shouldRevalidate?: boolean;
|
|
@@ -529,14 +551,13 @@ export interface ShellReadStats {
|
|
|
529
551
|
};
|
|
530
552
|
}
|
|
531
553
|
/**
|
|
532
|
-
* The families a shell snapshot pins
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
* it would be self-referential.
|
|
554
|
+
* The families a shell snapshot pins: the doc segment record (recorded by
|
|
555
|
+
* RecordingShellStore) and the settled CONTAINER of each bake-lane loader
|
|
556
|
+
* (lane rule: see resolveLoaderData, loader-cache.ts). No cache read is
|
|
557
|
+
* pinned: a HIT's holes, and a bake-lane loader body that runs on the HIT,
|
|
558
|
+
* read the store.
|
|
538
559
|
*/
|
|
539
|
-
export type ShellSnapshotFamily = "
|
|
560
|
+
export type ShellSnapshotFamily = "segment" | "loader";
|
|
540
561
|
/**
|
|
541
562
|
* The stored form of a loader-family snapshot value: the bake-lane loader's
|
|
542
563
|
* settled container, Flight-serialized AFTER eliding every still-pending nested
|
|
@@ -552,50 +573,34 @@ export interface ShellSnapshotLoaderValue {
|
|
|
552
573
|
* container carries hole markers, so a HIT must gate the overlay on the
|
|
553
574
|
* fresh run (only the loader body can mint the live nested promises);
|
|
554
575
|
* 0 = fully pinned, so a HIT resolves the payload promise immediately from
|
|
555
|
-
* the pin and does not run the loader body (unless `runs`).
|
|
556
|
-
* pre-bit snapshots, which keep the gated path.
|
|
576
|
+
* the pin and does not run the loader body (unless `runs`).
|
|
557
577
|
*/
|
|
558
|
-
holes
|
|
578
|
+
holes: 0 | 1;
|
|
559
579
|
/**
|
|
560
580
|
* 1 when the capture saw a loader push it could not record (a deferred
|
|
561
581
|
* push, one with masked nested promises, or one made outside any loader
|
|
562
582
|
* body): a HIT then still runs the loader body in the background
|
|
563
583
|
* (pin-first) so those pushes reach the page. 0: a hole-free record is
|
|
564
|
-
* served from the pin alone and its body does not run on a HIT.
|
|
565
|
-
*
|
|
566
|
-
*
|
|
584
|
+
* served from the pin alone and its body does not run on a HIT.
|
|
585
|
+
*
|
|
586
|
+
* Both bits are always written. A record stored before they existed (v0.17)
|
|
587
|
+
* reads each missing bit as 1 (buildShellLoaderSeed): its snapshot lacks
|
|
588
|
+
* the loader-owned pushes, so the body supplies them.
|
|
567
589
|
*/
|
|
568
|
-
runs
|
|
569
|
-
}
|
|
570
|
-
/** A serialized cached Response for the response family of a shell snapshot. */
|
|
571
|
-
export interface ShellSnapshotResponseValue {
|
|
572
|
-
status: number;
|
|
573
|
-
/** Client-facing header pairs (per-client signal headers excluded at record). */
|
|
574
|
-
headers: [string, string][];
|
|
575
|
-
/** base64-encoded response body (binary-safe, JSON-serializable). */
|
|
576
|
-
body: string;
|
|
577
|
-
}
|
|
578
|
-
/** The stored form of an item-family (use cache / loader cache) snapshot value. */
|
|
579
|
-
export interface ShellSnapshotItemValue {
|
|
580
|
-
/** RSC-serialized return value. */
|
|
581
|
-
value: string;
|
|
582
|
-
/** RSC-encoded handle data, if any. */
|
|
583
|
-
handles?: string;
|
|
584
|
-
/** The entry's cache tags. */
|
|
585
|
-
tags?: string[];
|
|
590
|
+
runs: 0 | 1;
|
|
586
591
|
}
|
|
587
592
|
/**
|
|
588
|
-
* One
|
|
589
|
-
* carries
|
|
590
|
-
* JSON-serializing store (KV, CF, Vercel) with the rest of the
|
|
591
|
-
*
|
|
593
|
+
* One snapshot record: the doc segment record or a bake-lane loader pin.
|
|
594
|
+
* `value` carries it in its stored/serialized shape so it round-trips
|
|
595
|
+
* through a JSON-serializing store (KV, CF, Vercel) with the rest of the
|
|
596
|
+
* ShellCacheEntry:
|
|
592
597
|
* - `segment` -> {@link CachedEntryData} (already JSON-able)
|
|
593
|
-
* - `
|
|
598
|
+
* - `loader` -> {@link ShellSnapshotLoaderValue}
|
|
594
599
|
*/
|
|
595
600
|
export interface ShellSnapshotRecord {
|
|
596
601
|
family: ShellSnapshotFamily;
|
|
597
602
|
key: string;
|
|
598
|
-
value:
|
|
603
|
+
value: CachedEntryData | ShellSnapshotLoaderValue;
|
|
599
604
|
}
|
|
600
605
|
/**
|
|
601
606
|
* Options for setItem() for function-level caching ("use cache").
|
|
@@ -691,8 +696,10 @@ export type SegmentHandleData = Record<string, unknown[]>;
|
|
|
691
696
|
* index (null: not owned). Only a PPR shell capture writes owners: the
|
|
692
697
|
* settled pushes of the loader bodies it ran (an `ssr: false` loader's own,
|
|
693
698
|
* the loaders it awaits, and its own cache() replays), which the record keeps
|
|
694
|
-
* because the prelude rendered them.
|
|
695
|
-
* through HandleStore.
|
|
696
|
-
*
|
|
699
|
+
* because the prelude rendered them. A document HIT restores a bake-lane
|
|
700
|
+
* owner's value through HandleStore.pushRestored, and it stands against a run
|
|
701
|
+
* of its loader there; a live-lane owner's (a hole), and every owner's on
|
|
702
|
+
* any other replay of the record (a client navigation), go through
|
|
703
|
+
* pushReplayed, so a run of the loader replaces it with its live push.
|
|
697
704
|
*/
|
|
698
705
|
export type HandleOwners = Record<string, Record<string, (string | null)[]>>;
|