@rangojs/router 0.21.0 → 0.22.1
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/bin/rango.js +13 -1
- package/dist/types/browser/event-controller.d.ts +30 -13
- package/dist/types/browser/navigation-store.d.ts +9 -0
- package/dist/types/browser/partial-update.d.ts +2 -1
- package/dist/types/browser/prefetch/default-strategy.d.ts +16 -20
- package/dist/types/browser/react/NavigationProvider.d.ts +14 -1
- package/dist/types/browser/react/context.d.ts +14 -0
- package/dist/types/browser/rsc-router.d.ts +13 -2
- package/dist/types/browser/types.d.ts +10 -0
- package/dist/types/build/generate-manifest.d.ts +2 -0
- package/dist/types/cache/background-task.d.ts +22 -0
- package/dist/types/cache/cache-key-utils.d.ts +50 -5
- package/dist/types/cache/cache-policy.d.ts +17 -0
- package/dist/types/cache/cache-scope.d.ts +1 -1
- package/dist/types/cache/cf/cf-cache-store.d.ts +7 -1
- package/dist/types/cache/document-cache.d.ts +8 -5
- package/dist/types/cache/handle-snapshot.d.ts +23 -0
- package/dist/types/cache/index.d.ts +1 -1
- package/dist/types/cache/invalidation-order.d.ts +14 -0
- package/dist/types/cache/memory-segment-store.d.ts +33 -1
- package/dist/types/cache/shell-snapshot.d.ts +10 -1
- package/dist/types/cache/store-scope.d.ts +22 -0
- package/dist/types/cache/tag-invalidation.d.ts +7 -6
- package/dist/types/cache/types.d.ts +63 -14
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +7 -1
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/handles/deferred-resolution.d.ts +7 -0
- package/dist/types/internal-suspense-audit.d.ts +1 -0
- package/dist/types/loader-store.d.ts +4 -8
- package/dist/types/outlet-provider.d.ts +2 -1
- package/dist/types/prerender/cloudflare.d.ts +49 -0
- package/dist/types/prerender/create-prerender-trigger.d.ts +121 -0
- package/dist/types/prerender/index.d.ts +12 -0
- package/dist/types/prerender/memory-prerender-store.d.ts +29 -0
- package/dist/types/prerender/on-demand.d.ts +272 -0
- package/dist/types/prerender/producer-guard.d.ts +33 -0
- package/dist/types/prerender/shell-manifest-key.d.ts +1 -18
- package/dist/types/prerender/warm-request.d.ts +65 -0
- package/dist/types/prerender/warm.d.ts +65 -0
- package/dist/types/prerender/writable-store.d.ts +170 -0
- package/dist/types/prerender.d.ts +27 -0
- package/dist/types/reverse.d.ts +1 -1
- package/dist/types/route-content-wrapper.d.ts +3 -1
- package/dist/types/router/error-handling.d.ts +2 -0
- package/dist/types/router/handler-context.d.ts +1 -1
- package/dist/types/router/match-middleware/cache-lookup.d.ts +14 -0
- package/dist/types/router/pattern-matching.d.ts +2 -0
- package/dist/types/router/prefetch-default.d.ts +4 -4
- package/dist/types/router/prerender-match.d.ts +23 -1
- package/dist/types/router/route-trie-builder.d.ts +8 -1
- package/dist/types/router/router-context.d.ts +1 -0
- package/dist/types/router/router-interfaces.d.ts +30 -0
- package/dist/types/router/router-options.d.ts +24 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +7 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +2 -1
- package/dist/types/router/segment-resolution/revalidation.d.ts +5 -1
- package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +43 -0
- package/dist/types/router/trie-matching.d.ts +2 -0
- package/dist/types/rsc/shell-build-manifest.d.ts +6 -4
- package/dist/types/rsc/shell-capture-constants.d.ts +20 -5
- package/dist/types/rsc/shell-capture.d.ts +14 -1
- package/dist/types/rsc/shell-serve.d.ts +2 -2
- package/dist/types/rsc/ssr-module-loader.d.ts +15 -0
- package/dist/types/rsc/types.d.ts +8 -0
- package/dist/types/segment-boundary-content.d.ts +17 -0
- package/dist/types/segment-loader-promise.d.ts +2 -6
- package/dist/types/server/build-version-table.d.ts +9 -0
- package/dist/types/server/context.d.ts +12 -4
- package/dist/types/server/handle-store.d.ts +2 -0
- package/dist/types/server/request-context.d.ts +63 -2
- package/dist/types/suspense-audit-react.d.ts +26 -0
- package/dist/types/suspense-audit.d.ts +157 -0
- package/dist/types/testing/action-form.d.ts +34 -0
- package/dist/types/testing/flight.entry.d.ts +2 -0
- package/dist/types/testing/index.d.ts +4 -0
- package/dist/types/testing/internal/server-modules.d.ts +8 -0
- package/dist/types/testing/serve-shell-request.d.ts +34 -4
- package/dist/types/testing/shell-status.d.ts +14 -6
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +9 -6
- package/dist/types/thenable-status.d.ts +6 -0
- package/dist/types/types/handler-context.d.ts +7 -0
- package/dist/types/types/route-entry.d.ts +5 -0
- package/dist/types/urls/path-helper.d.ts +18 -0
- package/dist/types/vite/discovery/state.d.ts +11 -0
- package/dist/types/vite/inject-client-debug.d.ts +6 -25
- package/dist/types/vite/utils/bundle-analysis.d.ts +6 -2
- package/dist/vite/index.js +180 -497
- package/package.json +13 -3
- package/skills/cache-guide/SKILL.md +18 -17
- package/skills/caching/SKILL.md +40 -4
- package/skills/catalog.json +1 -1
- package/skills/cloudflare/SKILL.md +131 -0
- package/skills/comparison/references/framework-comparison.md +1 -1
- package/skills/deployment-caching/SKILL.md +33 -12
- package/skills/document-cache/SKILL.md +16 -14
- package/skills/hooks/SKILL.md +22 -0
- package/skills/hooks/handle-and-actions.md +3 -4
- package/skills/hooks/navigation.md +10 -0
- package/skills/hooks/state.md +5 -4
- package/skills/host-router/SKILL.md +18 -0
- package/skills/loader/SKILL.md +6 -4
- package/skills/middleware/SKILL.md +1 -1
- package/skills/migrate-nextjs/SKILL.md +82 -9
- package/skills/ppr/SKILL.md +31 -8
- package/skills/prerender/SKILL.md +645 -8
- package/skills/rango/SKILL.md +1 -0
- package/skills/response-routes/SKILL.md +5 -5
- package/skills/route/SKILL.md +29 -0
- package/skills/testing/SKILL.md +2 -1
- package/skills/testing/cache-prerender.md +18 -17
- package/skills/testing/serve-shell-request.md +104 -8
- package/skills/use-cache/SKILL.md +9 -5
- package/skills/vercel/SKILL.md +2 -0
- package/skills/view-transitions/SKILL.md +9 -4
- package/src/browser/event-controller.ts +69 -25
- package/src/browser/link-interceptor.ts +2 -2
- package/src/browser/navigation-bridge.ts +75 -35
- package/src/browser/navigation-store.ts +26 -0
- package/src/browser/navigation-transaction.ts +9 -2
- package/src/browser/network-error-handler.ts +2 -0
- package/src/browser/partial-update.ts +48 -12
- package/src/browser/prefetch/default-strategy.ts +22 -42
- package/src/browser/react/Link.tsx +37 -42
- package/src/browser/react/NavigationProvider.tsx +63 -3
- package/src/browser/react/context.ts +17 -0
- package/src/browser/react/location-state.ts +5 -19
- package/src/browser/react/use-action.ts +4 -1
- package/src/browser/react/use-handle.ts +4 -20
- package/src/browser/react/use-link-status.ts +4 -3
- package/src/browser/react/use-navigation.ts +4 -1
- package/src/browser/react/use-params.ts +4 -1
- package/src/browser/react/use-pathname.ts +4 -1
- package/src/browser/react/use-search-params.ts +5 -3
- package/src/browser/react/use-segments.ts +36 -54
- package/src/browser/rsc-router.tsx +79 -39
- package/src/browser/segment-reconciler.ts +3 -3
- package/src/browser/server-action-bridge.ts +26 -6
- package/src/browser/types.ts +11 -0
- package/src/build/generate-manifest.ts +17 -0
- package/src/build/merge-full-manifests.ts +5 -0
- package/src/build/route-trie.ts +1 -0
- package/src/cache/background-task.ts +61 -0
- package/src/cache/cache-key-utils.ts +91 -12
- package/src/cache/cache-policy.ts +11 -2
- package/src/cache/cache-runtime.ts +23 -23
- package/src/cache/cache-scope.ts +38 -36
- package/src/cache/cf/cf-cache-store.ts +16 -11
- package/src/cache/document-cache.ts +35 -14
- package/src/cache/handle-snapshot.ts +50 -0
- package/src/cache/index.ts +1 -0
- package/src/cache/invalidation-order.ts +53 -0
- package/src/cache/memory-segment-store.ts +52 -1
- package/src/cache/shell-snapshot.ts +17 -0
- package/src/cache/store-scope.ts +36 -0
- package/src/cache/tag-invalidation.ts +7 -5
- package/src/cache/types.ts +69 -14
- package/src/cache/vercel/vercel-cache-store.ts +20 -6
- package/src/client.tsx +40 -3
- package/src/errors.ts +13 -6
- package/src/handles/deferred-resolution.ts +7 -2
- package/src/internal-suspense-audit.ts +12 -0
- package/src/loader-store.ts +4 -9
- package/src/outlet-provider.tsx +25 -1
- package/src/prerender/cloudflare.ts +130 -0
- package/src/prerender/create-prerender-trigger.ts +780 -0
- package/src/prerender/index.ts +39 -0
- package/src/prerender/memory-prerender-store.ts +115 -0
- package/src/prerender/on-demand.ts +339 -0
- package/src/prerender/producer-guard.ts +66 -0
- package/src/prerender/shell-manifest-key.ts +12 -17
- package/src/prerender/warm-request.ts +154 -0
- package/src/prerender/warm.ts +193 -0
- package/src/prerender/writable-store.ts +278 -0
- package/src/prerender.ts +29 -0
- package/src/reverse.ts +1 -1
- package/src/route-content-wrapper.tsx +107 -13
- package/src/router/error-handling.ts +12 -12
- package/src/router/find-match.ts +1 -0
- package/src/router/handler-context.ts +2 -0
- package/src/router/intercept-resolution.ts +15 -8
- package/src/router/loader-resolution.ts +2 -10
- package/src/router/match-middleware/background-revalidation.ts +2 -0
- package/src/router/match-middleware/cache-lookup.ts +230 -38
- package/src/router/pattern-matching.ts +14 -0
- package/src/router/prefetch-default.ts +4 -4
- package/src/router/prerender-match.ts +460 -352
- package/src/router/route-trie-builder.ts +9 -0
- package/src/router/router-context.ts +1 -0
- package/src/router/router-interfaces.ts +33 -0
- package/src/router/router-options.ts +30 -0
- package/src/router/segment-resolution/fresh.ts +20 -19
- package/src/router/segment-resolution/loader-cache.ts +15 -17
- package/src/router/segment-resolution/revalidation.ts +34 -24
- package/src/router/segment-resolution/streamed-handler-boundary.ts +133 -0
- package/src/router/trie-matching.ts +3 -0
- package/src/router.ts +107 -1
- package/src/rsc/handler.ts +51 -4
- package/src/rsc/progressive-enhancement.ts +5 -1
- package/src/rsc/response-cache-serve.ts +10 -4
- package/src/rsc/rsc-rendering.ts +53 -11
- package/src/rsc/shell-build-manifest.ts +10 -8
- package/src/rsc/shell-capture-constants.ts +39 -7
- package/src/rsc/shell-capture.ts +108 -19
- package/src/rsc/shell-serve.ts +12 -6
- package/src/rsc/ssr-module-loader.ts +26 -0
- package/src/rsc/types.ts +8 -0
- package/src/segment-boundary-content.ts +25 -0
- package/src/segment-loader-promise.ts +28 -38
- package/src/segment-system.tsx +117 -57
- package/src/server/build-version-table.ts +15 -0
- package/src/server/context.ts +40 -17
- package/src/server/cookie-store.ts +5 -0
- package/src/server/handle-store.ts +13 -0
- package/src/server/loader-registry.ts +6 -1
- package/src/server/request-context.ts +87 -1
- package/src/ssr/ssr-root.tsx +20 -13
- package/src/suspense-audit-react.tsx +98 -0
- package/src/suspense-audit.ts +1030 -0
- package/src/testing/action-form.ts +66 -0
- package/src/testing/flight-runtime.d.ts +27 -0
- package/src/testing/flight.entry.ts +3 -0
- package/src/testing/index.ts +19 -0
- package/src/testing/internal/server-modules.ts +32 -0
- package/src/testing/render-route.tsx +25 -12
- package/src/testing/serve-shell-request.ts +190 -34
- package/src/testing/shell-status.ts +17 -6
- package/src/testing/vitest-stubs/plugin-rsc.ts +37 -11
- package/src/thenable-status.ts +10 -0
- package/src/types/handler-context.ts +7 -0
- package/src/types/route-entry.ts +6 -0
- package/src/urls/path-helper.ts +69 -9
- package/src/use-loader.tsx +57 -30
- package/src/vite/discovery/bundle-postprocess.ts +4 -0
- package/src/vite/discovery/discover-routers.ts +15 -0
- package/src/vite/discovery/shell-prerender-phase.ts +5 -5
- package/src/vite/discovery/state.ts +17 -1
- package/src/vite/inject-client-debug.ts +42 -20
- package/src/vite/plugins/virtual-entries.ts +8 -1
- package/src/vite/router-discovery.ts +14 -0
- package/src/vite/utils/bundle-analysis.ts +39 -7
- package/dist/types/browser/react/subscribe-to-nothing.d.ts +0 -7
- package/dist/types/segment-content-promise.d.ts +0 -13
- package/src/browser/react/subscribe-to-nothing.ts +0 -7
- package/src/segment-content-promise.ts +0 -67
package/dist/bin/rango.js
CHANGED
|
@@ -1571,6 +1571,11 @@ function mergeFullManifests(manifests) {
|
|
|
1571
1571
|
manifest.passthroughRoutes,
|
|
1572
1572
|
overwrittenRoutes
|
|
1573
1573
|
),
|
|
1574
|
+
onDemandRoutes: mergeRouteList(
|
|
1575
|
+
merged.onDemandRoutes,
|
|
1576
|
+
manifest.onDemandRoutes,
|
|
1577
|
+
overwrittenRoutes
|
|
1578
|
+
),
|
|
1574
1579
|
responseTypeRoutes: mergeRouteRecord(
|
|
1575
1580
|
merged.responseTypeRoutes,
|
|
1576
1581
|
manifest.responseTypeRoutes,
|
|
@@ -1653,6 +1658,12 @@ async function initializeApp() {
|
|
|
1653
1658
|
// is the default; createRouter({ strictMode: false }) ships the opt-out in the
|
|
1654
1659
|
// payload metadata. StrictMode emits no DOM, so toggling never changes markup.
|
|
1655
1660
|
const { strictMode, initialPayload } = await initBrowserApp({ rscStream, deps });
|
|
1661
|
+
// Set only on a document a no-JS useActionState POST rendered: React needs
|
|
1662
|
+
// the server's form state to hydrate the hook without resetting it. A state
|
|
1663
|
+
// Flight could not carry rejects: hydrate without it, as before.
|
|
1664
|
+
const formState = await Promise.resolve(initialPayload.formState).catch(
|
|
1665
|
+
() => undefined
|
|
1666
|
+
);
|
|
1656
1667
|
|
|
1657
1668
|
if (import.meta.hot) {
|
|
1658
1669
|
const { startDevDiscoveryHandshake } = await import(
|
|
@@ -1667,7 +1678,8 @@ async function initializeApp() {
|
|
|
1667
1678
|
const app = createElement(Rango);
|
|
1668
1679
|
hydrateRoot(
|
|
1669
1680
|
document,
|
|
1670
|
-
strictMode === false ? app : createElement(StrictMode, null, app)
|
|
1681
|
+
strictMode === false ? app : createElement(StrictMode, null, app),
|
|
1682
|
+
formState ? { formState } : undefined
|
|
1671
1683
|
);
|
|
1672
1684
|
}
|
|
1673
1685
|
|
|
@@ -102,6 +102,15 @@ export interface HandleState {
|
|
|
102
102
|
segmentOrder: string[];
|
|
103
103
|
routeSegmentIds: string[];
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* What the document's HTML was rendered with, kept for the hydration window
|
|
107
|
+
* (EventController.lockHydration).
|
|
108
|
+
*/
|
|
109
|
+
export interface HydrationSnapshot {
|
|
110
|
+
state: DerivedNavigationState;
|
|
111
|
+
params: Record<string, string>;
|
|
112
|
+
handles: HandleState;
|
|
113
|
+
}
|
|
105
114
|
/**
|
|
106
115
|
* Result from starting a navigation
|
|
107
116
|
* Implements Disposable for use with `using` keyword
|
|
@@ -198,22 +207,30 @@ export interface EventController {
|
|
|
198
207
|
resolvedIds?: string[]): void;
|
|
199
208
|
getHandleState(): HandleState;
|
|
200
209
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
210
|
+
* Open the hydration window. Until releaseHydrationLock(), getHandleState()
|
|
211
|
+
* returns the state the document's HTML was rendered with, and handle writes
|
|
212
|
+
* (setHandleData, setRouteSegmentIds) wait in order. initBrowserApp opens it
|
|
213
|
+
* before hydrateRoot, once the document's handle snapshot is applied: a hook
|
|
214
|
+
* reading the handle state when its boundary hydrates, however late, reads
|
|
215
|
+
* what SSR rendered (issue #1035).
|
|
216
|
+
*/
|
|
217
|
+
lockHydration(): void;
|
|
218
|
+
/**
|
|
219
|
+
* While the hydration window is open, the state the document's HTML was
|
|
220
|
+
* rendered with; undefined once it closes. A router hook's first render
|
|
221
|
+
* reads it: a component hydrating in a boundary that streamed in late
|
|
222
|
+
* renders what SSR rendered, even after a navigation or an action started.
|
|
223
|
+
* The hook's effect then catches up with the live state, and its
|
|
224
|
+
* subscription stays live, so pending UI is not held back.
|
|
204
225
|
*/
|
|
205
|
-
|
|
226
|
+
getHydrationSnapshot(): HydrationSnapshot | undefined;
|
|
206
227
|
/**
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
* (useHandle), whenever its boundary hydrates: the late handle channel
|
|
212
|
-
* (rsc-router.tsx) waits for the root to hydrate, not for a `<Suspense>`
|
|
213
|
-
* boundary that hydrates after it, and by then the live state can hold
|
|
214
|
-
* values that boundary's HTML does not (issue #1035).
|
|
228
|
+
* Close the hydration window: apply the writes that waited, in order, and
|
|
229
|
+
* notify handle subscribers. NavigationProvider calls it after the commit
|
|
230
|
+
* that made React hydrate every boundary still dehydrated (its barrier).
|
|
231
|
+
* Idempotent.
|
|
215
232
|
*/
|
|
216
|
-
|
|
233
|
+
releaseHydrationLock(): void;
|
|
217
234
|
/**
|
|
218
235
|
* Update ONLY `routeSegmentIds` (what `useSegments` reads) from `matched`,
|
|
219
236
|
* leaving `data` and `segmentOrder` (what `useHandle` collects over) untouched.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { NavigationStore, ResolvedSegment, HandleData } from "./types.js";
|
|
2
|
+
import type { EventController } from "./event-controller.js";
|
|
2
3
|
/**
|
|
3
4
|
* Clone the handleData CONTAINERS (the handle-name map and each segment map) so
|
|
4
5
|
* a cache entry is decoupled from the live map that eventController mutates — it
|
|
@@ -11,6 +12,14 @@ import type { NavigationStore, ResolvedSegment, HandleData } from "./types.js";
|
|
|
11
12
|
* non-serializable bucket contents (React elements, functions, etc.).
|
|
12
13
|
*/
|
|
13
14
|
export declare function cloneHandleData(handleData: HandleData): HandleData;
|
|
15
|
+
/**
|
|
16
|
+
* Handle data to write into the history cache for the page on screen. During
|
|
17
|
+
* the hydration window getHandleState() is the document snapshot while late
|
|
18
|
+
* pushes sit queued in the controller (they are already in the cache entry,
|
|
19
|
+
* written by rsc-router), so writing the snapshot back would drop them; the
|
|
20
|
+
* entry's own data is the live view then.
|
|
21
|
+
*/
|
|
22
|
+
export declare function liveHandleDataForCache(eventController: Pick<EventController, "getHandleState" | "getHydrationSnapshot">, store: Pick<NavigationStore, "getCachedSegments">, historyKey: string): HandleData;
|
|
14
23
|
/**
|
|
15
24
|
* Options for generating a history key
|
|
16
25
|
*/
|
|
@@ -3,6 +3,7 @@ import type { ReactNode } from "react";
|
|
|
3
3
|
import type { RenderSegmentsOptions } from "../segment-system.js";
|
|
4
4
|
import type { BoundTransaction } from "./navigation-transaction.js";
|
|
5
5
|
import type { NavigationUpdate } from "./types.js";
|
|
6
|
+
import type { LoaderStore } from "../loader-store.js";
|
|
6
7
|
import { type TransitionWhenActionInput } from "./transition-when.js";
|
|
7
8
|
/**
|
|
8
9
|
* Hold/animate decision for a commit: a non-intercept segment carries a
|
|
@@ -18,7 +19,7 @@ export declare function shouldStartViewTransition(segments: readonly ResolvedSeg
|
|
|
18
19
|
* directly: nothing is held there, a reader of a pending stream suspends to
|
|
19
20
|
* its fallback. Also used by renderRoute's navigate() (testing/render-route.tsx).
|
|
20
21
|
*/
|
|
21
|
-
export declare function commitInTransition(onUpdate: UpdateSubscriber, segments: readonly ResolvedSegment[], update: NavigationUpdate, transitionTypes: readonly string[]): void;
|
|
22
|
+
export declare function commitInTransition(loaders: LoaderStore, onUpdate: UpdateSubscriber, segments: readonly ResolvedSegment[], update: NavigationUpdate, transitionTypes: readonly string[]): void;
|
|
22
23
|
/**
|
|
23
24
|
* Configuration for creating a partial updater
|
|
24
25
|
*/
|
|
@@ -2,30 +2,26 @@
|
|
|
2
2
|
* Router-wide default prefetch strategy (client seat).
|
|
3
3
|
*
|
|
4
4
|
* The server resolves `createRouter({ defaultPrefetch })` once at router init
|
|
5
|
-
* (router/prefetch-default.ts) and ships it in initial payload metadata
|
|
6
|
-
*
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* `data-prefetch-scope`.
|
|
12
|
-
*
|
|
13
|
-
* The module initial value must equal the server resolver's environment default:
|
|
14
|
-
* `"none"` in development and `"viewport"` in production. During SSR this
|
|
15
|
-
* module is never initialized from metadata, so keeping both seats aligned also
|
|
16
|
-
* gives metadata-less payloads the documented behavior.
|
|
5
|
+
* (router/prefetch-default.ts) and ships it in initial payload metadata. The
|
|
6
|
+
* router store carries it to its readers: `<Link>` reads
|
|
7
|
+
* `NavigationStoreContext.defaultPrefetch`, and delegated plain anchors get it
|
|
8
|
+
* from the navigation bridge. Every `<Link>` without an explicit `prefetch`
|
|
9
|
+
* prop and every eligible intercepted plain anchor that has not opted out with
|
|
10
|
+
* `data-prefetch="false"` or `data-prefetch="none"` uses it. Containers use the
|
|
11
|
+
* same `false`/`none` vocabulary via `data-prefetch-scope`.
|
|
17
12
|
*/
|
|
18
13
|
import type { PrefetchStrategy } from "../../router/prefetch-default.js";
|
|
19
|
-
/** Reset module state between tests that replace browser media globals. */
|
|
20
|
-
export declare function resetAdaptiveStrategyForTesting(): void;
|
|
21
14
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
15
|
+
* The default for a payload without `defaultPrefetch`: the server resolver's
|
|
16
|
+
* environment default (`"none"` in development, `"viewport"` in production),
|
|
17
|
+
* mirrored without pulling router-layer code into the client bundle. NODE_ENV
|
|
18
|
+
* is folded by the app build.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ENVIRONMENT_DEFAULT_PREFETCH: PrefetchStrategy;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve adaptive to the strategy for the current input capability. Called
|
|
23
|
+
* when a prefetch is armed or triggered, never during render.
|
|
24
24
|
*/
|
|
25
|
-
export declare function setDefaultPrefetchStrategy(strategy: PrefetchStrategy): void;
|
|
26
|
-
/** Current default strategy for Links and delegated plain anchors. */
|
|
27
|
-
export declare function getDefaultPrefetchStrategy(): PrefetchStrategy;
|
|
28
|
-
/** Resolve adaptive to the strategy for the current input capability. */
|
|
29
25
|
export declare function resolveAdaptiveStrategy(strategy: PrefetchStrategy): PrefetchStrategy;
|
|
30
26
|
/** Subscribe to changes in the input capability used by adaptive prefetch. */
|
|
31
27
|
export declare function subscribeToAdaptiveStrategyChange(listener: () => void): () => void;
|
|
@@ -63,6 +63,19 @@ export interface NavigationProviderProps {
|
|
|
63
63
|
* it to seed a nonce so components calling useNonce() can be exercised.
|
|
64
64
|
*/
|
|
65
65
|
nonce?: string;
|
|
66
|
+
/**
|
|
67
|
+
* The document this provider hydrates (initBrowserApp; renderRoute with
|
|
68
|
+
* `hydrate: true`), whose store EventController.lockHydration locked.
|
|
69
|
+
* `settled` resolves once the stream has ended and React has revealed every
|
|
70
|
+
* boundary. Until then location state is `undefined`, as SSR rendered it;
|
|
71
|
+
* then one transition gives the entry's state and changes
|
|
72
|
+
* HydrationBarrierContext, and the store is released after that commit. A
|
|
73
|
+
* navigation committed earlier releases the store before its update.
|
|
74
|
+
* Absent for a provider mounted on the client.
|
|
75
|
+
*/
|
|
76
|
+
hydration?: {
|
|
77
|
+
settled: Promise<void>;
|
|
78
|
+
};
|
|
66
79
|
}
|
|
67
80
|
/**
|
|
68
81
|
* Navigation provider component
|
|
@@ -85,4 +98,4 @@ export interface NavigationProviderProps {
|
|
|
85
98
|
* />
|
|
86
99
|
* ```
|
|
87
100
|
*/
|
|
88
|
-
export declare function NavigationProvider({ store, eventController, initialPayload, bridge, themeConfig, initialTheme, warmupEnabled, version, basename, appShellRef, nonce, }: NavigationProviderProps): ReactNode;
|
|
101
|
+
export declare function NavigationProvider({ store, eventController, initialPayload, bridge, themeConfig, initialTheme, warmupEnabled, version, basename, appShellRef, nonce, hydration, }: NavigationProviderProps): ReactNode;
|
|
@@ -48,6 +48,12 @@ export interface NavigationStoreContextValue {
|
|
|
48
48
|
basename: string | undefined;
|
|
49
49
|
/** Router default from this instance's initial payload. */
|
|
50
50
|
defaultPrefetch?: PrefetchStrategy;
|
|
51
|
+
/**
|
|
52
|
+
* The document's origin, fixed for its lifetime. Link compares absolute
|
|
53
|
+
* hrefs against it (data-external) and useLinkStatus resolves link targets
|
|
54
|
+
* with it.
|
|
55
|
+
*/
|
|
56
|
+
origin: string | undefined;
|
|
51
57
|
}
|
|
52
58
|
/**
|
|
53
59
|
* React context for navigation store
|
|
@@ -66,3 +72,11 @@ export declare const NavigationStoreContext: Context<NavigationStoreContextValue
|
|
|
66
72
|
* (#1029). Undefined on the server and outside a provider.
|
|
67
73
|
*/
|
|
68
74
|
export declare const LocationStateContext: Context<LocationStateSnapshot>;
|
|
75
|
+
/**
|
|
76
|
+
* Read by no component. NavigationProvider changes its value in a transition so
|
|
77
|
+
* that React hydrates every boundary still dehydrated beneath it before that
|
|
78
|
+
* commit: React hydrates a dehydrated boundary first when a provider above it
|
|
79
|
+
* changes, and nothing re-renders for a value nobody reads. See
|
|
80
|
+
* NavigationProviderProps.hydration.
|
|
81
|
+
*/
|
|
82
|
+
export declare const HydrationBarrierContext: Context<number>;
|
|
@@ -95,6 +95,12 @@ export interface BrowserAppContext {
|
|
|
95
95
|
* prefetch TTL are document-lifetime too (see AppShell).
|
|
96
96
|
*/
|
|
97
97
|
appShellRef?: import("./app-shell.js").AppShellRef;
|
|
98
|
+
/**
|
|
99
|
+
* Resolves when the document's stream has ended and every Suspense boundary
|
|
100
|
+
* in it has been revealed. NavigationProvider closes the hydration window
|
|
101
|
+
* then (NavigationProviderProps.hydration).
|
|
102
|
+
*/
|
|
103
|
+
documentRevealed: Promise<void>;
|
|
98
104
|
}
|
|
99
105
|
/**
|
|
100
106
|
* Initialize the browser app. Must be called before rendering Rango.
|
|
@@ -131,13 +137,18 @@ export interface RangoProps {
|
|
|
131
137
|
* import * as rscBrowser from "@vitejs/plugin-rsc/browser";
|
|
132
138
|
*
|
|
133
139
|
* async function main() {
|
|
134
|
-
* await initBrowserApp({ rscStream, deps: rscBrowser });
|
|
140
|
+
* const { initialPayload } = await initBrowserApp({ rscStream, deps: rscBrowser });
|
|
141
|
+
* // Rejects when the action's state is not Flight-serializable.
|
|
142
|
+
* const formState = await Promise.resolve(initialPayload.formState).catch(
|
|
143
|
+
* () => undefined,
|
|
144
|
+
* );
|
|
135
145
|
*
|
|
136
146
|
* hydrateRoot(
|
|
137
147
|
* document,
|
|
138
148
|
* <React.StrictMode>
|
|
139
149
|
* <Rango />
|
|
140
|
-
* </React.StrictMode
|
|
150
|
+
* </React.StrictMode>,
|
|
151
|
+
* formState ? { formState } : undefined
|
|
141
152
|
* );
|
|
142
153
|
* }
|
|
143
154
|
* main();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode, ComponentType } from "react";
|
|
2
|
+
import type { ReactFormState } from "react-dom/client";
|
|
2
3
|
import type { ResolvedSegment, SlotState } from "../types.js";
|
|
3
4
|
import type { ResolvedThemeConfig, Theme } from "../theme/types.js";
|
|
4
5
|
import type { RenderSegmentsOptions } from "../segment-system.js";
|
|
@@ -9,6 +10,11 @@ import type { RenderSegmentsOptions } from "../segment-system.js";
|
|
|
9
10
|
export interface RscPayload<TMetadata = RscMetadata> {
|
|
10
11
|
metadata?: TMetadata;
|
|
11
12
|
returnValue?: ActionResult;
|
|
13
|
+
/**
|
|
14
|
+
* Form state of a PE POST document, for hydrateRoot's `formState` option.
|
|
15
|
+
* Rejects when the action's state is not Flight-serializable.
|
|
16
|
+
*/
|
|
17
|
+
formState?: Promise<ReactFormState>;
|
|
12
18
|
}
|
|
13
19
|
/**
|
|
14
20
|
* Handle data structure: handleName -> segmentId -> entries[]
|
|
@@ -406,6 +412,8 @@ export interface NavigateOptionsInternal extends Omit<NavigateOptions, "state">
|
|
|
406
412
|
state?: unknown;
|
|
407
413
|
/** Skip segment cache (used by redirect-with-state to force re-render) */
|
|
408
414
|
_skipCache?: boolean;
|
|
415
|
+
/** Server redirects already followed by this navigation chain (0 for a user navigation) */
|
|
416
|
+
_redirectHops?: number;
|
|
409
417
|
}
|
|
410
418
|
/**
|
|
411
419
|
* Options for useRouter push/replace methods.
|
|
@@ -476,6 +484,8 @@ export type StateListener = () => void;
|
|
|
476
484
|
* EventController owns the public navigation lifecycle exposed by hooks.
|
|
477
485
|
*/
|
|
478
486
|
export interface NavigationStore {
|
|
487
|
+
/** Client loader data for useLoader / useFetchLoader (loader-store.ts). */
|
|
488
|
+
readonly loaders: import("../loader-store.js").LoaderStore;
|
|
479
489
|
getSegmentState(): SegmentState;
|
|
480
490
|
setPath(path: string): void;
|
|
481
491
|
setCurrentUrl(url: string): void;
|
|
@@ -37,6 +37,8 @@ export interface GeneratedManifest {
|
|
|
37
37
|
prerenderRoutes?: string[];
|
|
38
38
|
/** Route names wrapped with Passthrough() (live handler for runtime fallback) */
|
|
39
39
|
passthroughRoutes?: string[];
|
|
40
|
+
/** Route names opted into on-demand prerender (Prerender(..., { onDemand })) */
|
|
41
|
+
onDemandRoutes?: string[];
|
|
40
42
|
/** Route name → response type for non-RSC routes */
|
|
41
43
|
responseTypeRoutes?: Record<string, string>;
|
|
42
44
|
/** Route name -> search schema descriptor for typed URL helpers */
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* settleGrowing). When waitUntil is unavailable, falls back to blocking or
|
|
7
7
|
* skipping.
|
|
8
8
|
*/
|
|
9
|
+
import type { ExecutionContext } from "../types/request-scope.js";
|
|
9
10
|
interface WaitUntilHost {
|
|
10
11
|
waitUntil?: (fn: () => Promise<void>) => void;
|
|
11
12
|
}
|
|
@@ -40,4 +41,25 @@ export declare function raceDeadline<T>(work: Promise<T>, deadline: number): Pro
|
|
|
40
41
|
* mutates `list`: a later call waits for what is still pending.
|
|
41
42
|
*/
|
|
42
43
|
export declare function settleGrowing(list: readonly Promise<unknown>[], deadline: number): Promise<boolean>;
|
|
44
|
+
/** Macrotask turns `awaitLaterMillisecond` waits at most. */
|
|
45
|
+
export declare const LATER_MILLISECOND_MAX_TURNS = 10;
|
|
46
|
+
/**
|
|
47
|
+
* Yield until `Date.now()` passes `since`, so a store's whole-millisecond tag
|
|
48
|
+
* gate (putShell vs an invalidation made just before) sees a later
|
|
49
|
+
* millisecond. Bounded: on Cloudflare the clock stands still between I/O
|
|
50
|
+
* events, so an unbounded wait could hang. At the bound the caller proceeds
|
|
51
|
+
* and a store may refuse the write, which its result reports.
|
|
52
|
+
*/
|
|
53
|
+
export declare function awaitLaterMillisecond(since: number, maxTurns?: number): Promise<void>;
|
|
54
|
+
/** An ExecutionContext that keeps every promise handed to `waitUntil`. */
|
|
55
|
+
export interface CollectingExecutionContext extends ExecutionContext {
|
|
56
|
+
readonly tasks: Promise<unknown>[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Wrap the caller's ExecutionContext (or none) so a caller can wait for the
|
|
60
|
+
* request's background work: the deferred cache writes, the shell capture, a
|
|
61
|
+
* store's own writes. Every other member reads through to `inner`, bound to
|
|
62
|
+
* it (workerd's methods reject a foreign `this`).
|
|
63
|
+
*/
|
|
64
|
+
export declare function createCollectingExecutionContext(inner?: ExecutionContext): CollectingExecutionContext;
|
|
43
65
|
export {};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* Used by cache-runtime, cache-scope, document-cache, and loader-cache.
|
|
7
7
|
*/
|
|
8
8
|
import type { SearchParamsFilter } from "./search-params-filter.js";
|
|
9
|
+
export declare function isReservedSearchParam(key: string): boolean;
|
|
9
10
|
/**
|
|
10
11
|
* Build a sorted, deterministic query string from URLSearchParams,
|
|
11
12
|
* excluding the router's reserved params (see isReservedSearchParam).
|
|
@@ -27,11 +28,40 @@ export declare function sortedSearchString(searchParams: URLSearchParams, filter
|
|
|
27
28
|
*/
|
|
28
29
|
export declare function sortedRouteParams(params: Record<string, string> | undefined): string;
|
|
29
30
|
/**
|
|
30
|
-
*
|
|
31
|
+
* THE ROUTER RULE (#1065). A key that names one router's output for a host
|
|
32
|
+
* and path starts with the router part, `{encodeURIComponent(routerId)}@`. A
|
|
33
|
+
* key that names a function and its arguments, or a tag, does not.
|
|
31
34
|
*
|
|
32
|
-
*
|
|
33
|
-
* (
|
|
34
|
-
*
|
|
35
|
+
* - With the part: PPR shells and the build-shell manifest (buildShellKey,
|
|
36
|
+
* buildShellManifestKey); route cache() records, the document cache and
|
|
37
|
+
* response routes (cacheKeyBase); a loader's own cache() entry; a
|
|
38
|
+
* `"use cache"` entry of a call that takes a ctx (a ctx is one router's:
|
|
39
|
+
* its variables, env and reverse() map).
|
|
40
|
+
* - Without: a `"use cache"` entry of plain arguments or a bare Request
|
|
41
|
+
* (requestArgKey); tag markers; a key the app builds itself
|
|
42
|
+
* (`cache({ key })`, a `keyGenerator`).
|
|
43
|
+
*
|
|
44
|
+
* Why: a host and path do not name a router. A `hostOverride` cookie picks
|
|
45
|
+
* the router and forwards the request unmodified, and a `router.prerender()`
|
|
46
|
+
* warm requests whatever origin it resolved, so two routers on one store
|
|
47
|
+
* built one key and read each other's entry.
|
|
48
|
+
*
|
|
49
|
+
* The id (router.ts) has to be the same in every isolate and in build-time
|
|
50
|
+
* discovery: an explicit `id` and the injected `$$id` are, the `router_{n}`
|
|
51
|
+
* fallback is for a single router only (discover-routers.ts warns about
|
|
52
|
+
* more). Encoded, the id holds no `@` or `/`, and a host holds no `@`, so a
|
|
53
|
+
* key has a router part exactly when its first `@` comes before its first
|
|
54
|
+
* `/`: no id can be chosen to spell another router's key.
|
|
55
|
+
*/
|
|
56
|
+
export declare function routerKeyPrefix(routerId: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Key base of one router's output (the router rule, routerKeyPrefix):
|
|
59
|
+
* `${routerId}@${host}${pathname}[:params][?search]`.
|
|
60
|
+
*
|
|
61
|
+
* The ONE composition of the namespacing rule, shared by the segment tier
|
|
62
|
+
* (cache-scope.ts), the document tier (document-cache.ts), the response tier
|
|
63
|
+
* (rsc/response-cache-serve.ts) and the loader cache so the rule cannot drift
|
|
64
|
+
* between them. Host prefixing matters because VercelCacheStore /
|
|
35
65
|
* MemorySegmentCacheStore key by the raw string (only CFCacheStore adds host
|
|
36
66
|
* internally) -- on a single function serving multiple domains an
|
|
37
67
|
* un-namespaced key bleeds tenant A's cached response to tenant B.
|
|
@@ -40,7 +70,22 @@ export declare function sortedRouteParams(params: Record<string, string> | undef
|
|
|
40
70
|
* invalidates every persisted cache entry on upgrade. Callers append their own
|
|
41
71
|
* tier-specific suffixes (`:rsc`/`:html`, segment hash) after this base.
|
|
42
72
|
*/
|
|
43
|
-
export declare function cacheKeyBase(host: string, pathname: string, searchParams?: URLSearchParams, params?: Record<string, string>, filter?: SearchParamsFilter): string;
|
|
73
|
+
export declare function cacheKeyBase(routerId: string, host: string, pathname: string, searchParams?: URLSearchParams, params?: Record<string, string>, filter?: SearchParamsFilter): string;
|
|
74
|
+
/**
|
|
75
|
+
* cacheKeyBase for the request context `ctx`. rsc/handler.ts sets `_routerId`
|
|
76
|
+
* before the request scope opens and derived contexts inherit it, so a served
|
|
77
|
+
* request always has one. Only a hand-built context has none (a unit test,
|
|
78
|
+
* the runLoader / renderHandler primitives): its key has no router part,
|
|
79
|
+
* which no router's key equals (routerKeyPrefix).
|
|
80
|
+
*/
|
|
81
|
+
export declare function requestKeyBase(ctx: {
|
|
82
|
+
readonly _routerId?: string;
|
|
83
|
+
} | null | undefined, host: string, pathname: string, searchParams?: URLSearchParams, params?: Record<string, string>, filter?: SearchParamsFilter): string;
|
|
84
|
+
/**
|
|
85
|
+
* The `"use cache"` key part of a bare Request argument: its URL, with no
|
|
86
|
+
* router part (the router rule, routerKeyPrefix).
|
|
87
|
+
*/
|
|
88
|
+
export declare function requestArgKey(url: URL, filter?: SearchParamsFilter): string;
|
|
44
89
|
/**
|
|
45
90
|
* The prefix of a `key()` result's part in a record key (#975), and of a
|
|
46
91
|
* loader's own `key()` result after its `loader:<id>:` namespace (#1009,
|
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { CacheDefaults, SegmentCacheStore } from "./types.js";
|
|
9
9
|
import type { RequestContext } from "../server/request-context.js";
|
|
10
|
+
/**
|
|
11
|
+
* How long a follower trusts an in-flight leader before evicting it and
|
|
12
|
+
* running fresh. High enough that a slow-but-healthy upstream never triggers
|
|
13
|
+
* duplicate work (a legitimate cached call taking >15s is already pathological);
|
|
14
|
+
* low enough to bound the blast radius of a wedged leader to seconds, not the
|
|
15
|
+
* isolate lifetime. Aligned with SHELL_CAPTURE_MAX_WAIT_MS.
|
|
16
|
+
*/
|
|
17
|
+
export declare const IN_FLIGHT_LEADER_MAX_WAIT_MS = 15000;
|
|
10
18
|
/**
|
|
11
19
|
* Default TTL for route-level cache() DSL and loader cache.
|
|
12
20
|
* Applied when neither the cache options nor the store defaults specify a TTL.
|
|
@@ -73,4 +81,13 @@ export declare function computeExpiration(ttlSeconds: number, swrSeconds?: numbe
|
|
|
73
81
|
};
|
|
74
82
|
export declare function resolveCacheKey(keyFn: ((ctx: RequestContext) => string | Promise<string>) | undefined, store: SegmentCacheStore | null, defaultKey: string): Promise<string>;
|
|
75
83
|
export declare function resolveTagsOption<TEnv>(tags: string[] | ((ctx: RequestContext<TEnv>) => string[]) | undefined, ctx: RequestContext<TEnv> | undefined, label: string): string[] | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Normalize a resolved tags array so the WRITE path matches the invalidate path:
|
|
86
|
+
* updateTag()/revalidateTag()/cacheTag() all drop empty/whitespace-only tags via
|
|
87
|
+
* normalizeTag(). Without this, an empty tag attached at write time would enter
|
|
88
|
+
* the store index but could never be invalidated (the verbs normalize it away),
|
|
89
|
+
* and on CFCacheStore would also cost a wasted KV marker read per request.
|
|
90
|
+
* Returns undefined when nothing usable remains, keeping the entry header-free.
|
|
91
|
+
*/
|
|
92
|
+
export declare function normalizeTagList(tags: string[]): string[] | undefined;
|
|
76
93
|
export declare function resolveCacheStore(explicitStore: SegmentCacheStore | undefined): SegmentCacheStore | null;
|
|
@@ -356,7 +356,7 @@ export declare class CacheScope {
|
|
|
356
356
|
* enclosing scopes on another store (#974) and of a scope without its own
|
|
357
357
|
* `key()` (#970)); with none, the app store's keyGenerator result
|
|
358
358
|
* given the document default key. Undefined (synchronously, with no work)
|
|
359
|
-
* when neither applies: the shell key stays
|
|
359
|
+
* when neither applies: the shell key stays unpartitioned (buildShellKey).
|
|
360
360
|
* Resolves to null when the partition is the default key itself (a
|
|
361
361
|
* keyGenerator that returns it unchanged): that partitions nothing, so the
|
|
362
362
|
* shell stays unpartitioned and keeps its build shell. The shell's key, its
|
|
@@ -3,7 +3,7 @@ declare global {
|
|
|
3
3
|
readonly default: Cache;
|
|
4
4
|
}
|
|
5
5
|
}
|
|
6
|
-
import type { SegmentCacheStore, CachedEntryData, CacheDefaults, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry, ShellDocumentRead, ShellDocumentReadOptions, CacheReadError } from "../types.js";
|
|
6
|
+
import type { CacheStoreScope, SegmentCacheStore, CachedEntryData, CacheDefaults, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry, ShellDocumentRead, ShellDocumentReadOptions, CacheReadError } from "../types.js";
|
|
7
7
|
import { type RequestContext } from "../../server/request-context.js";
|
|
8
8
|
import { CACHE_STALE_AT_HEADER, CACHE_STATUS_HEADER, CACHE_TAGS_HEADER, CACHE_TAGGED_AT_HEADER, TAG_MARKER_PREFIX, CACHE_REVALIDATING_AT_HEADER, MAX_REVALIDATION_INTERVAL, EDGE_LOOKUP_TIMEOUT_MS, EDGE_READ_TIMEOUT_MS, KV_READ_TIMEOUT_MS } from "./cf-cache-constants.js";
|
|
9
9
|
export { CACHE_STALE_AT_HEADER, CACHE_STATUS_HEADER, CACHE_TAGS_HEADER, CACHE_TAGGED_AT_HEADER, TAG_MARKER_PREFIX, CACHE_REVALIDATING_AT_HEADER, MAX_REVALIDATION_INTERVAL, EDGE_LOOKUP_TIMEOUT_MS, EDGE_READ_TIMEOUT_MS, KV_READ_TIMEOUT_MS, };
|
|
@@ -43,6 +43,12 @@ export declare class CFCacheStore<TEnv = unknown> implements SegmentCacheStore<T
|
|
|
43
43
|
private readonly kv?;
|
|
44
44
|
/** True when constructed without KV: no durable tag history (see ctor). */
|
|
45
45
|
readonly tagHistoryInert?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* SegmentCacheStore.scope: with KV every colo's L1 miss reads the same L2
|
|
48
|
+
* entry ("global"); without it entries live in one colo's Cache API
|
|
49
|
+
* ("local"), purge mode included (a purge evicts, it stores nothing).
|
|
50
|
+
*/
|
|
51
|
+
readonly scope: CacheStoreScope;
|
|
46
52
|
private readonly onRevalidateTag?;
|
|
47
53
|
private readonly tagPurge?;
|
|
48
54
|
private readonly tagInvalidationTtl?;
|
|
@@ -31,11 +31,14 @@ export interface DocumentCacheOptions<TEnv = any> {
|
|
|
31
31
|
/**
|
|
32
32
|
* Custom cache key generator.
|
|
33
33
|
*
|
|
34
|
-
* Replaces the default `host + pathname + search` key entirely.
|
|
35
|
-
* multi-domain deployment served by one function you MUST include
|
|
36
|
-
* (or an equivalent tenant discriminator) yourself — the default
|
|
37
|
-
* host-namespaced, but a custom generator's output is used verbatim,
|
|
38
|
-
* omitting host bleeds one hostname's cached response to another.
|
|
34
|
+
* Replaces the default `router id + host + pathname + search` key entirely.
|
|
35
|
+
* On a multi-domain deployment served by one function you MUST include
|
|
36
|
+
* `url.host` (or an equivalent tenant discriminator) yourself — the default
|
|
37
|
+
* key is host-namespaced, but a custom generator's output is used verbatim,
|
|
38
|
+
* so omitting host bleeds one hostname's cached response to another. The
|
|
39
|
+
* same goes for the router: two routers that share a cache store and can
|
|
40
|
+
* serve one host and path (a `hostOverride` cookie) need a generator that
|
|
41
|
+
* tells them apart.
|
|
39
42
|
*/
|
|
40
43
|
keyGenerator?: (url: URL) => string;
|
|
41
44
|
/**
|
|
@@ -44,6 +44,18 @@ export declare function decodeHandleValue<T>(encoded: string): Promise<T | null>
|
|
|
44
44
|
export declare function captureHandles(segments: ResolvedSegment[], handleStore: HandleStore): Record<string, SegmentHandleData>;
|
|
45
45
|
/** The owners of captureHandles' values; undefined when none is owned. */
|
|
46
46
|
export declare function captureHandleOwners(segments: ResolvedSegment[], handleStore: HandleStore): HandleOwners | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* captureHandles and captureHandleOwners cut down to the handle arrays that
|
|
49
|
+
* hold an owned value, each whole (its unowned values too, in place), so
|
|
50
|
+
* restoreHandles rebuilds exactly those arrays over a store that already
|
|
51
|
+
* holds the rest. A prerender-served shell capture stores this: the
|
|
52
|
+
* prerender store restores the handler pushes on a HIT, and the loader
|
|
53
|
+
* pushes have no other record (shell-capture.ts captureAndStoreShell).
|
|
54
|
+
*/
|
|
55
|
+
export declare function captureOwnedHandles(handleStore: HandleStore): {
|
|
56
|
+
handles: HandleRecord;
|
|
57
|
+
owners?: HandleOwners;
|
|
58
|
+
};
|
|
47
59
|
/**
|
|
48
60
|
* What the record being restored is to each loader's handle pushes on this
|
|
49
61
|
* request (HandleStore RecordAuthority). Built by loaderPins (loader-cache.ts)
|
|
@@ -65,6 +77,17 @@ export type OwnedPushDelivery = (loaderId: string) => RecordAuthority;
|
|
|
65
77
|
* pushes in a placeholder's place).
|
|
66
78
|
*/
|
|
67
79
|
export declare function restoreHandles(handles: Record<string, SegmentHandleData>, handleStore: HandleStore, owners?: HandleOwners, owned?: OwnedPushDelivery): void;
|
|
80
|
+
/**
|
|
81
|
+
* Serve a doc record's handles: set its authority over the loaders' pushes
|
|
82
|
+
* (with or without a handles blob: a pinned loader whose capture pushed
|
|
83
|
+
* nothing has no copy, and its run must still add no settled push), then
|
|
84
|
+
* decode and restoreHandles. `keepIds` limits the restore to the segments a
|
|
85
|
+
* boundary-scoped scope serves. A decode failure skips the restore.
|
|
86
|
+
*/
|
|
87
|
+
export declare function restoreRecordHandles(handleStore: HandleStore, record: {
|
|
88
|
+
handles?: string;
|
|
89
|
+
handleOwners?: HandleOwners;
|
|
90
|
+
}, owned: OwnedPushDelivery | undefined, keepIds?: ReadonlySet<string>): Promise<void>;
|
|
68
91
|
/**
|
|
69
92
|
* Append recorded handle pushes to the store, in recorded order, via push()
|
|
70
93
|
* so active captures and loader-scope tagging see them like live pushes. For
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { SegmentCacheStore, CachedEntryData, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry, SerializedSegmentData, SegmentHandleData, CacheReadError, } from "./types.js";
|
|
1
|
+
export type { SegmentCacheStore, CacheStoreScope, CachedEntryData, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry, SerializedSegmentData, SegmentHandleData, CacheReadError, } from "./types.js";
|
|
2
2
|
export { CACHE_READ_ERROR } from "./types.js";
|
|
3
3
|
export { MemorySegmentCacheStore } from "./memory-segment-store.js";
|
|
4
4
|
export type { StoreMemoOptions } from "./shell-memo.js";
|
|
@@ -8,6 +8,20 @@ export interface ExecutionStart {
|
|
|
8
8
|
readonly seq: number;
|
|
9
9
|
readonly at: number;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* The `taggedAt` / `ta` stamp a store writes on a tagged data entry: the start
|
|
13
|
+
* of the execution that produced the value (`startedAt`), so a marker written
|
|
14
|
+
* while it ran rejects the entry on read (#1068). Write time when the writer
|
|
15
|
+
* knows no start. Never later than now: a start from a skewed clock must not
|
|
16
|
+
* stamp the future, which would make the entry look newer than every marker.
|
|
17
|
+
*/
|
|
18
|
+
export declare function entryStamp(startedAt: number | undefined): number;
|
|
19
|
+
/** The stamp of a data entry: `entryStamp` for a tagged entry, none otherwise. */
|
|
20
|
+
export declare function taggedStamp(tags: readonly string[] | undefined, startedAt: number | undefined): number | undefined;
|
|
21
|
+
/** Mark the execution start behind a Response handed to putResponse. */
|
|
22
|
+
export declare function markResponseStart(response: Response, start: ExecutionStart): Response;
|
|
23
|
+
/** The start a writer marked on `response`, if any. */
|
|
24
|
+
export declare function responseStartedAt(response: Response): number | undefined;
|
|
11
25
|
/** Record an execution's start, before it reads its data. */
|
|
12
26
|
export declare function executionStart(): ExecutionStart;
|
|
13
27
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Simple in-memory implementation of SegmentCacheStore.
|
|
5
5
|
* Uses globalThis to survive HMR in development.
|
|
6
6
|
*/
|
|
7
|
-
import type { SegmentCacheStore, CachedEntryData, CacheDefaults, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry } from "./types.js";
|
|
7
|
+
import type { CacheStoreScope, SegmentCacheStore, CachedEntryData, CacheDefaults, CacheGetResult, CacheItemResult, CacheItemOptions, ShellCacheEntry } from "./types.js";
|
|
8
8
|
import type { RequestContext } from "../server/request-context.js";
|
|
9
9
|
/**
|
|
10
10
|
* Options for MemorySegmentCacheStore
|
|
@@ -70,6 +70,25 @@ export interface MemorySegmentCacheStoreOptions<TEnv = unknown> {
|
|
|
70
70
|
* ```
|
|
71
71
|
*/
|
|
72
72
|
maxEntries?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Where an entry this store writes can be read; what `router.prerender()`
|
|
75
|
+
* checks before warming a route. Defaults to `"local"`: the maps live in one
|
|
76
|
+
* process, and the router cannot tell one long-running server from several
|
|
77
|
+
* replicas or serverless instances, so a warm into it is refused in
|
|
78
|
+
* production. Set `"global"` only when exactly one process serves the app
|
|
79
|
+
* (a single Node server); a warm then reports `warmed`. Under the Vite dev
|
|
80
|
+
* server a `"local"` instance already counts as shared.
|
|
81
|
+
*
|
|
82
|
+
* Like `defaults` and `keyGenerator`, the scope is per instance: two
|
|
83
|
+
* instances with the same `name` share their maps but each declares its own
|
|
84
|
+
* scope. Keep them identical.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const store = new MemorySegmentCacheStore({ scope: "global" });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
scope?: CacheStoreScope;
|
|
73
92
|
}
|
|
74
93
|
/**
|
|
75
94
|
* In-memory segment cache store.
|
|
@@ -106,6 +125,13 @@ export interface MemorySegmentCacheStoreOptions<TEnv = unknown> {
|
|
|
106
125
|
* ```
|
|
107
126
|
*/
|
|
108
127
|
export declare class MemorySegmentCacheStore<TEnv = unknown> implements SegmentCacheStore<TEnv> {
|
|
128
|
+
/**
|
|
129
|
+
* SegmentCacheStore.scope: "local" unless `options.scope` says otherwise, so
|
|
130
|
+
* router.prerender() refuses to warm into these maps in production. Under
|
|
131
|
+
* the Vite dev server the gate counts a "local" instance as shared
|
|
132
|
+
* (store-scope.ts resolveWarmStoreScope).
|
|
133
|
+
*/
|
|
134
|
+
readonly scope: CacheStoreScope;
|
|
109
135
|
readonly supportsPassiveShellReads: true;
|
|
110
136
|
private cache;
|
|
111
137
|
private responseCache;
|
|
@@ -151,6 +177,12 @@ export declare class MemorySegmentCacheStore<TEnv = unknown> implements SegmentC
|
|
|
151
177
|
} | null>;
|
|
152
178
|
putShell(key: string, entry: ShellCacheEntry, ttlSeconds?: number, swrSeconds?: number, tags?: string[]): Promise<"stored" | "invalidated">;
|
|
153
179
|
isTagsInvalidatedSince(tags: string[], sinceMs: number): Promise<boolean>;
|
|
180
|
+
/**
|
|
181
|
+
* A tag invalidated in a millisecond after the write's execution started
|
|
182
|
+
* (#1068). Strictly after: the start's own millisecond is ambiguous, and
|
|
183
|
+
* invalidation-order.ts orders those exactly.
|
|
184
|
+
*/
|
|
185
|
+
private invalidatedAfter;
|
|
154
186
|
private tagsInvalidatedSince;
|
|
155
187
|
invalidateTags(tags: string[]): Promise<void>;
|
|
156
188
|
private registerTags;
|