@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
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derived render passes over a request past its middleware (PPR shell
|
|
3
|
+
* capture, PPR HIT tail, background re-render, document cache re-run), each
|
|
4
|
+
* `Object.create(base)`.
|
|
5
|
+
* A field missing from a RENDER_PASS_FIELDS row reads the foreground
|
|
6
|
+
* request's value (#684). derived-context-shape.rsc-test.tsx pins each row's
|
|
7
|
+
* own keys.
|
|
8
|
+
*/
|
|
9
|
+
import type { RecordingShellStore } from "../cache/shell-snapshot.js";
|
|
10
|
+
import type { HandleStore } from "./handle-store.js";
|
|
11
|
+
import { type RequestContext } from "./request-context.js";
|
|
12
|
+
type ShellImplicitCache = NonNullable<RequestContext["_shellImplicitCache"]>;
|
|
13
|
+
/** _handleStore, readonly on RequestContext, is written by the rows. */
|
|
14
|
+
type PassUnderConstruction = RequestContext<any> & {
|
|
15
|
+
_handleStore: HandleStore;
|
|
16
|
+
};
|
|
17
|
+
/** What each purpose's caller builds for its row. */
|
|
18
|
+
export interface RenderPassInit {
|
|
19
|
+
"shell-capture": {
|
|
20
|
+
handleStore: HandleStore;
|
|
21
|
+
/** A navigation-only capture renders this URL instead of the request's. */
|
|
22
|
+
identity: {
|
|
23
|
+
request: Request;
|
|
24
|
+
url: URL;
|
|
25
|
+
} | undefined;
|
|
26
|
+
/** Only with a cache store on the request. */
|
|
27
|
+
recording: {
|
|
28
|
+
store: RecordingShellStore;
|
|
29
|
+
implicitCache: ShellImplicitCache;
|
|
30
|
+
} | undefined;
|
|
31
|
+
};
|
|
32
|
+
"ppr-tail": {
|
|
33
|
+
/** The request's store, shared: the tail's handles are this response's. */
|
|
34
|
+
handleStore: HandleStore;
|
|
35
|
+
loaderSeed: RequestContext["_shellLoaderSeed"];
|
|
36
|
+
implicitCache: ShellImplicitCache;
|
|
37
|
+
};
|
|
38
|
+
"background-revalidation": {
|
|
39
|
+
handleStore: HandleStore;
|
|
40
|
+
/** Throwaway: the pass's response writes land here and are dropped. */
|
|
41
|
+
sink: RequestContext<any>;
|
|
42
|
+
};
|
|
43
|
+
"document-revalidation": {
|
|
44
|
+
/** The request's: the stale HIT pushed nothing into it. */
|
|
45
|
+
handleStore: HandleStore;
|
|
46
|
+
/**
|
|
47
|
+
* Holds the re-run's response writes, which make the response the
|
|
48
|
+
* document cache stores; starts from the request's response stub.
|
|
49
|
+
*/
|
|
50
|
+
sink: RequestContext<any>;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export type RenderPurpose = keyof RenderPassInit;
|
|
54
|
+
interface PassFieldPolicy<I> {
|
|
55
|
+
/** "own": wireRenderBarrier(pass, init.handleStore) before `own` runs. */
|
|
56
|
+
readonly renderBarrier: "own" | "inherited";
|
|
57
|
+
/**
|
|
58
|
+
* Named stores, not one Object.assign: on Node 24 an Object.assign that
|
|
59
|
+
* takes the object to 20 own properties leaves it in V8 dictionary mode
|
|
60
|
+
* (#1109).
|
|
61
|
+
*/
|
|
62
|
+
readonly own: (pass: PassUnderConstruction, init: I, base: RequestContext<any>) => void;
|
|
63
|
+
}
|
|
64
|
+
export declare const RENDER_PASS_FIELDS: {
|
|
65
|
+
readonly [P in RenderPurpose]: PassFieldPolicy<RenderPassInit[P]>;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* `Object.create(base)` with RENDER_PASS_FIELDS[purpose]'s own fields. The only
|
|
69
|
+
* place a request context is derived (tools/check-internals.mjs).
|
|
70
|
+
*/
|
|
71
|
+
export declare function deriveRenderPass<P extends RenderPurpose, TEnv>(base: RequestContext<TEnv>, purpose: P, init: RenderPassInit[P]): RequestContext<TEnv>;
|
|
72
|
+
export {};
|
|
@@ -29,6 +29,7 @@ import type { RenderMode, RenderPhase } from "../router/timeout.js";
|
|
|
29
29
|
import type { LocationStateEntry } from "../browser/react/location-state-shared.js";
|
|
30
30
|
import type { RoutineTrace } from "../rsc/routine-plan.js";
|
|
31
31
|
import type { ActionContinuation } from "../rsc/server-action.js";
|
|
32
|
+
import type { ShellCaptureState } from "../rsc/shell-capture.js";
|
|
32
33
|
import type { FormActionOutcome } from "../rsc/progressive-enhancement.js";
|
|
33
34
|
import { type ExecutionStart } from "../cache/invalidation-order.js";
|
|
34
35
|
export interface RenderForegroundCursor {
|
|
@@ -182,8 +183,8 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
182
183
|
method: string;
|
|
183
184
|
/**
|
|
184
185
|
* @internal Handle store for tracking handle data across segments.
|
|
185
|
-
* Readonly: a
|
|
186
|
-
* (
|
|
186
|
+
* Readonly: a render that needs its own store derives a render pass
|
|
187
|
+
* (deriveRenderPass, server/render-pass.ts) instead of swapping this field,
|
|
187
188
|
* which the foreground still reads while it produces the page.
|
|
188
189
|
*/
|
|
189
190
|
readonly _handleStore: HandleStore;
|
|
@@ -233,52 +234,13 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
233
234
|
*/
|
|
234
235
|
_searchParamsFilter?: import("../cache/search-params-filter.js").SearchParamsFilter;
|
|
235
236
|
/**
|
|
236
|
-
* @internal PPR shell
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
* (key/ttl/swr/tags/store) is NOT threaded through the request context — the
|
|
244
|
-
* integrated PPR serve path (rsc/shell-serve.ts + rsc-rendering.ts) builds it
|
|
245
|
-
* locally and passes it to scheduleShellCapture directly.
|
|
246
|
-
*/
|
|
247
|
-
_shellCaptureRun?: boolean;
|
|
248
|
-
/**
|
|
249
|
-
* @internal Set beside `_shellCaptureRun` when the shell is keyed by the
|
|
250
|
-
* visitor's URL (`rewrite(...).shell("visitor")`): the capture renders the
|
|
251
|
-
* visitor's location and `ctx.rewrittenFrom`; the theme stays the default.
|
|
252
|
-
*/
|
|
253
|
-
_shellCaptureForVisitor?: boolean;
|
|
254
|
-
/**
|
|
255
|
-
* @internal Bake-lane loader containers collected DURING a shell capture:
|
|
256
|
-
* segment-key -> the loader's (pre-wrap) result promise. Populated by
|
|
257
|
-
* resolveLoaderData for bake-lane loaders (lane rule: see its JSDoc in
|
|
258
|
-
* loader-cache.ts). Drained by captureAndStoreShell after the shell
|
|
259
|
-
* quiesces: settled containers are promise-elided, Flight-serialized, and
|
|
260
|
-
* pinned into the snapshot's loader family; a REJECTED container refuses
|
|
261
|
-
* the capture (error UI must never bake into the shared shell). Own
|
|
262
|
-
* property of the capture's derived context only.
|
|
263
|
-
*/
|
|
264
|
-
_shellCaptureLoaderRecords?: Map<string, Promise<unknown>>;
|
|
265
|
-
/**
|
|
266
|
-
* @internal Set on a capture's derived context when a loader pushed a
|
|
267
|
-
* value the record cannot keep (masked nested promises, a pushed promise
|
|
268
|
-
* that settled to one, a live-lane loader's push, or a push outside a
|
|
269
|
-
* loader body): the loader records then carry `runs: 1`, so a HIT still
|
|
270
|
-
* runs their bodies for those pushes.
|
|
271
|
-
*/
|
|
272
|
-
_shellCaptureUnrecordedLoaderPush?: true;
|
|
273
|
-
/**
|
|
274
|
-
* @internal The lane of each loader the capture's matched route registers
|
|
275
|
-
* (loader-cache.ts routeLoaderLanes), set by createMatchContextForFull
|
|
276
|
-
* before any loader runs. The capture's push funnel credits a push made
|
|
277
|
-
* under a live-lane loader's body, at any depth, to that loader
|
|
278
|
-
* (shell-capture.ts deriveShellCaptureContext). Own property of the
|
|
279
|
-
* capture's derived context only.
|
|
280
|
-
*/
|
|
281
|
-
_shellCaptureLoaderLanes?: ReadonlyMap<string, "live" | "bake">;
|
|
237
|
+
* @internal A PPR shell capture's own state (rsc/shell-capture.ts
|
|
238
|
+
* ShellCaptureState): created by RENDER_PASS_FIELDS["shell-capture"]
|
|
239
|
+
* (server/render-pass.ts) on the capture's derived context. The foreground
|
|
240
|
+
* render and every background re-render never have one, so
|
|
241
|
+
* `_shellCaptureState?.run` is the capture switch.
|
|
242
|
+
*/
|
|
243
|
+
_shellCaptureState?: ShellCaptureState;
|
|
282
244
|
/**
|
|
283
245
|
* @internal Record keys resolved for this request (CacheScope
|
|
284
246
|
* resolveKeyFrom): by the scope's `key()` (one result) or its store's
|
|
@@ -295,9 +257,9 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
295
257
|
_shellKey?: string;
|
|
296
258
|
/**
|
|
297
259
|
* @internal The request carried the forced-MISS reload marker
|
|
298
|
-
* (
|
|
299
|
-
*
|
|
300
|
-
* cache miss.
|
|
260
|
+
* (`WIRE.shellMiss`). The handler strips the marker from the request on
|
|
261
|
+
* entry (shell-serve.ts withoutShellMissMarker) and sets this; the shell
|
|
262
|
+
* gate renders the request like a cache miss.
|
|
301
263
|
*/
|
|
302
264
|
_shellForcedMiss?: true;
|
|
303
265
|
/**
|
|
@@ -314,16 +276,6 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
314
276
|
* runtime has no AsyncLocalStorage.snapshot.
|
|
315
277
|
*/
|
|
316
278
|
_runAtRequestEntry?: <T>(fn: () => T) => T;
|
|
317
|
-
/**
|
|
318
|
-
* @internal The freshness window of the route cache() records this
|
|
319
|
-
* request read or wrote (cache-scope.ts noteRouteRecordWindow), as ms
|
|
320
|
-
* timestamps: `freshUntil` is the record's `expiresAt`, `staleUntil` adds
|
|
321
|
-
* its scope's swr. The narrowest record wins. A shell capture caps its
|
|
322
|
-
* entry's ttl and ttl+swr to it (shell-capture.ts capShellWindow), so a
|
|
323
|
-
* shell is never fresher, or served longer, than the route cache() entry
|
|
324
|
-
* it replayed or wrote.
|
|
325
|
-
*/
|
|
326
|
-
_routeRecordWindow?: RouteRecordWindow;
|
|
327
279
|
/**
|
|
328
280
|
* @internal Loader-family snapshot seed for a shell HIT's tail render:
|
|
329
281
|
* loader id -> the capture's elided container (already Flight-deserialized
|
|
@@ -445,30 +397,6 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
445
397
|
* it as an own property for exactly that reason.
|
|
446
398
|
*/
|
|
447
399
|
_shellFragmentPayload?: boolean;
|
|
448
|
-
/**
|
|
449
|
-
* @internal Set by the capture guard (server/context.ts
|
|
450
|
-
* guardIdentityRead) when it throws DURING a capture render: the read
|
|
451
|
-
* ("cookies()", "headers()", `ctx.get() for a non-cacheable variable`,
|
|
452
|
-
* "ctx.theme") and the fix the
|
|
453
|
-
* refusal warning gives for it. Load-bearing for the
|
|
454
|
-
* bake lane: a guard throw inside an executing loader is swallowed by
|
|
455
|
-
* wrapLoaderPromise into per-loader error UI, which would otherwise bake
|
|
456
|
-
* silently into the shared shell — the capture checks this flag after the
|
|
457
|
-
* render and refuses instead. Deterministic, so the capture does not retry.
|
|
458
|
-
*/
|
|
459
|
-
_shellCaptureGuardTripped?: {
|
|
460
|
-
surface: string;
|
|
461
|
-
fix: string;
|
|
462
|
-
};
|
|
463
|
-
/**
|
|
464
|
-
* @internal The loader $$id whose BODY was executing when the capture guard
|
|
465
|
-
* tripped (read off the loader-body ALS scope at trip time), or undefined
|
|
466
|
-
* when the read came from handler/render code. Only used to make the
|
|
467
|
-
* once-per-key refusal warning name the real source — the old text
|
|
468
|
-
* hardcoded "a bake-lane loader", which misattributed handler-land reads
|
|
469
|
-
* and sent users debugging the wrong lane (issue #672, secondary).
|
|
470
|
-
*/
|
|
471
|
-
_shellCaptureGuardTrippedLoaderId?: string;
|
|
472
400
|
/**
|
|
473
401
|
* @internal Handler-owned registry of explicit per-scope stores from
|
|
474
402
|
* cache({ store }). Created once per createRSCHandler() and threaded into
|
|
@@ -732,8 +660,8 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
732
660
|
* (loader(Def, { ssr: false })): segment resolution awaits these
|
|
733
661
|
* before returning, so the render barrier cannot resolve until they settle.
|
|
734
662
|
* rendered() checks this set to fail fast — a flagged loader awaiting the
|
|
735
|
-
* barrier is a guaranteed cycle, not a race. Registered by
|
|
736
|
-
*
|
|
663
|
+
* barrier is a guaranteed cycle, not a race. Registered by resolveOwnerLoaders
|
|
664
|
+
* before loader kickoff; only ever populated on document renders
|
|
737
665
|
* (the flag is stamped per-isSSR at DSL evaluation).
|
|
738
666
|
*/
|
|
739
667
|
_awaitBeforeFlushLoaderIds?: Set<string>;
|
|
@@ -755,6 +683,15 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
755
683
|
_renderBarrierGuardClosed?: boolean;
|
|
756
684
|
/** @internal Per-request error dedup set for onError reporting */
|
|
757
685
|
_reportedErrors: WeakSet<object>;
|
|
686
|
+
/**
|
|
687
|
+
* @internal The segment a parallel slot's or orphan layout's error came
|
|
688
|
+
* from, for the owning entry's catch (segment-resolution/helpers.ts
|
|
689
|
+
* noteThrower). Per request: an error object can be thrown by several.
|
|
690
|
+
*/
|
|
691
|
+
_throwers?: WeakMap<object, {
|
|
692
|
+
id: string;
|
|
693
|
+
type: string;
|
|
694
|
+
}>;
|
|
758
695
|
/**
|
|
759
696
|
* @internal The errors this request printed to the server console, so a
|
|
760
697
|
* failure prints once where it originated (server/print-server-error.ts). A derived context shares it through the prototype.
|
|
@@ -811,6 +748,12 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
811
748
|
* keeping phases that began before the opt-in at their true (non-negative) offset.
|
|
812
749
|
*/
|
|
813
750
|
_handlerStart?: number;
|
|
751
|
+
/**
|
|
752
|
+
* @internal Handler-level Server-Timing entries (rsc/handler.ts): the
|
|
753
|
+
* bootstrap timings, then the core handler's classify. A stale document
|
|
754
|
+
* cache entry's re-run has its own (render-pass.ts).
|
|
755
|
+
*/
|
|
756
|
+
_handlerTiming?: string[];
|
|
814
757
|
/** @internal Resolved platform phase-span tracing for this request (Cloudflare or OTel) */
|
|
815
758
|
_tracing?: ResolvedTracing;
|
|
816
759
|
/** @internal Router basename for this request (used by redirect()) */
|
|
@@ -846,27 +789,13 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
846
789
|
*/
|
|
847
790
|
_cacheSignal?: import("../router/telemetry.js").CacheSegmentSignal[];
|
|
848
791
|
}
|
|
849
|
-
/**
|
|
850
|
-
* @internal The freshness window of a route cache() record, as ms
|
|
851
|
-
* timestamps: fresh until `freshUntil` (its `expiresAt`), stale until
|
|
852
|
-
* `staleUntil` (plus its scope's swr). `ttl`, `swr` and `written` describe
|
|
853
|
-
* the record that sets `staleUntil`: its cache() config, and whether this
|
|
854
|
-
* request wrote it (cacheRoute) rather than read it.
|
|
855
|
-
*/
|
|
856
|
-
export interface RouteRecordWindow {
|
|
857
|
-
freshUntil: number;
|
|
858
|
-
staleUntil: number;
|
|
859
|
-
ttl: number;
|
|
860
|
-
swr: number;
|
|
861
|
-
written: boolean;
|
|
862
|
-
}
|
|
863
792
|
/**
|
|
864
793
|
* Public view of RequestContext, without internal methods and fields.
|
|
865
794
|
*
|
|
866
795
|
* This is the type exported to library consumers. Internal code should
|
|
867
796
|
* use the full RequestContext interface directly.
|
|
868
797
|
*/
|
|
869
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "
|
|
798
|
+
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "_shellCaptureState" | "_shellImplicitCache" | "_shellLoaderSeed" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_prerenderWarm" | "_runAtRequestEntry" | "_shellFragmentPayload" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_payloadDeferred" | "_requestKind" | "_payloadVisitorLocation" | "_locationState" | "_routeName" | "_prevRouteKey" | "_visitorMoved" | "_inActionRevalidation" | "_actionRan" | "_reportedErrors" | "_throwers" | "_printedErrors" | "_renderErrors" | "_recoveredHandlerErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_handlerTiming" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
870
799
|
/**
|
|
871
800
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
872
801
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
|
@@ -896,6 +825,26 @@ export declare function captureRequestEntryContext(): (<T>(fn: () => T) => T) |
|
|
|
896
825
|
* Used by the RSC handler to provide context to server actions
|
|
897
826
|
*/
|
|
898
827
|
export declare function runWithRequestContext<TEnv, T>(context: RequestContext<TEnv>, fn: () => T): T;
|
|
828
|
+
/**
|
|
829
|
+
* Run work whose output goes only to a cache, never to the response of the
|
|
830
|
+
* request that started it, on `context`: a stale entry's refresh (a "use
|
|
831
|
+
* cache" function, a cached loader, a cache() record, a document), a
|
|
832
|
+
* navigation's proactive cache() write, a PPR shell capture. No visitor made
|
|
833
|
+
* the invalidations in it, so they set no fresh-reads cookie
|
|
834
|
+
* (cache/tag-invalidation.ts), and onError marks every error reported inside
|
|
835
|
+
* it `background` (router/error-handling.ts invokeOnError). Its failure is
|
|
836
|
+
* reported inside it too: a catch outside runs on the visitor's frame.
|
|
837
|
+
*/
|
|
838
|
+
export declare function runAsBackgroundWork<TEnv, T>(context: RequestContext<TEnv>, fn: () => T): T;
|
|
839
|
+
/** Whether the caller runs inside runAsBackgroundWork. */
|
|
840
|
+
export declare function isBackgroundWork(): boolean;
|
|
841
|
+
/**
|
|
842
|
+
* The set onError's dedupe records a reported error in. Background work keeps
|
|
843
|
+
* its own: an error object both the visitor's render and background work
|
|
844
|
+
* reach (a memoized rejection, a thrown constant) is reported by each, so a
|
|
845
|
+
* background report never takes the place of the visitor's.
|
|
846
|
+
*/
|
|
847
|
+
export declare function reportedErrorsOf(context: RequestContext<any>): WeakSet<object>;
|
|
899
848
|
/**
|
|
900
849
|
* Get the current request context
|
|
901
850
|
* Throws if called outside of a request context
|
|
@@ -1004,8 +953,8 @@ export declare function rebaseRequestContext(ctx: RequestContext<any>, request:
|
|
|
1004
953
|
/**
|
|
1005
954
|
* Wire a fresh render barrier onto `ctx`, closure-bound to THIS ctx and THIS
|
|
1006
955
|
* handle store. Called by createRequestContext for every fresh context, and by
|
|
1007
|
-
*
|
|
1008
|
-
*
|
|
956
|
+
* deriveRenderPass (server/render-pass.ts) for a derived pass whose
|
|
957
|
+
* RENDER_PASS_FIELDS row owns its barrier (the PPR capture and the HIT tail).
|
|
1009
958
|
*
|
|
1010
959
|
* The derived-context call is load-bearing (issue #684, plan 009): the capture
|
|
1011
960
|
* context is `Object.create(reqCtx)`, so without its own wiring every
|
|
@@ -25,12 +25,12 @@ export declare function recordRewriteHop(reqCtx: TrailContext, from: URL, to: UR
|
|
|
25
25
|
export declare function recordRewriteShell(reqCtx: TrailContext, audience: RewriteShell | undefined): void;
|
|
26
26
|
/** The last hop's `rewrite(...).shell()` choice; undefined: none. */
|
|
27
27
|
export declare function rewriteShellAudience(reqCtx: TrailContext | undefined): RewriteShell | undefined;
|
|
28
|
-
type AudienceContext = Pick<RequestContext<any>, "
|
|
28
|
+
type AudienceContext = Pick<RequestContext<any>, "_shellCaptureState" | "_documentCacheRender" | "res">;
|
|
29
29
|
/**
|
|
30
30
|
* A render other visitors may be served: a PPR shell capture, or a render
|
|
31
31
|
* the document cache stores (its response opted in before next()). It shows
|
|
32
32
|
* no visitor theme, and no visitor URL unless it is a visitor-keyed shell
|
|
33
|
-
* capture (`
|
|
33
|
+
* capture (`_shellCaptureState.forVisitor`).
|
|
34
34
|
*/
|
|
35
35
|
export declare function rendersForSharedAudience(reqCtx: AudienceContext): boolean;
|
|
36
36
|
/**
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
* dispatch — in-process request -> Response for unit/integration tests,
|
|
3
3
|
* WITHOUT the Flight RSC runtime.
|
|
4
4
|
*
|
|
5
|
-
* dispatch runs the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* dispatch runs the production handler's request stages
|
|
6
|
+
* (rsc/request-stages.ts: classify, the terminal plans, the global middleware
|
|
7
|
+
* passes, the response route and the response's finalization) so that
|
|
8
|
+
* redirects, 404s, reloads, response routes (path.json / path.text /
|
|
9
|
+
* path.html / ...), and middleware short-circuits behave exactly as in
|
|
10
|
+
* production. It deliberately
|
|
8
11
|
* does NOT render React Server Components: there is no Flight stream, no SSR,
|
|
9
12
|
* and no DOM. Hit an RSC (component) route and dispatch throws a clear error
|
|
10
13
|
* directing you to renderToFlightString/renderServerTree/renderHandler or an e2e test.
|
|
@@ -17,19 +20,20 @@
|
|
|
17
20
|
* so a global auth middleware can 401/redirect them and middleware-set
|
|
18
21
|
* cookies/headers merge onto the 308/404 the way createResponseWithMergedHeaders
|
|
19
22
|
* merges them in production.
|
|
20
|
-
* - Response routes (non-RSC)
|
|
23
|
+
* - Response routes (non-RSC), served by production's handleResponseRoute
|
|
24
|
+
* (rsc/response-route-handler.ts) -> serialized Response
|
|
21
25
|
* - json: JSON.stringify(result) (bare value) with application/json
|
|
22
26
|
* - text/html/xml/md: String(result) with the mapped MIME type
|
|
23
|
-
* - handler returning or throwing a Response: re-wrapped
|
|
24
|
-
*
|
|
25
|
-
*
|
|
27
|
+
* - handler returning or throwing a Response: re-wrapped (stub
|
|
28
|
+
* headers/cookies merged, Set-Cookie preserved, WebSocket upgrade passed
|
|
29
|
+
* through without reconstruction)
|
|
26
30
|
* - handler throwing a non-Response error: typed 500 / RouterError
|
|
27
|
-
* status
|
|
28
|
-
*
|
|
31
|
+
* status (RFC 9457 problem+json body with application/problem+json for
|
|
32
|
+
* json routes, text/plain message otherwise)
|
|
29
33
|
* - content-negotiated route: Vary: Accept appended
|
|
30
34
|
* - cached response route (cache({...})): getResponse/putResponse
|
|
31
|
-
* hit/SWR/tag write, resolved from the matched entry tree
|
|
32
|
-
*
|
|
35
|
+
* hit/SWR/tag write, resolved from the matched entry tree. The write is
|
|
36
|
+
* scheduled via ctx.waitUntil
|
|
33
37
|
* (a microtask without an executionContext), so a HIT-asserting test must
|
|
34
38
|
* flush microtasks between the seeding dispatch and the asserting one.
|
|
35
39
|
* - Global middleware (router.use(...)) AND route-level middleware, with full
|
|
@@ -38,10 +42,17 @@
|
|
|
38
42
|
* global middleware runs first (so an auth gate can still 401/redirect),
|
|
39
43
|
* then — if it passes through — an X-RSC-Reload is returned. Route-level
|
|
40
44
|
* middleware is skipped on a partial, exactly as production skips it.
|
|
41
|
-
* - A middleware redirect (3xx + Location) on a partial/action request
|
|
42
|
-
* (?_rsc_partial / ?_rsc_action)
|
|
43
|
-
*
|
|
45
|
+
* - A global middleware redirect (3xx + Location) on a partial/action request
|
|
46
|
+
* (?_rsc_partial / ?_rsc_action), and a findMatch() redirect on a partial
|
|
47
|
+
* request: a 204 + X-RSC-Redirect, so fetch() does not auto-follow the 3xx —
|
|
44
48
|
* identical to production's no-location-state path.
|
|
49
|
+
* - The terminal plans production answers inside the global chain
|
|
50
|
+
* (terminalPlanResponse): a `_rsc_v` version mismatch and a `_rsc_rid` app
|
|
51
|
+
* switch reload (X-RSC-Reload), and an action (?_rsc_action) a rewrite moved
|
|
52
|
+
* to a target that is not a page route throws production's error.
|
|
53
|
+
* - Route params and name are set inside the global chain, after classify, by
|
|
54
|
+
* the stage production's executeRequest runs (recordPlanRoute): global
|
|
55
|
+
* middleware sees them after next(), not before it.
|
|
45
56
|
* - The open-redirect guard (rsc/redirect-guard.ts) on full (browser-followed)
|
|
46
57
|
* redirects: a cross-origin Location is rewritten to the basename root unless
|
|
47
58
|
* redirect(url, { external: true }) opted out, mirroring production's single
|
|
@@ -60,7 +71,9 @@
|
|
|
60
71
|
* after finalizeResponse (segmentCount 0 / cacheHit false — dispatch renders no
|
|
61
72
|
* RSC segments and holds no match-cache state), and a thrown non-Response error
|
|
62
73
|
* emits request.error with phase "routing". All three carry the same requestId
|
|
63
|
-
* (getRequestId)
|
|
74
|
+
* (getRequestId), as does a response-route timeout on a rewritten pass
|
|
75
|
+
* (runRequestPasses carries the id to each pass's request, as in
|
|
76
|
+
* production). Emission is gated entirely on a configured sink; with none,
|
|
64
77
|
* dispatch does zero new work and stays byte-identical for existing callers.
|
|
65
78
|
* Lets a consumer unit-test their sink wiring in-process instead of only at e2e.
|
|
66
79
|
* - Response-route `renderStartMs` timeouts and `onTimeout`: dispatch races the
|
|
@@ -96,9 +109,13 @@
|
|
|
96
109
|
* request.start/end/error lifecycle above; cover cache/loader telemetry with an
|
|
97
110
|
* e2e test driving a real RSC request.
|
|
98
111
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* route
|
|
112
|
+
* Each pass is classified with the handler's classify stage
|
|
113
|
+
* (router/request-classification.ts classifyRequest), which runs content
|
|
114
|
+
* negotiation and resolves route middleware from the matched entry tree, so
|
|
115
|
+
* dispatch's route-middleware collection is exactly the router's, not a
|
|
116
|
+
* re-implementation. The origin guard is not run: it gates only the action,
|
|
117
|
+
* loader and PE-form plans, which classify gives a component route only, and
|
|
118
|
+
* dispatch throws on those before the pass's middleware.
|
|
102
119
|
*/
|
|
103
120
|
import type { Rango } from "../router/router-interfaces.js";
|
|
104
121
|
/**
|
|
@@ -26,24 +26,30 @@
|
|
|
26
26
|
* - navigate() drives the navigation lifecycle as a click does:
|
|
27
27
|
* useNavigation() reads loading from the call and idle with the commit,
|
|
28
28
|
* and useLinkStatus().pending is true for a link to the destination until
|
|
29
|
-
* the commit
|
|
29
|
+
* the commit, which React holds with it. A `transition` spec plus a pending
|
|
30
30
|
* Promise seeded via navigate(url, { loaders }) commits through
|
|
31
31
|
* production's commitInTransition (browser/partial-update.ts), which React
|
|
32
32
|
* holds: useNavigation() stays loading and the held reader's
|
|
33
33
|
* useLoader().isLoading reads true until the data lands. Without
|
|
34
34
|
* `transition` the commit is urgent (production's same-structure hold is
|
|
35
|
-
* not modeled).
|
|
35
|
+
* not modeled). navigate(url, { streamUntil }) gives the navigation a
|
|
36
|
+
* response stream that stays open past the commit (isStreaming).
|
|
37
|
+
* useAction().state stays idle: no action runs.
|
|
36
38
|
* - A spec's transition({ when }) decides every commit with production's
|
|
37
39
|
* browser decision: navigate() and useRouter().push model kind "push",
|
|
38
|
-
* useRouter().replace kind "replace", refresh() kind "revalidate"
|
|
39
|
-
*
|
|
40
|
-
* e2e territory.
|
|
40
|
+
* useRouter().replace kind "replace", refresh() kind "revalidate", and a
|
|
41
|
+
* back/forward that restores a page kind "pop". Action and optimistic
|
|
42
|
+
* clientUrls() swap decisions are e2e territory.
|
|
41
43
|
* - Location state reaches readers the way it does in production:
|
|
42
44
|
* NavigationProvider holds the committed entry's state next to the
|
|
43
45
|
* payload, so a navigation whose loader the test holds keeps the entry
|
|
44
46
|
* being left on screen with its own state. A `popstate` event is a
|
|
45
|
-
* back/forward onto the entry history.state holds
|
|
46
|
-
*
|
|
47
|
+
* back/forward onto the entry history.state holds. When it is the
|
|
48
|
+
* mounted entry or one a navigate() wrote, history still holds the state
|
|
49
|
+
* written there, and another page is on screen, its page is restored
|
|
50
|
+
* from the history cache, with the handle values it had, as production's
|
|
51
|
+
* restore is; otherwise the tree keeps its location. A stale entry's
|
|
52
|
+
* revalidation, a restore that fetches, a server action's state, a
|
|
47
53
|
* redirect's and an intercept's are e2e territory.
|
|
48
54
|
* What it DOES cover: client hooks that read NavigationProvider /
|
|
49
55
|
* OutletContext — useParams, useReverse, useHref, useMount, useNavigation,
|
|
@@ -361,8 +367,37 @@ export interface TestRouterHandle {
|
|
|
361
367
|
* `handles`). They arrive on the response's handle stream, so `useHandle`
|
|
362
368
|
* readers take them with the page's commit: while React holds the page,
|
|
363
369
|
* readers keep the values of the page being left.
|
|
370
|
+
*
|
|
371
|
+
* `options.streamUntil` gives the navigation a response stream, as a real
|
|
372
|
+
* response has: it opens in a task after the call, before the commit (the
|
|
373
|
+
* response arrives, and `useNavigation().pendingUrl` clears), and stays open
|
|
374
|
+
* until the promise settles (a page that streams a tail past its commit:
|
|
375
|
+
* `isStreaming` reads true until then). Without it the navigation has no
|
|
376
|
+
* stream. A navigation that a newer one or a back/forward aborts before its
|
|
377
|
+
* response arrives opens none and commits nothing; one aborted after its
|
|
378
|
+
* response arrived stops counting as streaming at the abort, as in
|
|
379
|
+
* production, where its response streams on and is ignored.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* const tail = deferred();
|
|
383
|
+
* await router.navigate("/products/2", { streamUntil: tail.promise });
|
|
384
|
+
* // useNavigation(): idle, isStreaming true
|
|
385
|
+
* await act(async () => tail.resolve());
|
|
386
|
+
* // useNavigation(): idle, isStreaming false
|
|
387
|
+
*
|
|
388
|
+
* A navigation started while React holds a page goes inside
|
|
389
|
+
* `await act(async () => ...)`. Its first update makes React retry the held
|
|
390
|
+
* page, which suspends again; a synchronous act() scope drops that retry
|
|
391
|
+
* and React renders no later update of the same priority.
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* await act(async () => {
|
|
395
|
+
* await router.navigate("/products/3", { transition: false });
|
|
396
|
+
* });
|
|
364
397
|
*/
|
|
365
|
-
navigate(url: string, options?: Pick<RenderRouteOptions, "loaders" | "handles"> & Pick<NavigateOptions, "state" | "replace" | "transition">
|
|
398
|
+
navigate(url: string, options?: Pick<RenderRouteOptions, "loaders" | "handles"> & Pick<NavigateOptions, "state" | "replace" | "transition"> & {
|
|
399
|
+
streamUntil?: Promise<unknown>;
|
|
400
|
+
}): Promise<void>;
|
|
366
401
|
/**
|
|
367
402
|
* Re-render the current location, as router.refresh() does: a spec's
|
|
368
403
|
* transition({ when }) decides it with kind "revalidate" (`to` is `from`).
|
|
@@ -81,7 +81,13 @@ export interface ServeShellRequestOptions<TEnv = any> {
|
|
|
81
81
|
* and segments take an action's revalidation defaults; it renders live, as
|
|
82
82
|
* an action does, so neither the route cache nor the document cache answers
|
|
83
83
|
* or stores it, and a `ppr` route's `replayStatus` is
|
|
84
|
-
* `{ outcome: "BYPASS", reason: "stale" }`.
|
|
84
|
+
* `{ outcome: "BYPASS", reason: "stale" }`. `boundary` names the error
|
|
85
|
+
* segment of a thrown action's boundary the page at `from` shows
|
|
86
|
+
* (`_rsc_boundary`), as the follow-up an earlier action owes that page
|
|
87
|
+
* sends it, with `stale: true` and no `segments`: the response renders
|
|
88
|
+
* every segment above the boundary and nothing at or below it, claims the
|
|
89
|
+
* boundary in `matched` and sends no segment for it. The server reads it
|
|
90
|
+
* only beside `stale`.
|
|
85
91
|
*/
|
|
86
92
|
partial?: true | {
|
|
87
93
|
from?: string;
|
|
@@ -91,6 +97,7 @@ export interface ServeShellRequestOptions<TEnv = any> {
|
|
|
91
97
|
fill?: boolean;
|
|
92
98
|
interceptSource?: string;
|
|
93
99
|
stale?: boolean;
|
|
100
|
+
boundary?: string;
|
|
94
101
|
};
|
|
95
102
|
/**
|
|
96
103
|
* POST this form as a submit before hydration: the no-JS request the
|
|
@@ -130,9 +130,12 @@ export interface CacheOptions<TEnv = unknown> {
|
|
|
130
130
|
*/
|
|
131
131
|
condition?: (ctx: import("../server/request-context.js").RequestContext<TEnv>) => boolean;
|
|
132
132
|
/**
|
|
133
|
-
* Custom cache key function
|
|
134
|
-
*
|
|
135
|
-
*
|
|
133
|
+
* Custom cache key function. Replaces the URL part of the default key
|
|
134
|
+
* (host, path, params, search) AND bypasses the store's keyGenerator. The
|
|
135
|
+
* request kind stays: a document request, a navigation and each intercept
|
|
136
|
+
* navigation keep their own record under one result, so the result decides
|
|
137
|
+
* which requests of one kind share a record. It is stored namespaced
|
|
138
|
+
* (`key:` plus its URI encoding, then the kind), so no value it returns
|
|
136
139
|
* names another route's record; a nested cache() keys its records within
|
|
137
140
|
* this partition.
|
|
138
141
|
*
|
|
@@ -67,11 +67,38 @@ export interface OnErrorContext<TEnv = any> {
|
|
|
67
67
|
actionId?: string;
|
|
68
68
|
/** Environment/bindings (platform context) */
|
|
69
69
|
env?: TEnv;
|
|
70
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Duration from request start to error (milliseconds). For a `background`
|
|
72
|
+
* error it counts from the start of the request that started the work, so
|
|
73
|
+
* it includes that response and any wait before the work ran.
|
|
74
|
+
*/
|
|
71
75
|
duration?: number;
|
|
72
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Whether this is a partial/navigation request, on an error the segment
|
|
78
|
+
* walk catches (a handler that throws, a streamed `loading()` handler that
|
|
79
|
+
* rejects, a DSL loader that rejects): `true` for a navigation, unset for a
|
|
80
|
+
* document. A `cache()` record's refresh or proactive write reports the
|
|
81
|
+
* request that started it; a PPR shell capture renders a document. The
|
|
82
|
+
* `routing` phase reports `false`.
|
|
83
|
+
*/
|
|
73
84
|
isPartial?: boolean;
|
|
74
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* `true` when the error came from work whose output goes to a cache and
|
|
87
|
+
* never to the response of the request that started it: a stale `cache()`
|
|
88
|
+
* record's refresh, the write of a navigation that kept a layout mounted, a
|
|
89
|
+
* stale document cache entry's re-run, a PPR shell capture, or a stale
|
|
90
|
+
* `"use cache"` function's or cached loader's refresh, the work's own
|
|
91
|
+
* failure included. `request` and `url` are the starting request's (a
|
|
92
|
+
* shell capture's handler errors name the page it captures). A
|
|
93
|
+
* `router.prerender()` warm's own render is its request's: unset, while a
|
|
94
|
+
* shell capture it makes is `true`. Unset for every other error.
|
|
95
|
+
*/
|
|
96
|
+
background?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Whether an error boundary caught the error and its fallback reached the
|
|
99
|
+
* response. `false` on a `background` error: the failed render is never
|
|
100
|
+
* stored, so no visitor sees the fallback.
|
|
101
|
+
*/
|
|
75
102
|
handledByBoundary?: boolean;
|
|
76
103
|
/** Stack trace (if available) */
|
|
77
104
|
stack?: string;
|
|
@@ -342,7 +342,7 @@ export type InternalHandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch exte
|
|
|
342
342
|
_reverseScope?: import("../server/context.js").ReverseScope;
|
|
343
343
|
/**
|
|
344
344
|
* @internal The on-demand overlay holds a "removed" marker for this request
|
|
345
|
-
* (
|
|
345
|
+
* (readPrerenderSource, cache-lookup.ts); gateOnDemandProducer reads it. On
|
|
346
346
|
* this context, not the request's: withCacheLookup documents that the
|
|
347
347
|
* request ALS can be lost mid-pipeline on workerd.
|
|
348
348
|
*/
|
|
@@ -390,6 +390,14 @@ export type InternalHandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch exte
|
|
|
390
390
|
* request is a fill. See router/segment-resolution/prefetch-deferral.ts.
|
|
391
391
|
*/
|
|
392
392
|
_prefetchDeferral?: import("../router/segment-resolution/prefetch-deferral.js").PrefetchDeferral;
|
|
393
|
+
/**
|
|
394
|
+
* @internal DSL loaders registered and not started, by `$$id`: a prefetch
|
|
395
|
+
* deferred them, or a pass that skips loaders (`skipLoaders`) did not run
|
|
396
|
+
* them. A reader's ctx.use() starts one through its registration
|
|
397
|
+
* (registerDeferredLoader, startDeferredLoader in
|
|
398
|
+
* router/segment-resolution/prefetch-deferral.ts).
|
|
399
|
+
*/
|
|
400
|
+
_deferredLoaders?: Map<string, import("../router/segment-resolution/prefetch-deferral.js").DeferredLoader>;
|
|
393
401
|
/**
|
|
394
402
|
* @internal Whether a loader was started in this request: a run of it (a
|
|
395
403
|
* handler's or another loader's ctx.use()) or its cache() binding. A
|
|
@@ -151,7 +151,7 @@ export interface ResolvedSegment {
|
|
|
151
151
|
loaderData?: any;
|
|
152
152
|
/**
|
|
153
153
|
* True when this loader was awaited before first flush
|
|
154
|
-
* (loader(Def, { ssr: false })). Stamped by
|
|
154
|
+
* (loader(Def, { ssr: false })). Stamped by resolveOwnerLoaders on
|
|
155
155
|
* document AND shell-capture renders — capture bakes flagged loaders and
|
|
156
156
|
* awaits the same lane. Feeds segment-system's settled-value delivery and
|
|
157
157
|
* the dev SSR suspension warning (ssr-suspension-warning.ts).
|