@rangojs/router 0.27.0 → 0.29.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/bin/rango.js +1 -1
- package/dist/types/__internal.d.ts +7 -1
- package/dist/types/browser/action-fence.d.ts +2 -1
- package/dist/types/browser/event-controller.d.ts +8 -2
- package/dist/types/browser/history-state.d.ts +3 -9
- package/dist/types/browser/navigation-store.d.ts +8 -6
- package/dist/types/browser/partial-update.d.ts +11 -0
- package/dist/types/browser/react/filter-segment-order.d.ts +2 -2
- package/dist/types/browser/react/use-action.d.ts +7 -2
- package/dist/types/browser/react/use-handle.d.ts +19 -16
- package/dist/types/browser/react/use-link-status.d.ts +5 -2
- package/dist/types/browser/segment-reconciler.d.ts +32 -4
- package/dist/types/browser/types.d.ts +24 -5
- package/dist/types/browser/wire-protocol.d.ts +26 -0
- package/dist/types/cache/cache-key-utils.d.ts +11 -5
- package/dist/types/cache/cache-scope.d.ts +34 -22
- package/dist/types/cache/cf/cf-cache-constants.d.ts +2 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +47 -65
- package/dist/types/cache/cf/cf-kv-utils.d.ts +1 -1
- package/dist/types/cache/handle-snapshot.d.ts +9 -4
- package/dist/types/cache/segment-codec.d.ts +14 -0
- package/dist/types/cache/shell-snapshot.d.ts +1 -1
- package/dist/types/cache/taint.d.ts +5 -3
- package/dist/types/cache/types.d.ts +7 -3
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +8 -6
- package/dist/types/prefetch-markers.d.ts +5 -14
- package/dist/types/prerender/store.d.ts +31 -0
- package/dist/types/prerender/warm-request.d.ts +3 -3
- package/dist/types/prerender.d.ts +2 -2
- package/dist/types/route-name.d.ts +5 -0
- package/dist/types/router/error-handling.d.ts +11 -5
- package/dist/types/router/instrument.d.ts +4 -3
- package/dist/types/router/intercept-resolution.d.ts +25 -9
- package/dist/types/router/match-context.d.ts +6 -11
- package/dist/types/router/match-handlers.d.ts +2 -6
- package/dist/types/router/match-middleware/background-revalidation.d.ts +13 -22
- package/dist/types/router/match-middleware/cache-lookup.d.ts +34 -86
- package/dist/types/router/match-middleware/segment-resolution.d.ts +8 -6
- package/dist/types/router/navigation-snapshot.d.ts +7 -0
- package/dist/types/router/prerender-match.d.ts +21 -6
- package/dist/types/router/preview-match.d.ts +2 -7
- package/dist/types/router/request-classification.d.ts +5 -0
- package/dist/types/router/router-context.d.ts +7 -46
- package/dist/types/router/router-interfaces.d.ts +8 -14
- package/dist/types/router/segment-resolution/helpers.d.ts +19 -3
- package/dist/types/router/segment-resolution/loader-cache.d.ts +3 -3
- package/dist/types/router/segment-resolution/loader-mask.d.ts +4 -4
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +20 -18
- package/dist/types/router/segment-resolution/resolution-pass.d.ts +95 -0
- package/dist/types/router/segment-resolution/revalidation.d.ts +82 -31
- package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +2 -0
- package/dist/types/router/segment-resolution.d.ts +1 -2
- package/dist/types/router/segment-wrappers.d.ts +11 -48
- package/dist/types/router/telemetry.d.ts +2 -0
- package/dist/types/router/types.d.ts +11 -1
- package/dist/types/rsc/full-payload.d.ts +2 -2
- package/dist/types/rsc/handler-context.d.ts +6 -6
- package/dist/types/rsc/json-route-result.d.ts +5 -9
- package/dist/types/rsc/request-stages.d.ts +203 -0
- package/dist/types/rsc/response-cache-serve.d.ts +7 -12
- package/dist/types/rsc/response-route-handler.d.ts +2 -2
- package/dist/types/rsc/routine-plan.d.ts +1 -1
- package/dist/types/rsc/server-action.d.ts +2 -2
- package/dist/types/rsc/shell-capture-constants.d.ts +1 -1
- package/dist/types/rsc/shell-capture.d.ts +132 -15
- package/dist/types/rsc/shell-serve.d.ts +37 -12
- package/dist/types/server/context.d.ts +9 -8
- package/dist/types/server/handle-store.d.ts +16 -0
- package/dist/types/server/render-pass.d.ts +72 -0
- package/dist/types/server/request-context.d.ts +53 -104
- package/dist/types/server/rewrite-trail.d.ts +2 -2
- package/dist/types/testing/dispatch.d.ts +35 -18
- package/dist/types/testing/render-route.d.ts +43 -8
- package/dist/types/testing/serve-shell-request.d.ts +8 -1
- package/dist/types/types/cache-types.d.ts +6 -3
- package/dist/types/types/error-types.d.ts +30 -3
- package/dist/types/types/handler-context.d.ts +9 -1
- package/dist/types/types/segments.d.ts +1 -1
- package/dist/types/vite/discovery/build-discovery-phase.d.ts +40 -0
- package/dist/types/vite/discovery/build-env.d.ts +22 -0
- package/dist/types/vite/discovery/bundle-scan-phase.d.ts +12 -0
- package/dist/types/vite/discovery/dev-prerender-cache.d.ts +3 -2
- package/dist/types/vite/discovery/dev-server-phase.d.ts +26 -0
- package/dist/types/vite/discovery/discovery-errors.d.ts +1 -1
- package/dist/types/vite/discovery/state.d.ts +12 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +1 -1
- package/dist/types/vite/plugins/virtual-entries.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +8 -47
- package/dist/types/vite/temp-rsc-server.d.ts +39 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +9 -0
- package/dist/types/wire-params.d.ts +39 -0
- package/dist/vite/index.js +3822 -3727
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +8 -5
- package/skills/caching/SKILL.md +37 -18
- package/skills/client-urls/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +13 -1
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/hooks/SKILL.md +1 -1
- package/skills/hooks/data.md +8 -1
- package/skills/hooks/handle-and-actions.md +33 -2
- package/skills/hooks/navigation.md +121 -15
- package/skills/hooks/state.md +6 -4
- package/skills/hooks/urls.md +16 -5
- package/skills/intercept/SKILL.md +23 -7
- package/skills/middleware/SKILL.md +18 -0
- package/skills/observability/SKILL.md +30 -0
- package/skills/ppr/SKILL.md +18 -3
- package/skills/prerender/SKILL.md +39 -15
- package/skills/rango/SKILL.md +5 -1
- package/skills/server-actions/SKILL.md +15 -1
- package/skills/testing/client-components.md +25 -18
- package/skills/testing/response-routes.md +6 -4
- package/skills/testing/serve-shell-request.md +7 -7
- package/skills/use-cache/SKILL.md +46 -8
- package/skills/view-transitions/SKILL.md +1 -1
- package/src/__internal.ts +7 -1
- package/src/browser/action-fence.ts +2 -1
- package/src/browser/connection-warmup.ts +3 -1
- package/src/browser/event-controller.ts +37 -13
- package/src/browser/history-state.ts +6 -12
- package/src/browser/navigation-bridge.ts +59 -26
- package/src/browser/navigation-client.ts +20 -25
- package/src/browser/navigation-store.ts +25 -27
- package/src/browser/navigation-transaction.ts +4 -1
- package/src/browser/network-error-handler.ts +4 -0
- package/src/browser/partial-update.ts +33 -6
- package/src/browser/prefetch/cache.ts +2 -1
- package/src/browser/prefetch/fetch.ts +8 -16
- package/src/browser/prefetch/queue.ts +4 -4
- package/src/browser/react/NavigationProvider.tsx +2 -1
- package/src/browser/react/filter-segment-order.ts +2 -2
- package/src/browser/react/use-action.ts +24 -48
- package/src/browser/react/use-handle.ts +22 -18
- package/src/browser/react/use-link-status.ts +48 -60
- package/src/browser/react/use-navigation.ts +92 -41
- package/src/browser/rsc-router.tsx +1 -0
- package/src/browser/segment-reconciler.ts +109 -53
- package/src/browser/server-action-bridge.ts +81 -61
- package/src/browser/types.ts +25 -5
- package/src/browser/wire-protocol.ts +43 -0
- package/src/cache/cache-key-utils.ts +11 -5
- package/src/cache/cache-runtime.ts +132 -75
- package/src/cache/cache-scope.ts +110 -64
- package/src/cache/cf/cf-cache-constants.ts +2 -2
- package/src/cache/cf/cf-cache-store.ts +486 -874
- package/src/cache/cf/cf-kv-utils.ts +1 -1
- package/src/cache/document-cache.ts +64 -46
- package/src/cache/handle-snapshot.ts +19 -7
- package/src/cache/read-through-swr.ts +20 -18
- package/src/cache/segment-codec.ts +55 -0
- package/src/cache/shell-snapshot.ts +2 -2
- package/src/cache/tag-invalidation.ts +6 -2
- package/src/cache/taint.ts +5 -3
- package/src/cache/types.ts +7 -3
- package/src/cache/vercel/vercel-cache-store.ts +243 -310
- package/src/handles/pushed-by.ts +1 -1
- package/src/prefetch-markers.ts +5 -16
- package/src/prerender/store.ts +76 -0
- package/src/prerender/warm-request.ts +8 -4
- package/src/prerender.ts +2 -2
- package/src/route-name.ts +8 -0
- package/src/router/error-handling.ts +22 -10
- package/src/router/instrument.ts +4 -3
- package/src/router/intercept-resolution.ts +82 -75
- package/src/router/loader-resolution.ts +5 -4
- package/src/router/match-api.ts +5 -5
- package/src/router/match-context.ts +23 -12
- package/src/router/match-handlers.ts +8 -20
- package/src/router/match-middleware/background-revalidation.ts +46 -57
- package/src/router/match-middleware/cache-lookup.ts +677 -726
- package/src/router/match-middleware/cache-store.ts +4 -8
- package/src/router/match-middleware/intercept-resolution.ts +3 -23
- package/src/router/match-middleware/segment-resolution.ts +34 -61
- package/src/router/middleware.ts +69 -11
- package/src/router/navigation-snapshot.ts +14 -4
- package/src/router/prerender-match.ts +100 -44
- package/src/router/preview-match.ts +6 -41
- package/src/router/request-classification.ts +13 -7
- package/src/router/route-snapshot.ts +2 -5
- package/src/router/router-context.ts +10 -95
- package/src/router/router-interfaces.ts +8 -14
- package/src/router/segment-resolution/helpers.ts +49 -13
- package/src/router/segment-resolution/loader-cache.ts +15 -9
- package/src/router/segment-resolution/loader-mask.ts +5 -5
- package/src/router/segment-resolution/prefetch-deferral.ts +30 -27
- package/src/router/segment-resolution/resolution-pass.ts +139 -0
- package/src/router/segment-resolution/revalidation.ts +939 -789
- package/src/router/segment-resolution/streamed-handler-boundary.ts +3 -0
- package/src/router/segment-resolution.ts +4 -13
- package/src/router/segment-wrappers.ts +51 -269
- package/src/router/telemetry.ts +5 -0
- package/src/router/types.ts +11 -1
- package/src/router.ts +19 -17
- package/src/rsc/full-payload.ts +6 -5
- package/src/rsc/handler-context.ts +8 -14
- package/src/rsc/handler.ts +126 -507
- package/src/rsc/json-route-result.ts +5 -9
- package/src/rsc/loader-fetch.ts +6 -5
- package/src/rsc/progressive-enhancement.ts +5 -0
- package/src/rsc/request-stages.ts +759 -0
- package/src/rsc/response-cache-serve.ts +10 -14
- package/src/rsc/response-route-handler.ts +13 -5
- package/src/rsc/rewrite-passes.ts +2 -1
- package/src/rsc/routine-plan.ts +1 -1
- package/src/rsc/rsc-rendering.ts +164 -349
- package/src/rsc/server-action.ts +87 -113
- package/src/rsc/shell-capture-constants.ts +1 -1
- package/src/rsc/shell-capture.ts +275 -227
- package/src/rsc/shell-serve.ts +121 -18
- package/src/rsc/ssr-setup.ts +5 -4
- package/src/segment-system.tsx +3 -3
- package/src/server/context.ts +22 -25
- package/src/server/handle-store.ts +55 -0
- package/src/server/render-pass.ts +291 -0
- package/src/server/request-context.ts +75 -115
- package/src/server/rewrite-trail.ts +6 -4
- package/src/ssr/index.tsx +1 -1
- package/src/testing/dispatch.ts +226 -710
- package/src/testing/e2e/page-helpers.ts +2 -2
- package/src/testing/render-route.tsx +199 -13
- package/src/testing/serve-shell-request.ts +36 -40
- package/src/types/cache-types.ts +6 -3
- package/src/types/error-types.ts +30 -3
- package/src/types/handler-context.ts +12 -1
- package/src/types/segments.ts +1 -1
- package/src/vite/discovery/build-discovery-phase.ts +204 -0
- package/src/vite/discovery/build-env.ts +148 -0
- package/src/vite/discovery/bundle-scan-phase.ts +128 -0
- package/src/vite/discovery/dev-prerender-cache.ts +8 -3
- package/src/vite/discovery/dev-server-phase.ts +1776 -0
- package/src/vite/discovery/discover-routers.ts +1 -1
- package/src/vite/discovery/discovery-errors.ts +1 -1
- package/src/vite/discovery/prerender-collection.ts +24 -39
- package/src/vite/discovery/state.ts +15 -0
- package/src/vite/plugins/version-plugin.ts +1 -1
- package/src/vite/plugins/virtual-entries.ts +1 -1
- package/src/vite/router-discovery.ts +29 -2428
- package/src/vite/temp-rsc-server.ts +223 -0
- package/src/vite/utils/prerender-utils.ts +47 -0
- package/src/wire-params.ts +40 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +0 -72
- package/src/router/segment-resolution/fresh.ts +0 -945
package/dist/bin/rango.js
CHANGED
|
@@ -1644,7 +1644,7 @@ var init_package = __esm({
|
|
|
1644
1644
|
"package.json"() {
|
|
1645
1645
|
package_default = {
|
|
1646
1646
|
name: "@rangojs/router",
|
|
1647
|
-
version: "0.
|
|
1647
|
+
version: "0.29.0",
|
|
1648
1648
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1649
1649
|
keywords: [
|
|
1650
1650
|
"react",
|
|
@@ -53,7 +53,13 @@ export type { CachedEntryData, CacheGetResult, SerializedSegmentData, CacheDefau
|
|
|
53
53
|
* @internal
|
|
54
54
|
* Router context for AsyncLocalStorage.
|
|
55
55
|
*/
|
|
56
|
-
export type { RouterContext,
|
|
56
|
+
export type { RouterContext, InterceptResult, } from "./router/router-context.js";
|
|
57
|
+
/**
|
|
58
|
+
* @internal
|
|
59
|
+
* The request side of a revalidating resolution pass (RouterContext's
|
|
60
|
+
* revalidating resolvers take it).
|
|
61
|
+
*/
|
|
62
|
+
export type { ResolutionPassInput } from "./router/segment-resolution/resolution-pass.js";
|
|
57
63
|
/**
|
|
58
64
|
* @internal
|
|
59
65
|
* Route match context during pipeline processing.
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
*
|
|
21
21
|
* The drop runs the batch's follow-up: when an action of the batch did not
|
|
22
22
|
* land on the page on screen, the action bridge refetches that page once,
|
|
23
|
-
* whole
|
|
23
|
+
* whole (or whole above an action's error boundary on screen, which it
|
|
24
|
+
* holds), after the navigation the user started, unless an intercept is on
|
|
24
25
|
* screen (server-action-bridge.ts followUp; the rules are R1-R7 in
|
|
25
26
|
* docs/internal/execution-model.md).
|
|
26
27
|
*
|
|
@@ -59,6 +59,11 @@ export interface ActionEntry {
|
|
|
59
59
|
startedAt: number;
|
|
60
60
|
/** Whether action processing is complete (may still be streaming) */
|
|
61
61
|
completed?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Set when a later call started (see startAction): "id" hides this call
|
|
64
|
+
* from every reader, "name" from readers that match by export name.
|
|
65
|
+
*/
|
|
66
|
+
supersededBy?: "id" | "name";
|
|
62
67
|
}
|
|
63
68
|
/**
|
|
64
69
|
* Derived navigation state (computed from source of truth)
|
|
@@ -70,7 +75,7 @@ export interface DerivedNavigationState {
|
|
|
70
75
|
isStreaming: boolean;
|
|
71
76
|
/** Whether a navigation is active (fetching or streaming, before commit) */
|
|
72
77
|
isNavigating: boolean;
|
|
73
|
-
/**
|
|
78
|
+
/** The location of the last page flushed to React (useNavigation keeps the page on screen) */
|
|
74
79
|
location: NavigationLocation;
|
|
75
80
|
/** URL being navigated to (null if idle) */
|
|
76
81
|
pendingUrl: string | null;
|
|
@@ -207,7 +212,8 @@ export interface EventController {
|
|
|
207
212
|
startAction(actionId: string, args: unknown[],
|
|
208
213
|
/** Originating history entry key; scopes location-state arbitration. */
|
|
209
214
|
cohort?: string): ActionHandle;
|
|
210
|
-
|
|
215
|
+
/** Abort every action in flight except `except` (an ActionHandle id). */
|
|
216
|
+
abortAllActions(except?: string): void;
|
|
211
217
|
getState(): DerivedNavigationState;
|
|
212
218
|
getActionState(actionId: string): TrackedActionState;
|
|
213
219
|
getLocation(): NavigationLocation;
|
|
@@ -21,15 +21,9 @@ export declare function hasLocationState(state: unknown): boolean;
|
|
|
21
21
|
*/
|
|
22
22
|
export declare function pushHistoryWithIdx(state: Record<string, unknown> | null, url: string, replace: boolean): void;
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* cache miss.
|
|
28
|
-
*/
|
|
29
|
-
export declare const SHELL_MISS_MARKER: string;
|
|
30
|
-
/**
|
|
31
|
-
* Drop the forced-MISS marker from the address bar at boot, keeping the
|
|
32
|
-
* history entry's state (initBrowserApp calls it before any location read).
|
|
24
|
+
* Drop the forced-MISS marker (`WIRE.shellMiss`, rsc/shell-serve.ts) from the
|
|
25
|
+
* address bar at boot, keeping the history entry's state (initBrowserApp
|
|
26
|
+
* calls it before any location read).
|
|
33
27
|
* Left in place, a refresh or a shared link would stay off the shell and the
|
|
34
28
|
* app's search params would carry it. The server strips the same marker from
|
|
35
29
|
* the request before rendering (shell-serve.ts withoutShellMissMarker), so
|
|
@@ -24,16 +24,18 @@ export declare function liveHandleDataForCache(eventController: Pick<EventContro
|
|
|
24
24
|
* Options for generating a history key
|
|
25
25
|
*/
|
|
26
26
|
export interface HistoryKeyOptions {
|
|
27
|
-
/**
|
|
27
|
+
/** Key an intercept entry (apart from the plain entry for the URL). */
|
|
28
28
|
intercept?: boolean;
|
|
29
|
+
/** The page the intercept was opened over (history.state.sourceUrl). */
|
|
30
|
+
interceptSource?: string;
|
|
29
31
|
}
|
|
30
32
|
/**
|
|
31
|
-
* Generate a cache key from a URL.
|
|
32
|
-
*
|
|
33
|
-
* Hash fragments (#) are excluded since they don't affect server data.
|
|
33
|
+
* Generate a cache key from a URL: pathname + search. Hash fragments (#) are
|
|
34
|
+
* excluded since they don't affect server data.
|
|
34
35
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
36
|
+
* An intercept entry is keyed `<url>:intercept:<source>`: its cached tree
|
|
37
|
+
* includes the page under the intercept. hasInterceptCache relies on the
|
|
38
|
+
* `:intercept:` separator.
|
|
37
39
|
*/
|
|
38
40
|
export declare function generateHistoryKey(url?: string, options?: HistoryKeyOptions): string;
|
|
39
41
|
/**
|
|
@@ -112,18 +112,29 @@ export type UpdateMode = {
|
|
|
112
112
|
* transition({ when }) sees kind "revalidate", not "replace".
|
|
113
113
|
*/
|
|
114
114
|
refresh?: boolean;
|
|
115
|
+
/** The cross-tab refresh's held boundary (see `action`). */
|
|
116
|
+
boundary?: string;
|
|
115
117
|
} | {
|
|
116
118
|
type: "leave-intercept";
|
|
117
119
|
interceptSourceUrl?: string;
|
|
120
|
+
boundary?: never;
|
|
118
121
|
} | {
|
|
119
122
|
type: "stale-revalidation";
|
|
120
123
|
interceptSourceUrl?: string;
|
|
124
|
+
/** Back/Forward's held boundary (see `action`). */
|
|
125
|
+
boundary?: string;
|
|
121
126
|
} | {
|
|
122
127
|
type: "action";
|
|
123
128
|
interceptSourceUrl?: string;
|
|
124
129
|
actionId?: string;
|
|
125
130
|
/** The action's FormData and result, for transition({ when }) `action`. */
|
|
126
131
|
action?: TransitionWhenActionInput;
|
|
132
|
+
/**
|
|
133
|
+
* An action's error boundary the page shows (actionBoundaryAt): the
|
|
134
|
+
* server renders above it, its cached segment stays, and the page
|
|
135
|
+
* holds only the ids above it.
|
|
136
|
+
*/
|
|
137
|
+
boundary?: string;
|
|
127
138
|
};
|
|
128
139
|
/**
|
|
129
140
|
* Type for the fetchPartialUpdate function. In `action` mode it resolves with
|
|
@@ -26,8 +26,8 @@ export declare function loaderParentId(id: string): string;
|
|
|
26
26
|
* 2. Place each parallel slot id (contains ".@") immediately after its
|
|
27
27
|
* parent layout/route id. Raw segment-resolution emission order does NOT
|
|
28
28
|
* guarantee this: route-mounted parallels are resolved/pushed BEFORE the
|
|
29
|
-
* route handler's segment is appended (see
|
|
30
|
-
*
|
|
29
|
+
* route handler's segment is appended (see resolveSegment in
|
|
30
|
+
* segment-resolution/revalidation.ts), so matched can read
|
|
31
31
|
* `[..., R0.@panel, R0]`. collectHandleData consumes segmentOrder verbatim
|
|
32
32
|
* with later-wins semantics, so without normalization the route handler's
|
|
33
33
|
* Meta would override the slot's more-specific Meta — backwards.
|
|
@@ -18,14 +18,19 @@ export type ServerActionFunction = ((...args: any[]) => Promise<any>) & {
|
|
|
18
18
|
* Features:
|
|
19
19
|
* - Tracks action lifecycle: idle → loading → streaming → idle
|
|
20
20
|
* - Captures result/error locally (React handles cleanup)
|
|
21
|
-
* - If
|
|
21
|
+
* - If the same action fires several times, reports the latest call to
|
|
22
|
+
* start. An earlier call that settles later changes nothing it reports;
|
|
23
|
+
* a latest call that was aborted reports idle with nothing. One call at a
|
|
24
|
+
* time, not one per argument: a reader filtering on `payload` cannot track
|
|
25
|
+
* an earlier call once a later one starts.
|
|
22
26
|
* - Supports selector pattern like useNavigation
|
|
23
27
|
*
|
|
24
28
|
* Matching behavior:
|
|
25
29
|
* - **Function reference**: Uses full $$id for exact matching. This is precise
|
|
26
30
|
* and distinguishes between actions with the same name in different files.
|
|
27
31
|
* - **String**: Matches by suffix (action name after #). This is convenient
|
|
28
|
-
* but may be ambiguous if multiple files export the same action name
|
|
32
|
+
* but may be ambiguous if multiple files export the same action name: it
|
|
33
|
+
* follows the latest call of any action with that export name.
|
|
29
34
|
*
|
|
30
35
|
* @param action - Either a server action function or a string action name.
|
|
31
36
|
* - **Function**: Must be directly imported in the client component.
|
|
@@ -21,21 +21,24 @@ import type { RouteStateSignal } from "../event-controller.js";
|
|
|
21
21
|
export declare function useHandle<T, A>(handle: Handle<T, A>): Rango.FlightSerialize<A>;
|
|
22
22
|
export declare function useHandle<T, A, S>(handle: Handle<T, A>, selector: (data: Rango.FlightSerialize<A>) => S): S;
|
|
23
23
|
/**
|
|
24
|
-
* Route state the controller's handle notifications drive
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* priority, it renders in the page's lane, and the page's effects read it.
|
|
30
|
-
* A page in a transition (signal "anchor") does not: until it commits
|
|
24
|
+
* Route state the controller's handle notifications drive commits with the
|
|
25
|
+
* page it belongs to. NavigationProvider flushes the controller inside every
|
|
26
|
+
* payload update, with signal "anchor" for a page in a transition and
|
|
27
|
+
* "release" for an urgent one, so the page's own change is set in the page's
|
|
28
|
+
* lane and the page's effects read it. From the anchor until the page commits
|
|
31
29
|
* (releaseRouteState() from the provider's layout effect, signal "release"),
|
|
32
|
-
* a
|
|
33
|
-
* page's own commit
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
30
|
+
* a later change waits and is applied in the commit's task, right after the
|
|
31
|
+
* page's own commit: set in a lane of its own, it would commit over the page
|
|
32
|
+
* being left (#1165).
|
|
33
|
+
*
|
|
34
|
+
* `waitForRelease`, set by useHandle only: the anchor's own change waits too,
|
|
35
|
+
* so a handle value lands right after its page's commit, never in its lane. A
|
|
36
|
+
* handle value can carry a promise that suspends, and in the page's lane one
|
|
37
|
+
* that suspends in a revealed <Suspense> would hold the page. Nothing
|
|
38
|
+
* useSegments reads can suspend, so it leaves it off and its path and
|
|
39
|
+
* location commit with their page.
|
|
40
|
+
*
|
|
41
|
+
* A value shallow-equal to the last one sets nothing, so a reader renders only
|
|
42
|
+
* when its value moves.
|
|
40
43
|
*/
|
|
41
|
-
export declare function useCommitAnchoredState<T>(init: () => T): [T, (value: T, signal?: RouteStateSignal) => void];
|
|
44
|
+
export declare function useCommitAnchoredState<T>(init: () => T, waitForRelease?: boolean): [T, (value: T, signal?: RouteStateSignal) => void];
|
|
@@ -14,8 +14,11 @@ export interface LinkStatus {
|
|
|
14
14
|
/**
|
|
15
15
|
* Hook to track the pending state of a Link component
|
|
16
16
|
*
|
|
17
|
-
* Must be used inside a Link component. Returns `{ pending: true }`
|
|
18
|
-
*
|
|
17
|
+
* Must be used inside a Link component. Returns `{ pending: true }` while a
|
|
18
|
+
* navigation to the link's destination is in flight, until the page it
|
|
19
|
+
* brings commits: under transition() while React holds that page, and
|
|
20
|
+
* through a server redirect until the target page commits. A newer
|
|
21
|
+
* navigation ends it at once.
|
|
19
22
|
*
|
|
20
23
|
* Useful for showing inline loading indicators on individual links.
|
|
21
24
|
*
|
|
@@ -62,10 +62,38 @@ export interface ReconcileResult {
|
|
|
62
62
|
*/
|
|
63
63
|
export declare function reconcileSegments(input: ReconcileInput): ReconcileResult;
|
|
64
64
|
/**
|
|
65
|
-
* Reconcile error
|
|
65
|
+
* Reconcile an error-boundary response with cached segments.
|
|
66
66
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* preserving sibling layouts that aren't in
|
|
67
|
+
* The server returns the error boundary segment and, above it, what the
|
|
68
|
+
* action's revalidation re-ran (rsc/server-action.ts). This function overlays
|
|
69
|
+
* them onto the full cached tree, preserving sibling layouts that aren't in
|
|
70
|
+
* the error parent chain. The error segment replaces its cached copy; every
|
|
71
|
+
* other segment merges as an action's does (mergeCached).
|
|
70
72
|
*/
|
|
71
73
|
export declare function reconcileErrorSegments(cachedSegments: ResolvedSegment[], errorSegments: ResolvedSegment[]): ReconcileResult;
|
|
74
|
+
/**
|
|
75
|
+
* The ids a page holds once an action's error boundary `boundary` shows: the
|
|
76
|
+
* ones above it. Nothing at or below the boundary ran after the action's
|
|
77
|
+
* write (its response and the follow-up cut there), so the next request must
|
|
78
|
+
* not hold it. ShortCodes nest, so those ids start with the boundary's: the
|
|
79
|
+
* boundary, its loaders (`${id}D…`), its slots and every entry under it. A
|
|
80
|
+
* sibling with a longer index (`…R10` beside `…R1`) is kept.
|
|
81
|
+
*/
|
|
82
|
+
export declare function idsAboveBoundary(ids: string[], boundary: string | undefined): string[];
|
|
83
|
+
/**
|
|
84
|
+
* The error segment of every action error boundary committed, by identity
|
|
85
|
+
* (server-action-bridge.ts adds and deletes). An entry shows one while its
|
|
86
|
+
* cached list still holds that object: a later commit on the entry replaces
|
|
87
|
+
* the list, and a refetch that holds the boundary keeps it. Weak, so a
|
|
88
|
+
* replaced boundary is not kept alive. Two routers never share a segment
|
|
89
|
+
* object. No hook reads it.
|
|
90
|
+
*/
|
|
91
|
+
export declare const actionBoundaries: WeakSet<ResolvedSegment>;
|
|
92
|
+
/**
|
|
93
|
+
* The index of the deepest action error boundary in `segments`, -1 for none.
|
|
94
|
+
* It is that action's outcome, which no GET reproduces: a background refetch
|
|
95
|
+
* of the page (the follow-up, Back/Forward's stale revalidation, the
|
|
96
|
+
* cross-tab refresh) holds it and renders what is above it. At 0 nothing is
|
|
97
|
+
* above it.
|
|
98
|
+
*/
|
|
99
|
+
export declare function actionBoundaryAt(segments: readonly ResolvedSegment[]): number;
|
|
@@ -191,11 +191,24 @@ export interface InflightAction {
|
|
|
191
191
|
* @internal This type is an implementation detail. Use PublicNavigationState instead.
|
|
192
192
|
*/
|
|
193
193
|
export interface NavigationState {
|
|
194
|
-
/**
|
|
194
|
+
/**
|
|
195
|
+
* Lifecycle state: `"loading"` while a navigation is in flight and while a
|
|
196
|
+
* server action runs, `"idle"` otherwise
|
|
197
|
+
*/
|
|
195
198
|
state: "idle" | "loading";
|
|
196
|
-
/**
|
|
199
|
+
/**
|
|
200
|
+
* Whether RSC data is currently streaming: a navigation's response, or a
|
|
201
|
+
* server action's response (initial load, navigation or action)
|
|
202
|
+
*/
|
|
197
203
|
isStreaming: boolean;
|
|
198
|
-
/**
|
|
204
|
+
/**
|
|
205
|
+
* True while a navigation is in flight (fetching or streaming, before its
|
|
206
|
+
* commit); false during a server action, whose `state` is still `"loading"`.
|
|
207
|
+
* Drive a navigation progress bar from this and an action spinner from
|
|
208
|
+
* `state`.
|
|
209
|
+
*/
|
|
210
|
+
isNavigating: boolean;
|
|
211
|
+
/** The page on screen; moves when the next page shows (`pendingUrl` is the page being fetched) */
|
|
199
212
|
location: NavigationLocation;
|
|
200
213
|
/** URL being navigated to (null when idle) */
|
|
201
214
|
pendingUrl: string | null;
|
|
@@ -450,6 +463,8 @@ export interface NavigateOptionsInternal extends Omit<NavigateOptions, "state">
|
|
|
450
463
|
_skipCache?: boolean;
|
|
451
464
|
/** Server redirects already followed by this navigation chain (0 for a user navigation) */
|
|
452
465
|
_redirectHops?: number;
|
|
466
|
+
/** The URL a redirected navigation chain started from: a link to it stays pending (useLinkStatus) */
|
|
467
|
+
_redirectFrom?: string;
|
|
453
468
|
}
|
|
454
469
|
/**
|
|
455
470
|
* Options for useRouter push/replace methods.
|
|
@@ -558,7 +573,8 @@ export interface NavigationStore {
|
|
|
558
573
|
*/
|
|
559
574
|
handlesPending?: boolean;
|
|
560
575
|
} | undefined;
|
|
561
|
-
|
|
576
|
+
/** Whether an intercept entry is cached for the plain `historyKey`, from any source page. */
|
|
577
|
+
hasInterceptCache(historyKey: string): boolean;
|
|
562
578
|
/**
|
|
563
579
|
* Update only the handleData (and optionally the stale / handlesPending flags)
|
|
564
580
|
* of an existing cache entry. When a flag is omitted the entry's current value
|
|
@@ -602,6 +618,8 @@ export interface FetchPartialOptions {
|
|
|
602
618
|
signal?: AbortSignal;
|
|
603
619
|
/** If true, this is a stale cache revalidation request - server should force revalidators */
|
|
604
620
|
staleRevalidation?: boolean;
|
|
621
|
+
/** Sent as `_rsc_boundary` (wire-params.ts WIRE.boundary). */
|
|
622
|
+
boundary?: string;
|
|
605
623
|
interceptSourceUrl?: string;
|
|
606
624
|
/** RSC version for cache invalidation detection */
|
|
607
625
|
version?: string;
|
|
@@ -666,7 +684,8 @@ export interface ServerActionBridgeConfig {
|
|
|
666
684
|
*/
|
|
667
685
|
export interface NavigationBridge {
|
|
668
686
|
navigate(url: string, options?: NavigateOptionsInternal): Promise<void>;
|
|
669
|
-
|
|
687
|
+
/** `crossTab`: another tab's write; an action's error boundary stays. */
|
|
688
|
+
refresh(crossTab?: boolean): Promise<void>;
|
|
670
689
|
/** `event`: the popstate event; a traversal the browser animated itself (hasUAVisualTransition) is not animated again. */
|
|
671
690
|
handlePopstate(event?: PopStateEvent): Promise<void>;
|
|
672
691
|
registerLinkInterception(): () => void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** The parameters of a partial request: a navigation, a prefetch or a JS server action. */
|
|
2
|
+
export interface PartialRequestInit {
|
|
3
|
+
/** A JS server action's id: written as `_rsc_action` in place of `_rsc_partial`. */
|
|
4
|
+
action?: string;
|
|
5
|
+
/** The mounted segment ids the server diffs against. */
|
|
6
|
+
segmentIds: readonly string[];
|
|
7
|
+
/**
|
|
8
|
+
* An empty `segmentIds`: "send" writes `_rsc_segments=` (navigation,
|
|
9
|
+
* action), "omit" leaves it out (prefetch). The prefetch cache keys carry
|
|
10
|
+
* the difference.
|
|
11
|
+
*/
|
|
12
|
+
emptySegments: "send" | "omit";
|
|
13
|
+
stale?: boolean;
|
|
14
|
+
boundary?: string;
|
|
15
|
+
version?: string;
|
|
16
|
+
routerId?: string;
|
|
17
|
+
rewriteTarget?: string;
|
|
18
|
+
fill?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Writes the partial-request parameters onto `url` in the one order every
|
|
22
|
+
* sender uses. Navigation and prefetch cache keys are built from the result
|
|
23
|
+
* (prefetch/cache.ts), so a navigation adopts a prefetch only while both
|
|
24
|
+
* write identically: browser/__tests__/wire-urls.test.ts pins the strings.
|
|
25
|
+
*/
|
|
26
|
+
export declare function writePartialParams(url: URL, init: PartialRequestInit): URL;
|
|
@@ -97,8 +97,10 @@ export declare const KEY_PART_PREFIX = "key:";
|
|
|
97
97
|
* (CacheScope.resolveKeyFrom, CacheScope.resolvePartition): the `key()`
|
|
98
98
|
* results of the scope's cache() chain, outermost first, then its default
|
|
99
99
|
* parts: the keyGenerator results of enclosing scopes on another store
|
|
100
|
-
* (#974) and, for a record key
|
|
101
|
-
* default key (or its store's keyGenerator result,
|
|
100
|
+
* (#974) and, for a route record key, the scope's own part: without a
|
|
101
|
+
* `key()` of its own, its default key (or its store's keyGenerator result,
|
|
102
|
+
* #970); with one, the default key's request kind (`doc`, `partial` or
|
|
103
|
+
* `intercept:<intercept>`, routeRecordKind in cache-scope.ts).
|
|
102
104
|
*
|
|
103
105
|
* Key scheme invariant (#975). A `key()` result is often request input,
|
|
104
106
|
* and a record key has no route or scope discriminator (the store reads
|
|
@@ -124,9 +126,13 @@ export declare const KEY_PART_PREFIX = "key:";
|
|
|
124
126
|
* A namespaced `key()` result starts with `key:` and holds no `|`. A
|
|
125
127
|
* composed key holds a `|` and either starts with `key:` or holds no `:`.
|
|
126
128
|
* Among composed keys, splitting on `|` recovers each part, a part's kind
|
|
127
|
-
* (a `key:` prefix, or no `:` at all) and its value.
|
|
128
|
-
*
|
|
129
|
-
*
|
|
129
|
+
* (a `key:` prefix, or no `:` at all) and its value. A request kind part is
|
|
130
|
+
* a default key's prefix without the URL after it, so it never equals a
|
|
131
|
+
* default key part; a keyGenerator part can equal it (`doc`) only when the
|
|
132
|
+
* keyGenerator returns a constant, which already gives every URL one record.
|
|
133
|
+
* Pinned by the collision probe in
|
|
134
|
+
* src/cache/__tests__/cache-scope-chain.test.ts. A keyGenerator result is
|
|
135
|
+
* the store's own namespace, as before.
|
|
130
136
|
*
|
|
131
137
|
* Shared with the testing helper `shellCacheKey`, so a test builds the
|
|
132
138
|
* production partition.
|
|
@@ -14,16 +14,23 @@ import { type ExecutionStart } from "./tag-invalidation.js";
|
|
|
14
14
|
import { type OwnedPushDelivery } from "./handle-snapshot.js";
|
|
15
15
|
import type { RequestContext } from "../server/request-context.js";
|
|
16
16
|
type CacheKeyFn = NonNullable<PartialCacheOptions["key"]>;
|
|
17
|
+
/**
|
|
18
|
+
* A route record that answered. `restoreHandles` is set when the lookup left
|
|
19
|
+
* the handle restore to its caller (lookupRouteDetailed `deferHandles`),
|
|
20
|
+
* which names the segments it sends (handle-snapshot.ts restoreHandles).
|
|
21
|
+
*/
|
|
22
|
+
export interface CachedRouteHit {
|
|
23
|
+
segments: ResolvedSegment[];
|
|
24
|
+
shouldRevalidate: boolean;
|
|
25
|
+
restoreHandles?: (sentIds: ReadonlySet<string>) => Promise<void>;
|
|
26
|
+
}
|
|
17
27
|
/**
|
|
18
28
|
* Discriminated outcome of a route cache lookup — see
|
|
19
29
|
* {@link CacheScope.lookupRouteDetailed} for what each status licenses.
|
|
20
30
|
*/
|
|
21
31
|
export type CacheRouteLookupOutcome = {
|
|
22
32
|
status: "hit";
|
|
23
|
-
result:
|
|
24
|
-
segments: ResolvedSegment[];
|
|
25
|
-
shouldRevalidate: boolean;
|
|
26
|
-
};
|
|
33
|
+
result: CachedRouteHit;
|
|
27
34
|
} | {
|
|
28
35
|
status: "miss" | "bypass" | "error";
|
|
29
36
|
};
|
|
@@ -187,14 +194,18 @@ export declare class CacheScope {
|
|
|
187
194
|
* enclosing partition (#970, #974). A scope whose own config sets no
|
|
188
195
|
* `key()` appends its own default key (resolveDefaultKey). Reusing the
|
|
189
196
|
* outer `key()` result alone would give every route under the inner
|
|
190
|
-
* cache() one record: a `key()` replaces the
|
|
191
|
-
* outer key that names no route (`tier:gold`) would make `/a` HIT
|
|
192
|
-
* record. A scope with its own `key()` adds no default key:
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
197
|
+
* cache() one record: a `key()` replaces the default key's URL part, so
|
|
198
|
+
* an outer key that names no route (`tier:gold`) would make `/a` HIT
|
|
199
|
+
* `/b`'s record. A scope with its own `key()` adds no default key: its `key()`
|
|
200
|
+
* replaces the URL part, and its store's keyGenerator does not run. It
|
|
201
|
+
* appends `kind` instead (routeRecordKind): the `key()` decides which
|
|
202
|
+
* requests of one kind share a record, never that a document, a
|
|
203
|
+
* navigation and an intercept navigation do. With no partition part it is
|
|
204
|
+
* resolveDefaultKey alone. With a `key()` on the chain but no request
|
|
205
|
+
* context it rejects (keyWithoutContextError). `partitionedPrefix`
|
|
206
|
+
* prefixes a key built from partition parts only (the response family's
|
|
207
|
+
* `response:`, which passes no `kind`: a response route answers every
|
|
208
|
+
* request alike).
|
|
198
209
|
*
|
|
199
210
|
* Each `key()` result lives on the request context (`_resolvedCacheKeys`),
|
|
200
211
|
* by function: it runs once per request whatever the default key
|
|
@@ -205,7 +216,7 @@ export declare class CacheScope {
|
|
|
205
216
|
* itself: a `key()` calling `cookies()` would trip the capture guard there,
|
|
206
217
|
* and a capture must store the partition its request resolved.
|
|
207
218
|
*/
|
|
208
|
-
resolveKeyFrom(defaultKey: string, partitionedPrefix?: string): Promise<string>;
|
|
219
|
+
resolveKeyFrom(defaultKey: string, partitionedPrefix?: string, kind?: string): Promise<string>;
|
|
209
220
|
/**
|
|
210
221
|
* @internal The request partition of a ppr route's shell under this scope
|
|
211
222
|
* (resolveShellPartition): its partition parts (resolvePartitionParts),
|
|
@@ -285,14 +296,14 @@ export declare class CacheScope {
|
|
|
285
296
|
*
|
|
286
297
|
* @param pathname - URL pathname for cache key generation
|
|
287
298
|
* @param params - Route params for cache key generation
|
|
288
|
-
* @param
|
|
299
|
+
* @param intercept - The intercept an intercept navigation selected
|
|
300
|
+
* (interceptRecordKey): its record has its own key
|
|
289
301
|
* @param ownedPushes - What the record is to each loader's handle pushes
|
|
290
302
|
* (withCacheLookup: loader-cache.ts loaderPins), called on a hit
|
|
303
|
+
* @param deferHandles - Restore no handle value here: the caller calls the
|
|
304
|
+
* hit's `restoreHandles` once it decided which segments it sends
|
|
291
305
|
*/
|
|
292
|
-
lookupRoute(pathname: string, params: Record<string, string>,
|
|
293
|
-
segments: ResolvedSegment[];
|
|
294
|
-
shouldRevalidate: boolean;
|
|
295
|
-
} | null>;
|
|
306
|
+
lookupRoute(pathname: string, params: Record<string, string>, intercept?: string, ownedPushes?: () => OwnedPushDelivery, deferHandles?: boolean): Promise<CachedRouteHit | null>;
|
|
296
307
|
/**
|
|
297
308
|
* @internal lookupRoute with a discriminated outcome. The PPR replay
|
|
298
309
|
* composition (withCacheLookup) may substitute the seeded doc record ONLY on
|
|
@@ -311,7 +322,7 @@ export declare class CacheScope {
|
|
|
311
322
|
* A corrupt entry that was evicted reads as `miss`: the store was consulted
|
|
312
323
|
* and holds nothing servable, which is the post-eviction truth.
|
|
313
324
|
*/
|
|
314
|
-
lookupRouteDetailed(pathname: string, params: Record<string, string>,
|
|
325
|
+
lookupRouteDetailed(pathname: string, params: Record<string, string>, intercept?: string, ownedPushes?: () => OwnedPushDelivery, deferHandles?: boolean): Promise<CacheRouteLookupOutcome>;
|
|
315
326
|
/**
|
|
316
327
|
* Record this scope's segment-DSL cache({ tags }) into the request tag union
|
|
317
328
|
* synchronously, under the same gate cacheRoute() uses for a write.
|
|
@@ -341,13 +352,14 @@ export declare class CacheScope {
|
|
|
341
352
|
* @param pathname - URL pathname for cache key generation
|
|
342
353
|
* @param params - Route params for cache key generation
|
|
343
354
|
* @param segments - All resolved segments to cache
|
|
344
|
-
* @param
|
|
355
|
+
* @param intercept - The intercept an intercept navigation selected
|
|
356
|
+
* (interceptRecordKey): its record has its own key
|
|
345
357
|
* @param start - Where the render of `segments` started: the record is not
|
|
346
358
|
* written when one of its tags was invalidated since (#977,
|
|
347
359
|
* predatesInvalidation). A shell capture's doc record passes none: it
|
|
348
360
|
* lives only in the shell entry, which putShell gates by its own start.
|
|
349
361
|
*/
|
|
350
|
-
cacheRoute(pathname: string, params: Record<string, string>, segments: ResolvedSegment[],
|
|
362
|
+
cacheRoute(pathname: string, params: Record<string, string>, segments: ResolvedSegment[], intercept?: string, start?: ExecutionStart): Promise<void>;
|
|
351
363
|
}
|
|
352
364
|
/**
|
|
353
365
|
* @internal The request partition of a ppr route's shell: with a route
|
|
@@ -392,7 +404,7 @@ export declare function createShellImplicitDocScope(marker: ShellImplicitCacheMa
|
|
|
392
404
|
* normal partial navigation replay), substitute an implicit doc-level scope
|
|
393
405
|
* so withCacheLookup/withCacheStore treat the WHOLE matched route as a
|
|
394
406
|
* cache() boundary — the shell entry IS a cache() of the handler layer, with
|
|
395
|
-
* loaders as the live carve-outs (
|
|
407
|
+
* loaders as the live carve-outs (serveStoredSegments).
|
|
396
408
|
*
|
|
397
409
|
* A document HIT tail (`docTail`) always gets the implicit scope: it replays
|
|
398
410
|
* the shell's own record and never consults a route-derived scope, whose
|
|
@@ -38,13 +38,13 @@ export declare const CACHE_REVALIDATING_AT_HEADER = "x-edge-cache-revalidating-a
|
|
|
38
38
|
* re-arm re-puts the full window and restarts CF's retention clock, pinning a
|
|
39
39
|
* perpetually-stale entry (one whose background revalidation keeps failing) past
|
|
40
40
|
* its intended hard-expiry indefinitely. Mirrors the KVSegmentEnvelope `e`
|
|
41
|
-
* field and the remaining-ttl math in
|
|
41
|
+
* field and the remaining-ttl math in promoteToL1.
|
|
42
42
|
* @internal
|
|
43
43
|
*/
|
|
44
44
|
export declare const CACHE_EXPIRES_AT_HEADER = "x-edge-cache-expires-at";
|
|
45
45
|
/**
|
|
46
46
|
* Header stashing the route author's original Cache-Control on L1 document
|
|
47
|
-
* entries. putResponse/
|
|
47
|
+
* entries. putResponse/promoteToL1 overwrite Cache-Control with a long
|
|
48
48
|
* `max-age` so the CF Cache API retains the entry across the whole SWR window;
|
|
49
49
|
* getResponse restores this original value before serving so the client and any
|
|
50
50
|
* upstream CDN see the author's intended directive, not the internal edge TTL.
|