@rangojs/router 0.22.0 → 0.23.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 +8 -3
- package/dist/testing/vitest.js +31 -1
- package/dist/types/browser/defer.d.ts +48 -0
- package/dist/types/browser/document-revealed.d.ts +17 -0
- package/dist/types/browser/event-controller.d.ts +7 -1
- package/dist/types/browser/navigation-transaction.d.ts +21 -7
- package/dist/types/browser/partial-update.d.ts +34 -5
- package/dist/types/browser/react/NavigationProvider.d.ts +13 -3
- package/dist/types/browser/react/filter-segment-order.d.ts +7 -0
- package/dist/types/browser/response-adapter.d.ts +7 -0
- package/dist/types/browser/types.d.ts +19 -9
- package/dist/types/browser/validate-redirect-origin.d.ts +11 -0
- package/dist/types/build/generate-route-types.d.ts +1 -1
- package/dist/types/build/route-types/router-processing.d.ts +1 -1
- package/dist/types/build/route-types/scan-filter.d.ts +16 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +16 -1
- package/dist/types/cache/cf/cf-cache-types.d.ts +23 -2
- package/dist/types/client-urls/client-urls.d.ts +1 -1
- package/dist/types/client-urls/hoisted-revalidate.d.ts +13 -0
- package/dist/types/client-urls/navigation.d.ts +0 -37
- package/dist/types/client-urls/revalidate-registry.d.ts +4 -0
- package/dist/types/client-urls/server-projection.d.ts +29 -1
- package/dist/types/client-urls/types.d.ts +34 -69
- package/dist/types/client.d.ts +0 -1
- package/dist/types/errors.d.ts +5 -0
- package/dist/types/handles/deferred-resolution.d.ts +2 -1
- package/dist/types/handles/pushed-by.d.ts +23 -0
- package/dist/types/loader-store.d.ts +8 -0
- package/dist/types/prefetch-markers.d.ts +11 -0
- package/dist/types/route-definition/helpers-types.d.ts +27 -0
- package/dist/types/router/is-action.d.ts +2 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -2
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +241 -0
- package/dist/types/server/context.d.ts +21 -1
- package/dist/types/server/handle-store.d.ts +9 -1
- package/dist/types/server/request-context.d.ts +14 -1
- package/dist/types/server.d.ts +1 -0
- package/dist/types/testing/flight.entry.d.ts +1 -1
- package/dist/types/testing/index.d.ts +3 -3
- package/dist/types/testing/internal/action-id.d.ts +10 -1
- package/dist/types/testing/internal/client-urls-projection.d.ts +16 -0
- package/dist/types/testing/internal/test-action.d.ts +8 -0
- package/dist/types/testing/run-loader.d.ts +2 -1
- package/dist/types/testing/run-revalidate.d.ts +74 -0
- package/dist/types/testing/run-transition-when.d.ts +2 -3
- package/dist/types/testing/serve-shell-request.d.ts +38 -0
- package/dist/types/testing/vitest.d.ts +11 -0
- package/dist/types/types/boundaries.d.ts +9 -0
- package/dist/types/types/handler-context.d.ts +14 -0
- package/dist/types/types/loader-types.d.ts +30 -0
- package/dist/types/types/segments.d.ts +21 -4
- package/dist/types/urls/path-helper-types.d.ts +25 -4
- package/dist/types/urls/type-extraction.d.ts +6 -2
- package/dist/types/vite/discovery/discover-routers.d.ts +9 -0
- package/dist/types/vite/discovery/state.d.ts +11 -4
- package/dist/types/vite/plugins/client-urls-revalidate-hoist.d.ts +54 -0
- package/dist/types/vite/plugins/hoist/literal.d.ts +83 -0
- package/dist/types/vite/plugins/hoist/scope.d.ts +40 -0
- package/dist/types/vite/plugins/hoist/source.d.ts +41 -0
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +8 -11
- package/dist/types/vite/router-discovery.d.ts +10 -0
- package/dist/vite/index.js +843 -309
- package/package.json +2 -2
- package/skills/caching/SKILL.md +42 -5
- package/skills/catalog.json +2 -2
- package/skills/client-urls/SKILL.md +113 -24
- package/skills/cloudflare/SKILL.md +14 -9
- package/skills/hooks/SKILL.md +11 -3
- package/skills/links/SKILL.md +24 -0
- package/skills/loader/SKILL.md +192 -1
- package/skills/migrate-nextjs/SKILL.md +2 -2
- package/skills/migrate-react-router/SKILL.md +10 -7
- package/skills/migrate-react-router/data-and-actions.md +1 -1
- package/skills/ppr/SKILL.md +13 -0
- package/skills/prerender/SKILL.md +22 -8
- package/skills/rango/SKILL.md +12 -6
- package/skills/route/SKILL.md +139 -0
- package/skills/testing/SKILL.md +3 -2
- package/skills/testing/client-components.md +1 -1
- package/skills/testing/predicates.md +67 -32
- package/skills/testing/serve-shell-request.md +88 -18
- package/skills/testing/setup.md +2 -2
- package/skills/typesafety/route-types.md +2 -2
- package/skills/view-transitions/SKILL.md +26 -0
- package/src/browser/defer.ts +82 -0
- package/src/browser/document-revealed.ts +52 -0
- package/src/browser/event-controller.ts +43 -32
- package/src/browser/navigation-bridge.ts +64 -14
- package/src/browser/navigation-client.ts +48 -36
- package/src/browser/navigation-store.ts +13 -0
- package/src/browser/navigation-transaction.ts +25 -8
- package/src/browser/partial-update.ts +528 -135
- package/src/browser/prefetch/fetch.ts +2 -1
- package/src/browser/react/NavigationProvider.tsx +47 -28
- package/src/browser/react/filter-segment-order.ts +13 -2
- package/src/browser/response-adapter.ts +20 -0
- package/src/browser/rsc-router.tsx +17 -45
- package/src/browser/server-action-bridge.ts +19 -63
- package/src/browser/types.ts +19 -9
- package/src/browser/validate-redirect-origin.ts +16 -0
- package/src/build/generate-route-types.ts +1 -0
- package/src/build/route-types/router-processing.ts +3 -6
- package/src/build/route-types/scan-filter.ts +37 -10
- package/src/cache/cf/cf-cache-store.ts +59 -21
- package/src/cache/cf/cf-cache-types.ts +24 -2
- package/src/cache/document-cache.ts +22 -1
- package/src/client-urls/client-urls.ts +22 -6
- package/src/client-urls/hoisted-revalidate.ts +25 -0
- package/src/client-urls/navigation.ts +0 -96
- package/src/client-urls/revalidate-registry.ts +30 -0
- package/src/client-urls/server-projection.ts +151 -65
- package/src/client-urls/types.ts +39 -71
- package/src/client.tsx +9 -5
- package/src/errors.ts +15 -0
- package/src/handles/deferred-resolution.ts +28 -5
- package/src/handles/pushed-by.ts +122 -0
- package/src/loader-store.ts +18 -7
- package/src/prefetch-markers.ts +13 -0
- package/src/route-content-wrapper.tsx +18 -4
- package/src/route-definition/dsl-helpers.ts +27 -4
- package/src/route-definition/helpers-types.ts +27 -1
- package/src/router/intercept-resolution.ts +6 -4
- package/src/router/is-action.ts +2 -1
- package/src/router/loader-resolution.ts +83 -4
- package/src/router/match-api.ts +36 -1
- package/src/router/match-middleware/background-revalidation.ts +11 -1
- package/src/router/match-middleware/cache-lookup.ts +29 -6
- package/src/router/match-middleware/cache-store.ts +17 -1
- package/src/router/match-result.ts +14 -2
- package/src/router/navigation-snapshot.ts +2 -1
- package/src/router/segment-resolution/fresh.ts +22 -18
- package/src/router/segment-resolution/loader-cache.ts +2 -1
- package/src/router/segment-resolution/loader-mask.ts +5 -3
- package/src/router/segment-resolution/prefetch-deferral.ts +543 -0
- package/src/router/segment-resolution/revalidation.ts +169 -60
- package/src/rsc/rsc-rendering.ts +50 -7
- package/src/rsc/shell-capture.ts +2 -1
- package/src/segment-loader-promise.ts +23 -20
- package/src/segment-system.tsx +60 -26
- package/src/server/context.ts +39 -5
- package/src/server/handle-store.ts +104 -8
- package/src/server/loader-registry.ts +6 -1
- package/src/server/request-context.ts +21 -1
- package/src/server.ts +4 -0
- package/src/testing/action-form.ts +2 -11
- package/src/testing/e2e/page-helpers.ts +3 -1
- package/src/testing/flight.entry.ts +1 -0
- package/src/testing/index.ts +6 -3
- package/src/testing/internal/action-id.ts +16 -1
- package/src/testing/internal/client-urls-projection.ts +70 -0
- package/src/testing/internal/test-action.ts +25 -0
- package/src/testing/run-loader.ts +2 -1
- package/src/testing/run-revalidate.ts +142 -0
- package/src/testing/run-transition-when.ts +7 -8
- package/src/testing/serve-shell-request.ts +116 -6
- package/src/testing/vitest.ts +67 -1
- package/src/types/boundaries.ts +12 -0
- package/src/types/handler-context.ts +14 -0
- package/src/types/loader-types.ts +30 -0
- package/src/types/segments.ts +26 -4
- package/src/urls/path-helper-types.ts +27 -5
- package/src/urls/type-extraction.ts +30 -10
- package/src/use-loader.tsx +18 -13
- package/src/vite/discovery/client-urls-projection.ts +20 -21
- package/src/vite/discovery/discover-routers.ts +94 -26
- package/src/vite/discovery/state.ts +20 -4
- package/src/vite/discovery/virtual-module-codegen.ts +22 -17
- package/src/vite/plugins/client-urls-revalidate-hoist.ts +564 -0
- package/src/vite/plugins/hoist/literal.ts +417 -0
- package/src/vite/plugins/hoist/scope.ts +370 -0
- package/src/vite/plugins/hoist/source.ts +84 -0
- package/src/vite/plugins/transition-when-hoist.ts +113 -779
- package/src/vite/rango.ts +2 -0
- package/src/vite/router-discovery.ts +93 -32
- package/dist/types/client-urls/revalidate-chain.d.ts +0 -33
- package/dist/types/client-urls/revalidation-protocol.d.ts +0 -25
- package/dist/types/testing/run-client-revalidate.d.ts +0 -43
- package/src/client-urls/revalidate-chain.ts +0 -83
- package/src/client-urls/revalidation-protocol.ts +0 -56
- package/src/testing/run-client-revalidate.ts +0 -92
|
@@ -32,6 +32,16 @@ export interface ClientUrlProjectionRoute {
|
|
|
32
32
|
* document renders await them before first flush. Absent (= none) in
|
|
33
33
|
* projections serialized before the option existed. */
|
|
34
34
|
readonly awaitedLoaderIndices?: readonly number[];
|
|
35
|
+
/** Indices into loaderIds of loaders declared loader(Def, { prefetch:
|
|
36
|
+
* false }); materialization passes the option through to the server
|
|
37
|
+
* loader(), so a prefetch of the route defers them. Absent (= none) in
|
|
38
|
+
* projections serialized before the option existed. */
|
|
39
|
+
readonly deferrableLoaderIndices?: readonly number[];
|
|
40
|
+
/** Per loader (aligned with loaderIds), the keys of its hoisted
|
|
41
|
+
* revalidate() predicates in declaration order; materialization attaches
|
|
42
|
+
* the registered predicates (revalidate-registry.ts). Absent when no
|
|
43
|
+
* loader declares one. */
|
|
44
|
+
readonly loaderRevalidate?: readonly (readonly string[])[];
|
|
35
45
|
/** Data-only transition config (never `when`); absent in projections
|
|
36
46
|
* serialized before transition support. */
|
|
37
47
|
readonly transition?: Readonly<ClientTransitionConfig>;
|
|
@@ -54,7 +64,25 @@ export interface ClientUrlProjection {
|
|
|
54
64
|
* must treat missing as empty. */
|
|
55
65
|
readonly intercepts?: readonly ClientUrlProjectionIntercept[];
|
|
56
66
|
}
|
|
57
|
-
|
|
67
|
+
/** Options for {@link serializeClientUrlPatterns}. */
|
|
68
|
+
export interface SerializeClientUrlPatternsOptions {
|
|
69
|
+
/**
|
|
70
|
+
* The definition was loaded through the rango Vite plugin (route
|
|
71
|
+
* discovery), which moves every revalidate() predicate to the server and
|
|
72
|
+
* leaves a marker: a plain function then is a site the build could not
|
|
73
|
+
* see, and fails loudly.
|
|
74
|
+
*/
|
|
75
|
+
readonly hoisted?: boolean;
|
|
76
|
+
}
|
|
77
|
+
export declare function serializeClientUrlPatterns(patterns: ClientUrlPatterns, options?: SerializeClientUrlPatternsOptions): ClientUrlProjection;
|
|
78
|
+
/**
|
|
79
|
+
* The projection of a clientUrls() module from its namespace, or undefined
|
|
80
|
+
* when its default export is not a clientUrls() definition. Discovery
|
|
81
|
+
* (vite/discovery/client-urls-projection.ts) and the testing "use client"
|
|
82
|
+
* transform (testing/internal/client-urls-projection.ts) both project a
|
|
83
|
+
* module through it.
|
|
84
|
+
*/
|
|
85
|
+
export declare function projectClientUrlsModule(namespace: Readonly<Record<string, unknown>>, options?: SerializeClientUrlPatternsOptions): ClientUrlProjection | undefined;
|
|
58
86
|
export declare function isClientUrlPatterns(value: unknown): value is ClientUrlPatterns;
|
|
59
87
|
export declare function isClientUrlReference(value: unknown): value is ClientUrlReference;
|
|
60
88
|
/**
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { LoaderDefinition, LoaderOptions, ShouldRevalidateFn, TransitionConfig } from "../types.js";
|
|
3
|
+
import type { DefaultEnv } from "../types/global-namespace.js";
|
|
4
|
+
import type { HoistedRevalidateRef } from "./hoisted-revalidate.js";
|
|
3
5
|
import type { TrieMatchResult } from "../router/trie-matching.js";
|
|
4
6
|
import type { PathOptions } from "../urls/pattern-types.js";
|
|
5
7
|
import type { SearchSchema } from "../search-params.js";
|
|
@@ -18,67 +20,14 @@ export type ClientUrlUse = () => ClientUrlItems;
|
|
|
18
20
|
export type ClientPathOptions<TName extends string = string, TSearch extends SearchSchema = SearchSchema> = Pick<PathOptions<TName, TSearch>, "name" | "search" | "trailingSlash" | "ppr">;
|
|
19
21
|
export type ClientPathFn = <const TPattern extends string, const TName extends string = UnnamedRoute, const TSearch extends SearchSchema = {}>(pattern: TPattern, component: ComponentType, optionsOrUse?: ClientPathOptions<TName, TSearch> | ClientUrlUse, use?: ClientUrlUse) => ClientUrlItem & TypedRouteItem<TName, TPattern, unknown, TSearch>;
|
|
20
22
|
export type ClientLayoutFn = <const TItems extends ClientUrlItems>(component: ComponentType, children: () => TItems) => ClientUrlItem & TypedLayoutItem<ExtractRoutes<TItems>>;
|
|
21
|
-
/**
|
|
22
|
-
* Arguments a clientUrls() revalidate() predicate receives. A client-computable
|
|
23
|
-
* subset of the server ShouldRevalidateFn args — the predicate RUNS IN THE
|
|
24
|
-
* BROWSER (it is declared in a "use client" module and never crosses the
|
|
25
|
-
* projection boundary); only its decision is sent to the server. There is no
|
|
26
|
-
* `context` — no server handler context exists where this executes. `isAction`
|
|
27
|
-
* is the same callable matcher as on the server, not a boolean.
|
|
28
|
-
*/
|
|
29
|
-
export interface ClientRevalidateArgs {
|
|
30
|
-
/** Full URL of the page being navigated away from (current location). */
|
|
31
|
-
readonly currentUrl: URL;
|
|
32
|
-
/** Full URL of the navigation target (equals currentUrl for actions). */
|
|
33
|
-
readonly nextUrl: URL;
|
|
34
|
-
/** Route params of the held client route (definition-local match). */
|
|
35
|
-
readonly currentParams: Record<string, string>;
|
|
36
|
-
/** Route params for the navigation target (definition-local match). */
|
|
37
|
-
readonly nextParams: Record<string, string>;
|
|
38
|
-
/**
|
|
39
|
-
* The current default decision for this loader, computed client-side with
|
|
40
|
-
* the same rules the server applies to the request the decisions ride on:
|
|
41
|
-
* `true` when they ride the action POST itself, otherwise `true` when
|
|
42
|
-
* params/search changed. (An action-triggered refetch GET gets navigation
|
|
43
|
-
* defaults — matching the server — even though `isAction()` is true.)
|
|
44
|
-
* Earlier predicates' `{ defaultShouldRevalidate }` verdicts thread into
|
|
45
|
-
* this value, exactly like the server chain. Return it for default
|
|
46
|
-
* behavior plus your own conditions.
|
|
47
|
-
*/
|
|
48
|
-
readonly defaultShouldRevalidate: boolean;
|
|
49
|
-
/** True when this is a stale history-entry background revalidation. */
|
|
50
|
-
readonly stale: boolean;
|
|
51
|
-
/**
|
|
52
|
-
* Same {@link IsActionFn} the server `revalidate()` predicate receives.
|
|
53
|
-
* In the browser the match is against the action stub's hashed `$$id`
|
|
54
|
-
* (the id the action request carries) — not the RSC file-path `$id`.
|
|
55
|
-
*/
|
|
56
|
-
readonly isAction: IsActionFn;
|
|
57
|
-
/**
|
|
58
|
-
* The triggering server action's id, when this is an action. In the
|
|
59
|
-
* browser this is the hashed `hash#export` form (`$$id`), not the RSC
|
|
60
|
-
* file-path `src/...#export`. Prefer `isAction(ref)` — a substring of
|
|
61
|
-
* `path#export` will not match here in production.
|
|
62
|
-
*/
|
|
63
|
-
readonly actionId?: string;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Client-run per-loader predicate, with the same chain semantics as the
|
|
67
|
-
* server's `revalidate()` (src/router/revalidation.ts): a boolean is a HARD
|
|
68
|
-
* decision that short-circuits the rest of the chain; a
|
|
69
|
-
* `{ defaultShouldRevalidate }` object updates the running suggestion, which
|
|
70
|
-
* later predicates receive as their `defaultShouldRevalidate`; `void` /
|
|
71
|
-
* `null` / `undefined` defers to the current suggestion — so
|
|
72
|
-
* `isAction(CartActions) || undefined` defers to the locked default.
|
|
73
|
-
* Predicates must be synchronous; the object form requires a boolean value.
|
|
74
|
-
*/
|
|
75
|
-
export type ClientRevalidateFn = (args: ClientRevalidateArgs) => boolean | {
|
|
76
|
-
defaultShouldRevalidate: boolean;
|
|
77
|
-
} | null | void;
|
|
78
23
|
export interface ClientUrlLoaderRecord {
|
|
79
24
|
readonly loader: LoaderDefinition<any, any>;
|
|
80
|
-
/**
|
|
81
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Per-loader revalidate() predicates, run on the server; empty = the
|
|
27
|
+
* router's defaults. Under the rango Vite plugin the browser and SSR copies
|
|
28
|
+
* hold the marker the build left in place of each hoisted predicate.
|
|
29
|
+
*/
|
|
30
|
+
readonly revalidate: readonly (ShouldRevalidateFn<any, DefaultEnv> | HoistedRevalidateRef)[];
|
|
82
31
|
/**
|
|
83
32
|
* loader(Def, { ssr: false }): document renders await this loader before
|
|
84
33
|
* first flush (see {@link LoaderOptions}). Projected into the server tree,
|
|
@@ -86,6 +35,14 @@ export interface ClientUrlLoaderRecord {
|
|
|
86
35
|
* regardless.
|
|
87
36
|
*/
|
|
88
37
|
readonly ssr?: false;
|
|
38
|
+
/**
|
|
39
|
+
* loader(Def, { prefetch: false }): a prefetch of the route defers this
|
|
40
|
+
* loader and the click that adopts it runs it in its fill request (see
|
|
41
|
+
* {@link LoaderOptions}). Projected onto the materialized stub. Inside
|
|
42
|
+
* intercept() it is not recorded: intercept loaders ignore the flag, as in
|
|
43
|
+
* urls().
|
|
44
|
+
*/
|
|
45
|
+
readonly prefetch?: false;
|
|
89
46
|
}
|
|
90
47
|
/**
|
|
91
48
|
* The TransitionConfig subset a clientUrls() route may declare: ViewTransition
|
|
@@ -124,8 +81,7 @@ export interface ClientUrlHelpers {
|
|
|
124
81
|
readonly layout: ClientLayoutFn;
|
|
125
82
|
/**
|
|
126
83
|
* Attach a projected loader. The optional use callback may contain
|
|
127
|
-
* revalidate() only
|
|
128
|
-
* the function) is sent with the revalidation request.
|
|
84
|
+
* revalidate() only: a per-loader predicate the server runs, as in urls().
|
|
129
85
|
*
|
|
130
86
|
* Pass `{ ssr: false }` — the same knob as loading(fallback, { ssr:
|
|
131
87
|
* false }) — to await this loader before first flush on DOCUMENT requests
|
|
@@ -135,18 +91,27 @@ export interface ClientUrlHelpers {
|
|
|
135
91
|
* route the flag BAKES: the loader executes at shell capture and its
|
|
136
92
|
* settled return freezes into the shell (nested promises stay live
|
|
137
93
|
* holes).
|
|
94
|
+
*
|
|
95
|
+
* Pass `{ prefetch: false }` to keep this loader out of the route's
|
|
96
|
+
* prefetches (see {@link LoaderOptions}): an in-group click still shows
|
|
97
|
+
* the destination at once, commits the adopted prefetch with the other
|
|
98
|
+
* loaders' data, and runs only the flagged loaders in its one fill
|
|
99
|
+
* request. A `layout()` loader with the flag is flagged on every route
|
|
100
|
+
* below it. Inside intercept() the flag is accepted and ignored, as in
|
|
101
|
+
* urls().
|
|
138
102
|
*/
|
|
139
|
-
readonly loader: <TData>(definition: LoaderDefinition<TData>, optionsOrUse?: LoaderOptions | ClientUrlUse, use?: ClientUrlUse) => ClientUrlItem;
|
|
103
|
+
readonly loader: <TData>(definition: LoaderDefinition<TData>, optionsOrUse?: Pick<LoaderOptions, "ssr" | "prefetch"> | ClientUrlUse, use?: ClientUrlUse) => ClientUrlItem;
|
|
140
104
|
readonly loading: (component: ReactNode) => ClientUrlItem;
|
|
141
105
|
/**
|
|
142
106
|
* Per-loader revalidation predicate, valid inside a loader() use callback
|
|
143
|
-
* only.
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
107
|
+
* only. It runs ON THE SERVER with the same arguments as a urls() loader's
|
|
108
|
+
* revalidate() (`actionResult`, `formData`, `context`, `isAction`, route
|
|
109
|
+
* names, ...): the build moves it out of this "use client" module. It may
|
|
110
|
+
* reference imports and globals only; a binding of this module, `this`,
|
|
111
|
+
* `import()`, a browser global, an `async` function or an import from a
|
|
112
|
+
* "use client" module fails the build with its file and line.
|
|
148
113
|
*/
|
|
149
|
-
readonly revalidate: (fn:
|
|
114
|
+
readonly revalidate: (fn: ShouldRevalidateFn<any, DefaultEnv>) => ClientUrlItem;
|
|
150
115
|
/**
|
|
151
116
|
* Declare an intercept for a named route in THIS definition. The target is
|
|
152
117
|
* dot-local (`.detail`); scoping is module-local — only navigations whose
|
package/dist/types/client.d.ts
CHANGED
|
@@ -191,4 +191,3 @@ export { useReverse } from "./browser/react/use-reverse.js";
|
|
|
191
191
|
export type { ScopedReverseFunction, LocalReverseFunction } from "./reverse.js";
|
|
192
192
|
export type { LoaderDefinition } from "./types.js";
|
|
193
193
|
export type { ActionRef, IsActionFn } from "./types.js";
|
|
194
|
-
export type { ClientRevalidateArgs, ClientRevalidateFn, } from "./client-urls/types.js";
|
package/dist/types/errors.d.ts
CHANGED
|
@@ -212,6 +212,11 @@ export declare class InvalidHandlerError extends Error {
|
|
|
212
212
|
* ```
|
|
213
213
|
*/
|
|
214
214
|
export declare function invariant(condition: any, message: string): asserts condition;
|
|
215
|
+
/**
|
|
216
|
+
* Rejects a boolean-only DSL option that holds anything else (undefined
|
|
217
|
+
* passes), as an invariant.
|
|
218
|
+
*/
|
|
219
|
+
export declare function assertBooleanOption(value: unknown, option: string, effect: string): void;
|
|
215
220
|
/**
|
|
216
221
|
* Sanitize errors for production - prevents leaking sensitive information
|
|
217
222
|
*
|
|
@@ -24,7 +24,8 @@ export declare function deferredHandleNames(data: HandleData): Set<string>;
|
|
|
24
24
|
* thenables). A rejected deferred is dropped, and a deferred that resolves to
|
|
25
25
|
* `null`/`undefined` is dropped (the `.defer({ else })` skip semantics), so a
|
|
26
26
|
* nullish deferred slot never reaches a collector. Sync (non-thenable) values —
|
|
27
|
-
* including a legitimate sync `null` push — pass through unchanged.
|
|
27
|
+
* including a legitimate sync `null` push — pass through unchanged. A
|
|
28
|
+
* pushedBy record (pushed-by.ts) loses the entries of the dropped values.
|
|
28
29
|
*/
|
|
29
30
|
export declare function resolveDeferredHandleValues(data: HandleData): Promise<HandleData>;
|
|
30
31
|
/**
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { HandleData } from "../server/handle-store.js";
|
|
2
|
+
/** The snapshot key holding `handleName`'s pushedBy record. */
|
|
3
|
+
export declare function pushedByKey(handleName: string): string;
|
|
4
|
+
/** True for a pushedBy record's key, false for a handle's. */
|
|
5
|
+
export declare function isPushedByKey(name: string): boolean;
|
|
6
|
+
/** `data` without its pushedBy records, as a reader outside the router sees it. */
|
|
7
|
+
export declare function withoutPushedBy(data: HandleData): HandleData;
|
|
8
|
+
/**
|
|
9
|
+
* The handle data after a partial response's snapshot `incoming` (each stream
|
|
10
|
+
* yield holds everything the response pushed so far). A segment outside
|
|
11
|
+
* `segmentOrder` loses its buckets. In the others a value stands for the run
|
|
12
|
+
* that pushed it: the segment's handler, or a loader `matched` registers on
|
|
13
|
+
* the segment (`${shortCode}D${index}.${$$id}`, a loader's pushes being filed
|
|
14
|
+
* under its shortCode; an id it does not register, a dependency or a loader a
|
|
15
|
+
* handler read, counts as the handler's). A run that has values in the
|
|
16
|
+
* response, or ran for it (`resolvedIds`: the handlers and loaders that ran),
|
|
17
|
+
* replaces its values with the ones it delivered, nothing when it delivered
|
|
18
|
+
* none. The other runs keep theirs in place, and the response's values take
|
|
19
|
+
* the position of the first value they replace (the end when they replace
|
|
20
|
+
* none). New containers throughout: an object a reader was handed (a history
|
|
21
|
+
* entry's data) is never written to.
|
|
22
|
+
*/
|
|
23
|
+
export declare function mergePartialHandleData(current: HandleData, incoming: HandleData, segmentOrder: readonly string[], matched: readonly string[], resolvedIds: readonly string[] | undefined): HandleData;
|
|
@@ -215,6 +215,14 @@ export declare class LoaderStore {
|
|
|
215
215
|
* awaited before flush. Released as the stream settles, either way.
|
|
216
216
|
*/
|
|
217
217
|
trackPendingStream(loaderId: string, stream: Promise<unknown>): void;
|
|
218
|
+
/**
|
|
219
|
+
* Stop tracking a stream. trackPendingStream does it as the stream settles;
|
|
220
|
+
* an abandoned fill's hole (browser/partial-update.ts releaseHoles) never
|
|
221
|
+
* settles, and
|
|
222
|
+
* left tracked it would pin the family's held readers on every later
|
|
223
|
+
* transition.
|
|
224
|
+
*/
|
|
225
|
+
releasePendingStream(loaderId: string, stream: Promise<unknown>): void;
|
|
218
226
|
/** True while any navigation stream for `loaderId` is still pending. */
|
|
219
227
|
isStreamPending(loaderId: string): boolean;
|
|
220
228
|
/**
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wire markers of `prefetch: false` (docs/design/prefetch-false.md):
|
|
3
|
+
* shared by the browser that sends them and the server that reads them
|
|
4
|
+
* (router/segment-resolution/prefetch-deferral.ts requestKind). Dependency
|
|
5
|
+
* free, like segment-fragments.ts: the browser must not import the server
|
|
6
|
+
* module that reads them.
|
|
7
|
+
*/
|
|
8
|
+
/** Request header of a `<Link>` prefetch (browser/prefetch/fetch.ts). */
|
|
9
|
+
export declare const PREFETCH_HEADER = "X-Rango-Prefetch";
|
|
10
|
+
/** Query param of a fill request (browser/navigation-client.ts). */
|
|
11
|
+
export declare const FILL_PARAM = "_rsc_fill";
|
|
@@ -226,6 +226,16 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
226
226
|
* loader(RecommendationsLoader), // still streams behind loading()
|
|
227
227
|
* ```
|
|
228
228
|
*
|
|
229
|
+
* Pass `{ prefetch: false }` to keep the loader out of prefetches: a
|
|
230
|
+
* prefetch skips it and the click that adopts the prefetch fetches it in
|
|
231
|
+
* one follow-up request (see {@link LoaderOptions}). Only on a segment the
|
|
232
|
+
* client does not have yet: a loader the client already holds runs in the
|
|
233
|
+
* prefetch when it revalidates.
|
|
234
|
+
*
|
|
235
|
+
* ```typescript
|
|
236
|
+
* loader(ReviewsLoader, { prefetch: false }),
|
|
237
|
+
* ```
|
|
238
|
+
*
|
|
229
239
|
* @param loaderDef - Loader created with createLoader()
|
|
230
240
|
* @param optionsOrUse - Delivery options, or the use() callback when passing none
|
|
231
241
|
* @param use - Optional callback for loader-specific revalidation rules
|
|
@@ -239,13 +249,30 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
239
249
|
*
|
|
240
250
|
* // Skip loading on SSR, only show on client navigation
|
|
241
251
|
* loading(<Skeleton />, { ssr: false })
|
|
252
|
+
*
|
|
253
|
+
* // Keep everything behind this fallback out of prefetches
|
|
254
|
+
* loading(<Skeleton />, { prefetch: false })
|
|
242
255
|
* ```
|
|
243
256
|
* @param component - The loading UI to show during navigation
|
|
244
257
|
* @param options - Configuration options
|
|
245
258
|
* @param options.ssr - If false, skip showing loading on document requests (SSR)
|
|
259
|
+
* @param options.prefetch - If false, the flag applies when this entry's
|
|
260
|
+
* segment is new to the client. A prefetch then skips the whole unit: the
|
|
261
|
+
* handler, its loaders, its orphan layouts and parallel slots and, for a
|
|
262
|
+
* layout, every deeper entry; the click that adopts the prefetch shows
|
|
263
|
+
* this fallback and fetches them in one follow-up request, which reads
|
|
264
|
+
* cache() and "use cache" as any request does (a prefetch reads neither
|
|
265
|
+
* for skipped work). A segment the client already holds is never
|
|
266
|
+
* deferred: a prefetch renders it as usual when it revalidates, and what
|
|
267
|
+
* is below it follows its own flags. To keep a child out of prefetches
|
|
268
|
+
* while moving inside a section, flag the child's own loading(). An entry
|
|
269
|
+
* whose handler output is stored (cache(), ppr, Prerender/Static) is
|
|
270
|
+
* served as usual and only its loaders are skipped. Loaders behind the
|
|
271
|
+
* fallback cannot call ctx.rendered().
|
|
246
272
|
*/
|
|
247
273
|
loading: (component: ReactNode | (() => ReactNode), options?: {
|
|
248
274
|
ssr?: boolean;
|
|
275
|
+
prefetch?: boolean;
|
|
249
276
|
}) => LoadingItem;
|
|
250
277
|
/**
|
|
251
278
|
* Attach an error boundary to catch errors in this segment and children
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared `isAction()` matcher for revalidate predicates (server
|
|
2
|
+
* Shared `isAction()` matcher for revalidate() predicates (server) and
|
|
3
|
+
* transition({ when }) (browser).
|
|
3
4
|
*
|
|
4
5
|
* Action identity is `actionId`. The helper resolves an imported reference the
|
|
5
6
|
* same way the action boundary derives that id (`$id ?? $$id`), so a
|
|
@@ -24,8 +24,9 @@ import { type RequestContext } from "../../server/request-context.js";
|
|
|
24
24
|
export declare function isShellCaptureActive(reqCtx?: RequestContext<any> | undefined): boolean;
|
|
25
25
|
export { createMaskedLoaderPromise } from "./mask-nested.js";
|
|
26
26
|
/**
|
|
27
|
-
* True when the entry's loading() is renderable (
|
|
28
|
-
* isRenderableLoading
|
|
27
|
+
* True when the entry's loading() is renderable (the shared
|
|
28
|
+
* isRenderableLoading, types/boundaries.ts, that segment-system gates on).
|
|
29
|
+
* Not the lane decision (lane rule: see
|
|
29
30
|
* resolveLoaderData, loader-cache.ts): callers only use it to decide whether
|
|
30
31
|
* an unflagged loader's segment key rides as the bake/seed key, which is inert
|
|
31
32
|
* at capture.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `prefetch: false`: what a prefetch request defers and what its fill request
|
|
3
|
+
* runs (docs/design/prefetch-false.md).
|
|
4
|
+
*
|
|
5
|
+
* Two layers. The SCOPE is static per matched chain: which loader
|
|
6
|
+
* registrations are deferrable and which entries can be a handler unit. The
|
|
7
|
+
* PLAN is per match and rides the handler context
|
|
8
|
+
* (InternalHandlerContext._prefetchDeferral): the request's mode and where the
|
|
9
|
+
* chain's stored handler output starts. A request context cannot carry it: a
|
|
10
|
+
* shell capture derives its context from the request that scheduled it and
|
|
11
|
+
* would inherit a prefetch's mode.
|
|
12
|
+
*
|
|
13
|
+
* The decisions themselves are made in revalidation.ts, by asking this module.
|
|
14
|
+
*
|
|
15
|
+
* One rule runs through every decision: the flag applies only to a segment
|
|
16
|
+
* the client does not have yet. A segment the client holds is never deferred,
|
|
17
|
+
* whether or not it re-renders, and nothing is deferred because of it. A
|
|
18
|
+
* placeholder over content that is on screen would replace it with a fallback,
|
|
19
|
+
* or make the click wait where a plain navigation would not.
|
|
20
|
+
*
|
|
21
|
+
* "Holds" is what the request listed in `_rsc_segments` (PrefetchDeferral.held),
|
|
22
|
+
* the set buildMatchResult (match-result.ts) filters the response with. Not
|
|
23
|
+
* the set resolution works on: the match deletes a route's id from that one to
|
|
24
|
+
* force a same-route render from an intercept source (match-api.ts), and a
|
|
25
|
+
* unit deferred on that ground would be dropped from the response as held.
|
|
26
|
+
*/
|
|
27
|
+
import { type EntryData, type LoaderEntry } from "../../server/context.js";
|
|
28
|
+
import type { HandlerContext } from "../../types.js";
|
|
29
|
+
import type { CacheScope } from "../../cache/cache-scope.js";
|
|
30
|
+
/**
|
|
31
|
+
* What a request says it is, read once when its context is created
|
|
32
|
+
* (RequestContext._requestKind). A fill is marked on the raw URL and wins
|
|
33
|
+
* over the prefetch header. Whether a prefetch defers anything is decided per
|
|
34
|
+
* match, by partialDeferralMode: a shell capture inherits the context of the
|
|
35
|
+
* request that scheduled it and is never a prefetch.
|
|
36
|
+
*/
|
|
37
|
+
export declare function requestKind(request: Request, rawUrl: URL): "prefetch" | "fill" | undefined;
|
|
38
|
+
/** Static, per matched chain. */
|
|
39
|
+
interface DeferralScope {
|
|
40
|
+
/**
|
|
41
|
+
* Loader registrations a prefetch can defer, each with what makes it so:
|
|
42
|
+
* `true` for its own flag, else the segment ids of the flagged entries whose
|
|
43
|
+
* fallback covers it. A covered loader is deferred only while one of those
|
|
44
|
+
* segments is new to the client.
|
|
45
|
+
*/
|
|
46
|
+
readonly loaders: ReadonlyMap<LoaderEntry, true | readonly string[]>;
|
|
47
|
+
/** `$$id`s of `loaders`: the loaders that cannot call ctx.rendered(). */
|
|
48
|
+
readonly loaderIds: ReadonlySet<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Entries whose handler a prefetch can skip (a flagged loading() with a
|
|
51
|
+
* fallback to show). `index` is the chain index that owns the entry: its
|
|
52
|
+
* own for a chain entry, its parent's for a parallel entry. `ids` are its
|
|
53
|
+
* segment ids: the entry's for a chain entry, one per slot for a parallel
|
|
54
|
+
* entry.
|
|
55
|
+
*/
|
|
56
|
+
readonly units: ReadonlyMap<EntryData, DeferralUnit>;
|
|
57
|
+
}
|
|
58
|
+
interface DeferralUnit {
|
|
59
|
+
readonly index: number;
|
|
60
|
+
readonly ids: readonly string[];
|
|
61
|
+
}
|
|
62
|
+
/** Per match: InternalHandlerContext._prefetchDeferral. */
|
|
63
|
+
export interface PrefetchDeferral {
|
|
64
|
+
readonly scope: DeferralScope;
|
|
65
|
+
/**
|
|
66
|
+
* "prefetch": deferral replaces execution. "fill": the request that follows
|
|
67
|
+
* an adopted prefetch; a held segment is skipped outright. Unset on every
|
|
68
|
+
* other request, where the plan only feeds the ctx.rendered() guards.
|
|
69
|
+
*/
|
|
70
|
+
readonly mode?: "prefetch" | "fill";
|
|
71
|
+
/**
|
|
72
|
+
* First chain index whose handler output is stored or about to be (a
|
|
73
|
+
* cache() boundary, a ppr or Prerender route): no unit at or below it.
|
|
74
|
+
*/
|
|
75
|
+
readonly storedFrom: number;
|
|
76
|
+
/** The segment ids the request listed as held (`_rsc_segments`). */
|
|
77
|
+
readonly held: ReadonlySet<string>;
|
|
78
|
+
/**
|
|
79
|
+
* Segment ids of the handler units this prefetch skips: every unit that is
|
|
80
|
+
* not stored and not held. Empty outside a prefetch.
|
|
81
|
+
*/
|
|
82
|
+
readonly skipped: ReadonlySet<string>;
|
|
83
|
+
/**
|
|
84
|
+
* One of `skipped` is a chain entry: nothing below it runs, so the response
|
|
85
|
+
* has no content for it, a route cache() record included.
|
|
86
|
+
*/
|
|
87
|
+
readonly skipsChain: boolean;
|
|
88
|
+
/** Segment id of the handler unit this prefetch skipped. */
|
|
89
|
+
deferredUnit?: string;
|
|
90
|
+
/**
|
|
91
|
+
* The walk is below a chain unit it skipped (resolution is in chain order,
|
|
92
|
+
* a route's orphan layouts and slots after its handler): every handler it
|
|
93
|
+
* reaches from here on is skipped too, and sends a placeholder with what
|
|
94
|
+
* the entry declares. The browser builds the page's tree once, from those
|
|
95
|
+
* (browser/partial-update.ts armHoles), so they have to list every segment
|
|
96
|
+
* a navigation to the page lists.
|
|
97
|
+
*/
|
|
98
|
+
below?: true;
|
|
99
|
+
/**
|
|
100
|
+
* The loaders this prefetch deferred, by `$$id` (registerDeferredLoader).
|
|
101
|
+
* A deferred loader runs only if something reads it: a handler's or another
|
|
102
|
+
* loader's ctx.use() starts it through its registration
|
|
103
|
+
* (startDeferredLoader), and revalidation.ts deliverStartedLoaders delivers
|
|
104
|
+
* what was started by the end of resolution.
|
|
105
|
+
*/
|
|
106
|
+
deferredLoaders?: Map<string, DeferredLoader>;
|
|
107
|
+
}
|
|
108
|
+
/** A loader this prefetch deferred: PrefetchDeferral.deferredLoaders. */
|
|
109
|
+
export interface DeferredLoader {
|
|
110
|
+
/**
|
|
111
|
+
* The segment that registers it. Its run files its handle pushes there,
|
|
112
|
+
* where a navigation's run of it files them, not under the reader
|
|
113
|
+
* (loaderOwner).
|
|
114
|
+
*/
|
|
115
|
+
readonly owner: string;
|
|
116
|
+
/**
|
|
117
|
+
* Starts it as resolution would have: resolveLoaderData with its cache()
|
|
118
|
+
* binding, so the reader and the delivered segment share one value.
|
|
119
|
+
*/
|
|
120
|
+
readonly start: () => Promise<unknown>;
|
|
121
|
+
/** A reader started it. */
|
|
122
|
+
started?: true;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The deferral scope of a matched chain, memoized on its leaf entry (entries
|
|
126
|
+
* are per-isSSR manifest objects, replaced on HMR). EMPTY_SCOPE when nothing
|
|
127
|
+
* in the tree declares `prefetch: false`.
|
|
128
|
+
*/
|
|
129
|
+
export declare function resolveDeferralScope(entries: readonly EntryData[]): DeferralScope;
|
|
130
|
+
/**
|
|
131
|
+
* Which half of the feature a partial request is, if either (`fill` and
|
|
132
|
+
* `prefetch` are requestKind's answer). Both halves are GETs: a request of
|
|
133
|
+
* another method that carries either marker is a normal request. A prefetch
|
|
134
|
+
* defers only on a plain GET navigation: an action re-renders what it
|
|
135
|
+
* changed, an intercept resolves its loaders outside the shared funnel, and a
|
|
136
|
+
* shell capture is never a prefetch whatever the request that scheduled it
|
|
137
|
+
* sent. The four conditions overlap today (an action is a POST, a capture
|
|
138
|
+
* runs the full match): each one states its own reason.
|
|
139
|
+
*/
|
|
140
|
+
export declare function partialDeferralMode(request: {
|
|
141
|
+
fill: boolean;
|
|
142
|
+
prefetch: boolean;
|
|
143
|
+
method: string;
|
|
144
|
+
isAction: boolean;
|
|
145
|
+
isIntercept: boolean;
|
|
146
|
+
isShellCapture: boolean;
|
|
147
|
+
}): PrefetchDeferral["mode"];
|
|
148
|
+
/**
|
|
149
|
+
* The plan for one match, or undefined when the tree declares no flag and the
|
|
150
|
+
* request is not a fill (the common case: nothing to carry). `held` is the
|
|
151
|
+
* client's segment ids as the request listed them.
|
|
152
|
+
*/
|
|
153
|
+
export declare function planPrefetchDeferral(entries: readonly EntryData[], mode: PrefetchDeferral["mode"], matched: {
|
|
154
|
+
pr?: boolean;
|
|
155
|
+
od?: boolean;
|
|
156
|
+
}, cacheScope: CacheScope | null | undefined, held?: ReadonlySet<string>): PrefetchDeferral | undefined;
|
|
157
|
+
export declare function getPrefetchDeferral(ctx: HandlerContext<any, any> | undefined): PrefetchDeferral | undefined;
|
|
158
|
+
/** The request is a fill: a held segment is skipped without consulting anything. */
|
|
159
|
+
export declare function isFillRequest(ctx: HandlerContext<any, any>): boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Register a loader this prefetch deferred, with the segment that registers
|
|
162
|
+
* it and how to start it there (PrefetchDeferral.deferredLoaders). The first
|
|
163
|
+
* registration wins, as the loader's one run per request does.
|
|
164
|
+
*/
|
|
165
|
+
export declare function registerDeferredLoader(ctx: HandlerContext<any, any>, loaderId: string, owner: string, start: () => Promise<unknown>): void;
|
|
166
|
+
/**
|
|
167
|
+
* A reader asks for a loader this prefetch deferred and nothing has started:
|
|
168
|
+
* start it through its registration and return the run, or undefined when
|
|
169
|
+
* the read takes the ordinary path. Without this the reader ran the loader
|
|
170
|
+
* bare, without its cache() binding, and the segment delivered afterwards
|
|
171
|
+
* read the binding: two values on one page and an extra run on a HIT.
|
|
172
|
+
*
|
|
173
|
+
* A started cache() binding of the loader (`_loaderCacheOverrides`) is never
|
|
174
|
+
* redirected here: the read is that binding's own MISS execution, and
|
|
175
|
+
* starting the registration would hand the binding its own pending value.
|
|
176
|
+
*/
|
|
177
|
+
export declare function startDeferredLoader(ctx: HandlerContext<any, any>, loaderId: string): Promise<unknown> | undefined;
|
|
178
|
+
/**
|
|
179
|
+
* The segment a run of `loaderId` files its handle pushes under: the one
|
|
180
|
+
* that registers it when this prefetch deferred it, else the segment being
|
|
181
|
+
* resolved.
|
|
182
|
+
*/
|
|
183
|
+
export declare function loaderOwner(ctx: HandlerContext<any, any>, loaderId: string): string | undefined;
|
|
184
|
+
/**
|
|
185
|
+
* This prefetch defers `loaderEntry`, whose segment is `segmentId`: the client
|
|
186
|
+
* does not hold that segment, and the loader is flagged itself or sits behind
|
|
187
|
+
* the fallback of a flagged entry the client does not hold either. Under a
|
|
188
|
+
* flagged layout the client holds, a new route's loaders run.
|
|
189
|
+
*/
|
|
190
|
+
export declare function defersLoader(ctx: HandlerContext<any, any>, loaderEntry: LoaderEntry, segmentId: string): boolean;
|
|
191
|
+
/**
|
|
192
|
+
* This prefetch skips the handler of the entry whose segment is `segmentId`:
|
|
193
|
+
* a unit the client does not hold, or anything the client does not hold
|
|
194
|
+
* below one (belowDeferredUnit). A held segment that re-renders is rendered
|
|
195
|
+
* by the prefetch, as by a navigation.
|
|
196
|
+
*/
|
|
197
|
+
export declare function defersUnit(ctx: HandlerContext<any, any>, segmentId: string): boolean;
|
|
198
|
+
/**
|
|
199
|
+
* `segmentId` is new to the client and the walk is below a chain unit this
|
|
200
|
+
* prefetch skipped (PrefetchDeferral.below). Nothing of such a segment runs
|
|
201
|
+
* in the prefetch, a slot's revalidate() predicates included: on a new
|
|
202
|
+
* segment they cannot change the outcome, and what they would read from
|
|
203
|
+
* context was set by handlers that did not run.
|
|
204
|
+
*/
|
|
205
|
+
export declare function belowDeferredUnit(ctx: HandlerContext<any, any>, segmentId: string): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* A unit candidate that is not stored: a prefetch of this tree can skip a
|
|
208
|
+
* handler. Returns its entry (the first in chain order), for the
|
|
209
|
+
* ctx.rendered() guards (loader-resolution.ts).
|
|
210
|
+
*/
|
|
211
|
+
export declare function firstUnitCandidate(plan: PrefetchDeferral): EntryData | undefined;
|
|
212
|
+
/**
|
|
213
|
+
* This prefetch skips a layout above the route cache's boundary, and with it
|
|
214
|
+
* everything the record below holds: withCacheLookup and withCacheStore leave
|
|
215
|
+
* the record alone for it. Decided per request, from what the client holds:
|
|
216
|
+
* a prefetch of the same tree that holds the layout reads and writes the
|
|
217
|
+
* record like any other request.
|
|
218
|
+
*/
|
|
219
|
+
export declare function defersAboveRecord(ctx: HandlerContext<any, any>): boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Record the handler unit this prefetch skipped. A `chain` entry takes what
|
|
222
|
+
* the walk reaches after it (PrefetchDeferral.below); a slot is skipped
|
|
223
|
+
* alone.
|
|
224
|
+
*/
|
|
225
|
+
export declare function markUnitDeferred(ctx: HandlerContext<any, any>, segmentId: string, chain?: boolean): void;
|
|
226
|
+
/**
|
|
227
|
+
* Whether this prefetch skips the handler of the unit whose segment is
|
|
228
|
+
* `segmentId`, recorded: the flag the segment carries
|
|
229
|
+
* (ResolvedSegment.deferred), or undefined when the handler runs.
|
|
230
|
+
* - `chain`: a chain entry, its own unit or below one (defersUnit). The walk
|
|
231
|
+
* takes what it reaches after it (markUnitDeferred).
|
|
232
|
+
* - `slot`: a slot that is its own unit, skipped alone.
|
|
233
|
+
* - `below`: what the walk reaches below a chain unit it skipped
|
|
234
|
+
* (belowDeferredUnit): a slot, before its predicates run, and an orphan
|
|
235
|
+
* layout, which is never a unit of its own (resolveDeferralScope). The unit
|
|
236
|
+
* above is recorded already.
|
|
237
|
+
*/
|
|
238
|
+
export declare function deferUnit(ctx: HandlerContext<any, any>, segmentId: string, kind: "chain" | "slot" | "below"): {
|
|
239
|
+
readonly deferred: true;
|
|
240
|
+
} | undefined;
|
|
241
|
+
export {};
|
|
@@ -84,6 +84,13 @@ export type EntryPropDatas = {
|
|
|
84
84
|
*/
|
|
85
85
|
export type EntryPropRender = {
|
|
86
86
|
loading?: ReactNode | false;
|
|
87
|
+
/**
|
|
88
|
+
* loading(fallback, { prefetch: false }) with a renderable fallback: a
|
|
89
|
+
* prefetch defers what the fallback covers while the entry's segment is
|
|
90
|
+
* new to the client (router/segment-resolution/prefetch-deferral.ts). Set
|
|
91
|
+
* on both DSL evaluations, whatever `ssr` did to `loading`.
|
|
92
|
+
*/
|
|
93
|
+
loadingPrefetch?: false;
|
|
87
94
|
transition?: TransitionConfig;
|
|
88
95
|
};
|
|
89
96
|
/**
|
|
@@ -116,6 +123,12 @@ export type LoaderEntry = {
|
|
|
116
123
|
* navigation evaluation never has it.
|
|
117
124
|
*/
|
|
118
125
|
bake?: true;
|
|
126
|
+
/**
|
|
127
|
+
* loader(Def, { prefetch: false }): a prefetch defers this registration
|
|
128
|
+
* while its segment is new to the client
|
|
129
|
+
* (router/segment-resolution/prefetch-deferral.ts).
|
|
130
|
+
*/
|
|
131
|
+
prefetch?: false;
|
|
119
132
|
};
|
|
120
133
|
/**
|
|
121
134
|
* Segments state for intercept context
|
|
@@ -668,7 +681,14 @@ export declare function assertCachedHeaderWriteAllowed(surface: string, surfaceP
|
|
|
668
681
|
* are bypassed because loaders are always fresh (never cached) and
|
|
669
682
|
* their side effects (setCookie, header, etc.) are safe.
|
|
670
683
|
*/
|
|
671
|
-
export declare function runInsideLoaderScope<T>(fn: () => T): T;
|
|
684
|
+
export declare function runInsideLoaderScope<T>(fn: () => T, loaderId?: string): T;
|
|
685
|
+
/**
|
|
686
|
+
* The loader whose run a handle push here belongs to, for the browser's
|
|
687
|
+
* merge of a partial response (handles/pushed-by.ts): the DSL loader
|
|
688
|
+
* this scope resolves, else the outermost loader body around the push (a
|
|
689
|
+
* loader a handler reads with ctx.use). Undefined for a handler's own push.
|
|
690
|
+
*/
|
|
691
|
+
export declare function getHandlePushOwner(): string | undefined;
|
|
672
692
|
/**
|
|
673
693
|
* Run `fn` inside a loader BODY scope. Marks loader-function execution for the
|
|
674
694
|
* cache() purity guard only (isInsideCacheScope), WITHOUT affecting
|
|
@@ -186,7 +186,8 @@ export interface HandleStore {
|
|
|
186
186
|
* nav/action payloads, whose consumer applies each yield progressively) or
|
|
187
187
|
* "settled" (the document lane, whose consumers drain to completion in
|
|
188
188
|
* blocking positions and must not wait on loader bodies).
|
|
189
|
-
* Each yield contains the full accumulated state (not just the delta)
|
|
189
|
+
* Each yield contains the full accumulated state (not just the delta),
|
|
190
|
+
* with the pushedBy records of its buckets (handles/pushed-by.ts).
|
|
190
191
|
* Safe for concurrent consumers (per-consumer version cursor).
|
|
191
192
|
* The "settled" lane of a frozen store (freezeDocumentSnapshot) yields the
|
|
192
193
|
* frozen state once, at once, and ends. That yield is the store's own
|
|
@@ -212,6 +213,13 @@ export interface HandleStore {
|
|
|
212
213
|
* time (see push); see captureHandles.
|
|
213
214
|
*/
|
|
214
215
|
getDataForSegment(segmentId: string, excludeLoaderPushes?: boolean): Record<string, unknown[]>;
|
|
216
|
+
/**
|
|
217
|
+
* The loader whose run pushed each value in getDataForSegment(segmentId,
|
|
218
|
+
* excludeLoaderPushes), index-aligned per handle (null: the handler's).
|
|
219
|
+
* Handles without such a value are omitted; undefined when none has one.
|
|
220
|
+
* The browser's pushedBy record (handles/pushed-by.ts).
|
|
221
|
+
*/
|
|
222
|
+
getPushedBy(segmentId: string, excludeLoaderPushes?: boolean): Record<string, (string | null)[]> | undefined;
|
|
215
223
|
/**
|
|
216
224
|
* The push `owner` of each value in getDataForSegment(segmentId, true),
|
|
217
225
|
* index-aligned per handle (null: no owner). Handles without an owned
|