@rangojs/router 0.5.2 → 0.7.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 +343 -125
- package/dist/types/browser/react/use-router.d.ts +10 -3
- package/dist/types/browser/react/use-search-params.d.ts +57 -10
- package/dist/types/browser/types.d.ts +22 -0
- package/dist/types/build/merge-full-manifests.d.ts +3 -0
- package/dist/types/build/route-trie.d.ts +4 -73
- package/dist/types/build/route-types/per-module-writer.d.ts +6 -4
- package/dist/types/build/route-types/router-processing.d.ts +2 -3
- package/dist/types/cache/cache-exec-scope.d.ts +31 -0
- package/dist/types/cache/taint.d.ts +12 -6
- package/dist/types/client-urls/client-root.d.ts +38 -0
- package/dist/types/client-urls/client-urls.d.ts +5 -0
- package/dist/types/client-urls/navigation.d.ts +38 -0
- package/dist/types/client-urls/revalidation-protocol.d.ts +25 -0
- package/dist/types/client-urls/server-projection.d.ts +71 -0
- package/dist/types/client-urls/types.d.ts +147 -0
- package/dist/types/client.d.ts +12 -4
- package/dist/types/client.rsc.d.ts +4 -1
- package/dist/types/decode-loader-results.d.ts +37 -0
- package/dist/types/errors.d.ts +1 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/loader-redirect.d.ts +27 -0
- package/dist/types/outlet-context.d.ts +12 -0
- package/dist/types/outlet-provider.d.ts +3 -1
- package/dist/types/redirect-origin.d.ts +4 -0
- package/dist/types/route-content-wrapper.d.ts +42 -1
- package/dist/types/route-definition/helpers-types.d.ts +13 -2
- package/dist/types/router/error-handling.d.ts +35 -1
- package/dist/types/router/intercept-resolution.d.ts +12 -0
- package/dist/types/router/loader-resolution.d.ts +24 -2
- package/dist/types/router/revalidation.d.ts +7 -0
- package/dist/types/router/route-trie-builder.d.ts +77 -0
- package/dist/types/router/router-interfaces.d.ts +20 -0
- package/dist/types/router/segment-resolution/helpers.d.ts +1 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +9 -9
- package/dist/types/router/trie-matching.d.ts +1 -1
- package/dist/types/rsc/manifest-init.d.ts +5 -5
- package/dist/types/rsc/shell-capture.d.ts +9 -0
- package/dist/types/rsc/shell-serve.d.ts +11 -0
- package/dist/types/rsc/types.d.ts +30 -0
- package/dist/types/segment-system.d.ts +2 -0
- package/dist/types/server/context.d.ts +10 -0
- package/dist/types/server/handle-store.d.ts +34 -3
- package/dist/types/server/request-context.d.ts +11 -1
- package/dist/types/server.d.ts +1 -0
- package/dist/types/ssr/index.d.ts +22 -0
- package/dist/types/ssr/ssr-root.d.ts +10 -0
- package/dist/types/testing/dom.entry.d.ts +1 -1
- package/dist/types/testing/render-route.d.ts +16 -6
- package/dist/types/testing/run-loader.d.ts +9 -0
- package/dist/types/types/boundaries.d.ts +22 -0
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/loader-types.d.ts +57 -5
- package/dist/types/types/segments.d.ts +7 -0
- package/dist/types/urls/path-helper-types.d.ts +13 -4
- package/dist/types/vite/discovery/client-urls-projection.d.ts +53 -0
- package/dist/types/vite/discovery/discover-routers.d.ts +1 -1
- package/dist/types/vite/discovery/state.d.ts +8 -1
- package/dist/types/vite/plugins/client-ref-dedup.d.ts +0 -11
- package/dist/vite/index.js +6159 -2959
- package/package.json +6 -5
- package/skills/breadcrumbs/SKILL.md +39 -9
- package/skills/catalog.json +7 -1
- package/skills/client-urls/SKILL.md +338 -0
- package/skills/comparison/references/framework-comparison.md +23 -9
- package/skills/hooks/SKILL.md +2 -2
- package/skills/hooks/data.md +11 -2
- package/skills/hooks/handle-and-actions.md +7 -0
- package/skills/hooks/outlets.md +26 -5
- package/skills/hooks/urls.md +40 -3
- package/skills/loader/SKILL.md +132 -20
- package/skills/migrate-nextjs/SKILL.md +70 -10
- package/skills/migrate-react-router/SKILL.md +49 -13
- package/skills/migrate-react-router/component-migration.md +18 -13
- package/skills/migrate-react-router/data-and-actions.md +14 -3
- package/skills/migrate-react-router/route-mapping.md +15 -2
- package/skills/parallel/SKILL.md +32 -1
- package/skills/ppr/SKILL.md +16 -6
- package/skills/prerender/SKILL.md +8 -4
- package/skills/rango/SKILL.md +21 -17
- package/skills/react-compiler/SKILL.md +3 -3
- package/skills/route/SKILL.md +5 -2
- package/skills/router-setup/SKILL.md +16 -2
- package/skills/scripts/SKILL.md +16 -6
- package/skills/shell-manifest/SKILL.md +16 -7
- package/skills/testing/SKILL.md +2 -2
- package/skills/testing/client-components.md +6 -0
- package/skills/testing/handles.md +30 -8
- package/skills/testing/loader.md +51 -49
- package/skills/testing/middleware.md +1 -1
- package/skills/theme/SKILL.md +8 -5
- package/src/bin/rango.ts +7 -3
- package/src/browser/navigation-bridge.ts +6 -0
- package/src/browser/navigation-client.ts +5 -0
- package/src/browser/partial-update.ts +65 -13
- package/src/browser/react/use-router.ts +40 -11
- package/src/browser/react/use-search-params.ts +140 -17
- package/src/browser/rsc-router.tsx +59 -0
- package/src/browser/server-action-bridge.ts +26 -0
- package/src/browser/types.ts +22 -0
- package/src/build/merge-full-manifests.ts +161 -0
- package/src/build/route-trie.ts +9 -332
- package/src/build/route-types/include-resolution.ts +66 -11
- package/src/build/route-types/per-module-writer.ts +11 -6
- package/src/build/route-types/router-processing.ts +184 -153
- package/src/build/runtime-discovery.ts +23 -12
- package/src/cache/cache-exec-scope.ts +47 -0
- package/src/cache/cache-runtime.ts +24 -25
- package/src/cache/taint.ts +28 -9
- package/src/client-urls/client-root.tsx +168 -0
- package/src/client-urls/client-urls.ts +776 -0
- package/src/client-urls/navigation.ts +237 -0
- package/src/client-urls/revalidation-protocol.ts +56 -0
- package/src/client-urls/server-projection.ts +670 -0
- package/src/client-urls/types.ts +201 -0
- package/src/client.rsc.tsx +12 -0
- package/src/client.tsx +49 -6
- package/src/decode-loader-results.ts +113 -0
- package/src/errors.ts +14 -0
- package/src/handles/deferred-resolution.ts +14 -7
- package/src/index.ts +1 -0
- package/src/loader-redirect.tsx +64 -0
- package/src/outlet-context.ts +12 -0
- package/src/outlet-provider.tsx +15 -1
- package/src/redirect-origin.ts +29 -0
- package/src/route-content-wrapper.tsx +96 -3
- package/src/route-definition/dsl-helpers.ts +28 -3
- package/src/route-definition/helpers-types.ts +13 -0
- package/src/route-definition/redirect.ts +17 -18
- package/src/router/error-handling.ts +65 -11
- package/src/router/intercept-resolution.ts +29 -0
- package/src/router/loader-resolution.ts +261 -28
- package/src/router/match-result.ts +7 -0
- package/src/router/revalidation.ts +24 -11
- package/src/router/route-trie-builder.ts +334 -0
- package/src/router/router-interfaces.ts +38 -0
- package/src/router/segment-resolution/fresh.ts +55 -2
- package/src/router/segment-resolution/helpers.ts +9 -11
- package/src/router/segment-resolution/loader-cache.ts +34 -23
- package/src/router/segment-resolution/loader-mask.ts +9 -9
- package/src/router/segment-resolution/revalidation.ts +23 -2
- package/src/router/trie-matching.ts +3 -3
- package/src/router.ts +46 -1
- package/src/rsc/full-payload.ts +6 -0
- package/src/rsc/handler.ts +10 -7
- package/src/rsc/loader-fetch.ts +2 -2
- package/src/rsc/manifest-init.ts +28 -9
- package/src/rsc/rsc-rendering.ts +15 -1
- package/src/rsc/shell-capture.ts +12 -0
- package/src/rsc/shell-serve.ts +15 -2
- package/src/rsc/ssr-setup.ts +10 -1
- package/src/rsc/types.ts +31 -2
- package/src/segment-system.tsx +83 -26
- package/src/server/context.ts +10 -0
- package/src/server/cookie-store.ts +19 -19
- package/src/server/handle-store.ts +185 -48
- package/src/server/request-context.ts +30 -6
- package/src/server.ts +7 -0
- package/src/ssr/index.tsx +37 -2
- package/src/ssr/ssr-root.tsx +29 -2
- package/src/testing/dom.entry.ts +1 -1
- package/src/testing/render-route.tsx +22 -8
- package/src/testing/run-loader.ts +51 -13
- package/src/types/boundaries.ts +19 -0
- package/src/types/index.ts +1 -0
- package/src/types/loader-types.ts +60 -5
- package/src/types/segments.ts +7 -0
- package/src/urls/include-helper.ts +22 -4
- package/src/urls/path-helper-types.ts +17 -1
- package/src/use-loader.tsx +67 -6
- package/src/vite/discovery/client-urls-projection.ts +322 -0
- package/src/vite/discovery/discover-routers.ts +43 -17
- package/src/vite/discovery/state.ts +11 -1
- package/src/vite/discovery/virtual-module-codegen.ts +20 -0
- package/src/vite/plugins/client-ref-dedup.ts +281 -19
- package/src/vite/plugins/expose-action-id.ts +45 -23
- package/src/vite/plugins/virtual-entries.ts +12 -3
- package/src/vite/router-discovery.ts +163 -12
|
@@ -1,19 +1,66 @@
|
|
|
1
1
|
import type { ReadonlyURLSearchParams } from "../types.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Accepted shapes for the setter: a full replacement for the search string.
|
|
4
|
+
* Record values are stringified; array values append one entry per element;
|
|
5
|
+
* null/undefined values are skipped (ergonomic conditional spreads).
|
|
6
|
+
*/
|
|
7
|
+
export type SearchParamsInit = string | URLSearchParams | ReadonlyURLSearchParams | Record<string, string | number | boolean | readonly (string | number | boolean)[] | null | undefined>;
|
|
8
|
+
export interface SetSearchParamsOptions {
|
|
9
|
+
/** Replace the current history entry instead of pushing (default false). */
|
|
10
|
+
replace?: boolean;
|
|
11
|
+
/** Scroll behavior for the navigation (default: router default, scroll). */
|
|
12
|
+
scroll?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Set false to skip the server fetch and only update the URL (default
|
|
15
|
+
* true). Purely client-derived search state (open accordions, view modes)
|
|
16
|
+
* needs no loader re-run; all location-aware hooks still update. Same
|
|
17
|
+
* contract as NavigateOptions.revalidate — it only applies because the
|
|
18
|
+
* setter never changes the pathname.
|
|
19
|
+
*/
|
|
20
|
+
revalidate?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export type SetSearchParams = (init: SearchParamsInit | ((prev: URLSearchParams) => SearchParamsInit), options?: SetSearchParamsOptions) => Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Hook to read and write the current URL search params
|
|
25
|
+
* (React Router-style tuple).
|
|
4
26
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
27
|
+
* The first element is a read-only URLSearchParams from the COMMITTED
|
|
28
|
+
* location — it updates when navigation completes, not during a pending
|
|
29
|
+
* navigation. During document SSR it carries the LIVE request's search (the
|
|
30
|
+
* SSR store is seeded from SSRRenderOptions.search), and the browser's
|
|
31
|
+
* first render seeds from its own store location (window.location) — the
|
|
32
|
+
* same URL, so hydration matches. Ppr capture/resume renders seed the SHELL
|
|
33
|
+
* KEY's search (sorted, cache.searchParams filter applied — search is part
|
|
34
|
+
* of shell identity like every other ppr key), so static-part reads bake
|
|
35
|
+
* markup consistent with the shell's own key. Two edges: a param EXCLUDED
|
|
36
|
+
* by cache.searchParams is absent in shell renders but present in the
|
|
37
|
+
* browser (exclusion declares "does not affect markup" — reading one
|
|
38
|
+
* anyway hydration-mismatches), and toString() renders sorted order while
|
|
39
|
+
* the browser holds the raw URL order.
|
|
7
40
|
*
|
|
8
|
-
*
|
|
9
|
-
* the pathname
|
|
10
|
-
*
|
|
41
|
+
* The setter REPLACES the whole search string (React Router semantics) and
|
|
42
|
+
* navigates to the current pathname with the new params — a same-route
|
|
43
|
+
* navigation, so route loaders re-evaluate per their revalidate() contract
|
|
44
|
+
* and the commit holds previous content (the same-structure transition
|
|
45
|
+
* lane). Pass a function to merge with the current params: it receives a
|
|
46
|
+
* MUTABLE copy read at call time. The hash is dropped, like React Router.
|
|
11
47
|
*
|
|
12
48
|
* @example
|
|
13
49
|
* ```tsx
|
|
14
|
-
* const searchParams = useSearchParams();
|
|
15
|
-
* const
|
|
16
|
-
*
|
|
50
|
+
* const [searchParams, setSearchParams] = useSearchParams();
|
|
51
|
+
* const category = searchParams.get("category");
|
|
52
|
+
*
|
|
53
|
+
* // Replace the whole search string
|
|
54
|
+
* setSearchParams({ category: "electronics" });
|
|
55
|
+
*
|
|
56
|
+
* // Merge with what's there now
|
|
57
|
+
* setSearchParams((prev) => {
|
|
58
|
+
* prev.set("page", "2");
|
|
59
|
+
* return prev;
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // Filter UIs usually want replace + preserved scroll
|
|
63
|
+
* setSearchParams({ category: "home" }, { replace: true, scroll: false });
|
|
17
64
|
* ```
|
|
18
65
|
*/
|
|
19
|
-
export declare function useSearchParams(): ReadonlyURLSearchParams;
|
|
66
|
+
export declare function useSearchParams(): [ReadonlyURLSearchParams, SetSearchParams];
|
|
@@ -47,12 +47,27 @@ export interface RscMetadata {
|
|
|
47
47
|
* Slots are used for intercepting routes during soft navigation
|
|
48
48
|
*/
|
|
49
49
|
slots?: Record<string, SlotState>;
|
|
50
|
+
/**
|
|
51
|
+
* Intercept TARGET route names reachable from this location as a
|
|
52
|
+
* navigation origin. The browser-local clientUrls matcher declines its
|
|
53
|
+
* optimistic presentation for these targets (the canonical response would
|
|
54
|
+
* commit the intercept over the ORIGIN page, so destination loading would
|
|
55
|
+
* flash and revert). Missing/empty means no targets.
|
|
56
|
+
*/
|
|
57
|
+
interceptTargets?: string[];
|
|
50
58
|
/** Root layout component for browser-side re-renders */
|
|
51
59
|
rootLayout?: ComponentType<{
|
|
52
60
|
children: ReactNode;
|
|
53
61
|
}>;
|
|
54
62
|
/** Handle data accumulated across route segments (async generator that yields on each push) */
|
|
55
63
|
handles?: AsyncGenerator<HandleData, void, unknown>;
|
|
64
|
+
/**
|
|
65
|
+
* Document-lane late handle channel: pushes landing after the handler
|
|
66
|
+
* barrier (streaming loader ctx.use(Handle) writes). Consumed non-blocking
|
|
67
|
+
* post-hydration (rsc-router.tsx); `handles` above is drained in blocking
|
|
68
|
+
* positions and must complete at the handler barrier.
|
|
69
|
+
*/
|
|
70
|
+
handlesLate?: AsyncGenerator<HandleData, void, unknown>;
|
|
56
71
|
/** Cached handle data (for back/forward navigation from cache) */
|
|
57
72
|
cachedHandleData?: HandleData;
|
|
58
73
|
/**
|
|
@@ -438,6 +453,13 @@ export interface FetchPartialOptions {
|
|
|
438
453
|
signal?: AbortSignal;
|
|
439
454
|
/** If true, this is a stale cache revalidation request - server should force revalidators */
|
|
440
455
|
staleRevalidation?: boolean;
|
|
456
|
+
/**
|
|
457
|
+
* Encoded client-run per-loader revalidation decisions
|
|
458
|
+
* (clientUrls revalidate() predicates executed in the browser); sent as
|
|
459
|
+
* X-Rango-Client-Reval and honored only by materialized client-urls loader
|
|
460
|
+
* stubs. Null/absent = locked server defaults.
|
|
461
|
+
*/
|
|
462
|
+
clientRevalidation?: string | null;
|
|
441
463
|
interceptSourceUrl?: string;
|
|
442
464
|
/** RSC version for cache invalidation detection */
|
|
443
465
|
version?: string;
|
|
@@ -1,81 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Build-time Route Trie Construction
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* route matching at runtime.
|
|
4
|
+
* Adapts generated manifests to the runtime-owned route trie builder.
|
|
6
5
|
*/
|
|
6
|
+
import { buildRouteTrie, type TrieNode } from "../router/route-trie-builder.js";
|
|
7
7
|
import type { FullManifest } from "./generate-manifest.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* the variant's own positional param-name array, carried so the runtime can
|
|
11
|
-
* re-key the matched params under the variant's names when it wins negotiation
|
|
12
|
-
* (the trie match extracts params under the PRIMARY leaf's pa). Omitted when the
|
|
13
|
-
* variant has no params; absent/identical pa means no re-key is needed.
|
|
14
|
-
*/
|
|
15
|
-
export interface NegotiateVariant {
|
|
16
|
-
routeKey: string;
|
|
17
|
-
responseType: string;
|
|
18
|
-
pa?: string[];
|
|
19
|
-
}
|
|
20
|
-
export interface TrieLeaf {
|
|
21
|
-
/** Route name (e.g., "site.l1_500") */
|
|
22
|
-
n: string;
|
|
23
|
-
/** Static prefix of the entry (e.g., "/site") */
|
|
24
|
-
sp: string;
|
|
25
|
-
/** Constraint validation: paramName -> allowed values */
|
|
26
|
-
cv?: Record<string, string[]>;
|
|
27
|
-
/** Ordered param names for this route (positional) */
|
|
28
|
-
pa?: string[];
|
|
29
|
-
/** Trailing slash mode */
|
|
30
|
-
ts?: string;
|
|
31
|
-
/** Route has pre-rendered data available */
|
|
32
|
-
pr?: true;
|
|
33
|
-
/** Passthrough: handler kept in bundle for live fallback on unknown params */
|
|
34
|
-
pt?: true;
|
|
35
|
-
/** Response type for non-RSC routes (json, text, image, any) */
|
|
36
|
-
rt?: string;
|
|
37
|
-
/** Negotiate variants: response-type routes sharing this path */
|
|
38
|
-
nv?: NegotiateVariant[];
|
|
39
|
-
/** RSC-first: RSC route was defined before response-type variants */
|
|
40
|
-
rf?: true;
|
|
41
|
-
}
|
|
42
|
-
export interface TrieNode {
|
|
43
|
-
/** Route terminal at this node */
|
|
44
|
-
r?: TrieLeaf;
|
|
45
|
-
/** Static segment children */
|
|
46
|
-
s?: Record<string, TrieNode>;
|
|
47
|
-
/** Param child: { n: paramName, c: child node } */
|
|
48
|
-
p?: {
|
|
49
|
-
n: string;
|
|
50
|
-
c: TrieNode;
|
|
51
|
-
};
|
|
52
|
-
/** Suffix-param children keyed by suffix (e.g., ".html" → { n: "productId", c: ... }) */
|
|
53
|
-
xp?: Record<string, {
|
|
54
|
-
n: string;
|
|
55
|
-
c: TrieNode;
|
|
56
|
-
}>;
|
|
57
|
-
/**
|
|
58
|
-
* Wildcard terminal: leaf + paramName (`pn`). `pn` is "*" for the bare `/*`
|
|
59
|
-
* form and the param name for a named catch-all (`:name+`/`:name*`). `w1`
|
|
60
|
-
* marks a one-or-more catch-all (`:name+`): the runtime walker then rejects
|
|
61
|
-
* the zero-segment/empty-remainder case. Absent `w1` is zero-or-more.
|
|
62
|
-
*/
|
|
63
|
-
w?: TrieLeaf & {
|
|
64
|
-
pn: string;
|
|
65
|
-
w1?: true;
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Build a route trie from build-time manifest data.
|
|
70
|
-
*
|
|
71
|
-
* @param routeManifest - Map of route name to full URL pattern
|
|
72
|
-
* @param routeToStaticPrefix - Map of route name to its entry's staticPrefix
|
|
73
|
-
* @param routeTrailingSlash - Optional map of route name to trailing slash mode
|
|
74
|
-
* @param prerenderRouteNames - Optional set of prerendered route names (sets leaf.pr)
|
|
75
|
-
* @param passthroughRouteNames - Optional set of passthrough route names (sets leaf.pt)
|
|
76
|
-
* @param responseTypeRoutes - Optional map of route name to response type (sets leaf.rt)
|
|
77
|
-
*/
|
|
78
|
-
export declare function buildRouteTrie(routeManifest: Record<string, string>, routeToStaticPrefix: Record<string, string>, routeTrailingSlash?: Record<string, string>, prerenderRouteNames?: Set<string>, passthroughRouteNames?: Set<string>, responseTypeRoutes?: Record<string, string>): TrieNode;
|
|
8
|
+
export { buildRouteTrie };
|
|
9
|
+
export type { NegotiateVariant, TrieLeaf, TrieNode, } from "../router/route-trie-builder.js";
|
|
79
10
|
/**
|
|
80
11
|
* Build a per-router trie from a generated manifest. This is the single
|
|
81
12
|
* construction path shared by build/discovery (discover-routers.ts, serialized
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import type { ScanFilter } from "./scan-filter.js";
|
|
2
2
|
/**
|
|
3
3
|
* Generate per-module route type files by statically parsing url module source.
|
|
4
|
-
* Scans for files containing `urls(` and writes a sibling
|
|
5
|
-
* extracted route name/pattern pairs. Only writes when
|
|
4
|
+
* Scans for files containing `urls(` or `clientUrls(` and writes a sibling
|
|
5
|
+
* `.gen.ts` with the extracted route name/pattern pairs. Only writes when
|
|
6
|
+
* content has changed.
|
|
6
7
|
*/
|
|
7
8
|
export declare function writePerModuleRouteTypes(root: string, filter?: ScanFilter): void;
|
|
8
9
|
/**
|
|
9
|
-
* Find all variable names assigned to urls() calls in source
|
|
10
|
+
* Find all variable names assigned to urls() or clientUrls() calls in source.
|
|
10
11
|
* e.g. `export const patterns = urls(...)` -> ["patterns"]
|
|
11
12
|
*/
|
|
12
13
|
export declare function findUrlsVariableNames(code: string): string[];
|
|
13
14
|
/**
|
|
14
15
|
* Generate per-module route types for a single url module file.
|
|
15
16
|
* Follows include() calls recursively to produce the full route tree.
|
|
16
|
-
* No-ops if the file doesn't contain `urls(` or has no named
|
|
17
|
+
* No-ops if the file doesn't contain `urls(`/`clientUrls(` or has no named
|
|
18
|
+
* routes.
|
|
17
19
|
*/
|
|
18
20
|
export declare function writePerModuleRouteTypesForFile(filePath: string): void;
|
|
@@ -38,9 +38,8 @@ export declare function extractBasenameFromRouter(code: string): string | undefi
|
|
|
38
38
|
export declare function genFileTsPath(sourceFile: string): string;
|
|
39
39
|
export declare function resolveSearchSchemas(publicRouteNames: string[], runtimeSchemas: Record<string, Record<string, string>> | undefined, sourceFile: string): Record<string, Record<string, string>> | undefined;
|
|
40
40
|
/**
|
|
41
|
-
* Resolve routes and search schemas from
|
|
42
|
-
*
|
|
43
|
-
* or by parsing an inline builder function directly.
|
|
41
|
+
* Resolve routes and search schemas from every direct mount in a createRouter
|
|
42
|
+
* chain. Registrations are merged in runtime order, with later mounts winning.
|
|
44
43
|
*/
|
|
45
44
|
export declare function buildCombinedRouteMapForRouterFile(routerFilePath: string): {
|
|
46
45
|
routes: Record<string, string>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution-chain scope for "use cache" function bodies.
|
|
3
|
+
*
|
|
4
|
+
* The ambient guards (cookies(), headers(), ctx.set() reached via
|
|
5
|
+
* getRequestContext()) must fire for code running INSIDE a cached body and
|
|
6
|
+
* stay silent for everything else on the request. A property stamped on the
|
|
7
|
+
* shared RequestContext cannot express that: while a slow "use cache" body is
|
|
8
|
+
* in flight, every parallel read on the same request sees the stamp. Scar: a
|
|
9
|
+
* 2s cached product fetch running beside a sibling loader made the loader's
|
|
10
|
+
* cookies() read throw `cannot be called inside a "use cache" function` —
|
|
11
|
+
* same shared-object hazard as issue #684 plan 010, which fixed only the
|
|
12
|
+
* background-revalidation path. AsyncLocalStorage follows the cached body's
|
|
13
|
+
* own async chain, so parallel work is invisible to the guard while genuine
|
|
14
|
+
* in-body reads still throw.
|
|
15
|
+
*
|
|
16
|
+
* Deliberately NOT entered on the store-less bypass paths in cache-runtime.ts:
|
|
17
|
+
* there the body executes for real on every call, side effects take effect,
|
|
18
|
+
* and request-scoped reads are safe (see the bypass comments there).
|
|
19
|
+
*
|
|
20
|
+
* Kept separate from taint.ts so `node:async_hooks` stays out of that module —
|
|
21
|
+
* taint.ts is reachable from browser-bundled DSL helpers. The probe
|
|
22
|
+
* registration below wires assertNotInsideCacheExec to this scope without
|
|
23
|
+
* taint.ts importing it.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Run fn with the "use cache" execution scope active. Continuations spawned
|
|
27
|
+
* from fn's synchronous kickoff inherit the scope; parallel chains do not.
|
|
28
|
+
*/
|
|
29
|
+
export declare function runWithCacheExecScope<T>(fn: () => T): T;
|
|
30
|
+
/** True when the calling async chain is inside a "use cache" body. */
|
|
31
|
+
export declare function isInsideCacheExecScope(): boolean;
|
|
@@ -11,14 +11,19 @@ export declare const NOCACHE_SYMBOL: unique symbol;
|
|
|
11
11
|
*/
|
|
12
12
|
export declare function isTainted(value: unknown): boolean;
|
|
13
13
|
/**
|
|
14
|
-
* Symbol stamped on tainted ctx
|
|
15
|
-
*
|
|
16
|
-
* throw if present —
|
|
17
|
-
*
|
|
14
|
+
* Symbol stamped on tainted ctx objects PASSED AS ARGUMENTS to a "use cache"
|
|
15
|
+
* function during its execution. ctx.set(), ctx.header(), etc. check this
|
|
16
|
+
* flag and throw if present — those side effects are lost on cache hit.
|
|
17
|
+
*
|
|
18
|
+
* Argument objects only. Ambient access (cookies()/headers() and ctx methods
|
|
19
|
+
* reached via getRequestContext()) is guarded by the AsyncLocalStorage scope
|
|
20
|
+
* in cache-exec-scope.ts instead: stamping the SHARED RequestContext made
|
|
21
|
+
* every parallel read on the request throw for the cached body's whole
|
|
22
|
+
* execution window (a 2s cached fetch poisoned a sibling loader's cookies()).
|
|
18
23
|
*
|
|
19
24
|
* The value is a numeric reference count, not a boolean. Multiple concurrent
|
|
20
|
-
* cached functions sharing the same ctx
|
|
21
|
-
*
|
|
25
|
+
* cached functions sharing the same ctx each increment on entry and decrement
|
|
26
|
+
* on exit. Guards fire when count > 0.
|
|
22
27
|
*/
|
|
23
28
|
export declare const INSIDE_CACHE_EXEC: unique symbol;
|
|
24
29
|
/**
|
|
@@ -31,6 +36,7 @@ export declare function stampCacheExec(obj: object): void;
|
|
|
31
36
|
* used by guards no longer fires.
|
|
32
37
|
*/
|
|
33
38
|
export declare function unstampCacheExec(obj: object): void;
|
|
39
|
+
export declare function _setCacheExecScopeProbe(probe: () => boolean): void;
|
|
34
40
|
/**
|
|
35
41
|
* Throw if ctx is inside a "use cache" execution.
|
|
36
42
|
* Call from side-effecting ctx methods (set, header, etc.) and cookie mutations.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { ClientUrlPatterns } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Server-materialized wrapper layout for a clientUrls() group that declares
|
|
5
|
+
* intercepts. Attachment scar: intercepts emitted at the TOP LEVEL of a lazily
|
|
6
|
+
* included module attach to the isolated parent clone
|
|
7
|
+
* (getIsolatedLazyParent in server/context.ts) and are silently discarded —
|
|
8
|
+
* only intercepts attached to a layout entry created WITHIN the expansion
|
|
9
|
+
* survive in origin chains. Materialization therefore wraps the group's routes
|
|
10
|
+
* and intercept entries in this layout; it renders the child outlet plus one
|
|
11
|
+
* named outlet per declared slot, so the modal presents inside the group's own
|
|
12
|
+
* subtree (module-local declaration, module-local presentation).
|
|
13
|
+
*/
|
|
14
|
+
export declare function ClientUrlsGroupLayout({ slotNames, }: {
|
|
15
|
+
slotNames: readonly `@${string}`[];
|
|
16
|
+
}): ReactNode;
|
|
17
|
+
/** Slot content for a client-declared intercept: renders the definition's
|
|
18
|
+
* modal component; its useLoader() calls read the slot segment's loader data
|
|
19
|
+
* from the surrounding outlet context. */
|
|
20
|
+
export declare function ClientUrlsInterceptSlot({ definition, interceptIndex, }: {
|
|
21
|
+
definition: ClientUrlPatterns;
|
|
22
|
+
interceptIndex: number;
|
|
23
|
+
}): ReactNode;
|
|
24
|
+
export declare function ClientUrlsInterceptLoading({ definition, interceptIndex, }: {
|
|
25
|
+
definition: ClientUrlPatterns;
|
|
26
|
+
interceptIndex: number;
|
|
27
|
+
}): ReactNode;
|
|
28
|
+
export declare function ClientUrlsRoot({ definition, routeId, namePrefix, }: {
|
|
29
|
+
definition: ClientUrlPatterns;
|
|
30
|
+
routeId: string;
|
|
31
|
+
/** include() route-name prefix, injected at materialization for canonical
|
|
32
|
+
* name composition (intercept-target coordination). */
|
|
33
|
+
namePrefix?: string;
|
|
34
|
+
}): ReactNode;
|
|
35
|
+
export declare function ClientUrlsLoading({ definition, routeId, }: {
|
|
36
|
+
definition: ClientUrlPatterns;
|
|
37
|
+
routeId: string;
|
|
38
|
+
}): ReactNode;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ClientUrlBuilder, ClientUrlPatterns } from "./types.js";
|
|
2
|
+
import type { ExtractRoutes } from "../urls/type-extraction.js";
|
|
3
|
+
import type { ClientUrlItems } from "./types.js";
|
|
4
|
+
export declare function clientUrls<const TItems extends ClientUrlItems>(builder: ClientUrlBuilder<TItems>): ClientUrlPatterns<ExtractRoutes<TItems>>;
|
|
5
|
+
export type { ClientRevalidateArgs, ClientRevalidateFn, ClientTransitionConfig, ClientUrlBuilder, ClientUrlHelpers, ClientUrlInterceptRecord, ClientUrlItem, ClientUrlItemInput, ClientUrlItems, ClientLayoutFn, ClientPathOptions, ClientUrlLoaderRecord, ClientPathFn, ClientUrlPatterns, ClientUrlRouteRecord, ClientUrlUse, } from "./types.js";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ClientUrlPatterns } from "./types.js";
|
|
2
|
+
export interface ClientUrlNavigationIntent {
|
|
3
|
+
readonly routeId: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function setActiveInterceptTargets(targets: readonly string[] | undefined): void;
|
|
6
|
+
export interface ClientUrlNavigationPresentation {
|
|
7
|
+
readonly routeId: string;
|
|
8
|
+
clear(): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function registerClientUrlGroup(definition: ClientUrlPatterns, mount: string, namePrefix: string, setIntent: (intent: ClientUrlNavigationIntent | null) => void): () => void;
|
|
11
|
+
export declare function beginClientUrlNavigation(targetUrl: URL, signal: AbortSignal): ClientUrlNavigationPresentation | null;
|
|
12
|
+
/**
|
|
13
|
+
* Run the held clientUrls route's per-loader revalidate() predicates and
|
|
14
|
+
* encode their decisions for the request header. Predicates are CLIENT code
|
|
15
|
+
* (declared in the "use client" definition module); only decisions cross the
|
|
16
|
+
* wire — the synthesized per-loader revalidate() on every materialized stub
|
|
17
|
+
* (server-projection.ts) reads them back by loader $$id.
|
|
18
|
+
*
|
|
19
|
+
* Decisions exist only for the loaders the client currently HOLDS: the local
|
|
20
|
+
* match of currentUrl. They matter when the server would re-evaluate those
|
|
21
|
+
* held loader segments — same-route param/search navs, actions, and stale
|
|
22
|
+
* restores. Cross-route targets render new segments unconditionally, so a
|
|
23
|
+
* decision would be ignored; we still compute against the current route since
|
|
24
|
+
* only its held segments are addressable.
|
|
25
|
+
*
|
|
26
|
+
* Returns null when no group is active, the current location is not a client
|
|
27
|
+
* route, or no predicate produced a decision that differs from the locked
|
|
28
|
+
* default — the server then applies defaults, which is also the behavior for
|
|
29
|
+
* requests that cannot carry decisions (no-JS, PE, prefetch, document loads).
|
|
30
|
+
*/
|
|
31
|
+
export declare function collectClientRevalidationDecisions(options: {
|
|
32
|
+
currentUrl: URL;
|
|
33
|
+
nextUrl: URL;
|
|
34
|
+
isAction: boolean;
|
|
35
|
+
actionId?: string;
|
|
36
|
+
stale: boolean;
|
|
37
|
+
}): string | null;
|
|
38
|
+
export declare function clearClientUrlNavigationRegistry(): void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire protocol for CLIENT-RUN per-loader revalidation decisions.
|
|
3
|
+
*
|
|
4
|
+
* clientUrls() revalidate() predicates are declared in a "use client" module,
|
|
5
|
+
* so they cannot cross the projection boundary as functions — instead they
|
|
6
|
+
* EXECUTE in the browser and only their DECISIONS cross: the browser attaches
|
|
7
|
+
* this header to partial-navigation and action requests, and the synthesized
|
|
8
|
+
* per-loader revalidate() on every materialized loader stub reads it back
|
|
9
|
+
* (see materializeRouteItems in server-projection.ts).
|
|
10
|
+
*
|
|
11
|
+
* Trust model: same class as `_rsc_segments` — a decision can only make the
|
|
12
|
+
* CLIENT's own view staler (skip) or fresher (force), and the synthesized
|
|
13
|
+
* predicates exist only on client-urls loader stubs, so the header can never
|
|
14
|
+
* influence server-tree loaders. Requests without the header (no-JS, PE,
|
|
15
|
+
* prefetch, document loads) fall back to the locked server defaults.
|
|
16
|
+
*/
|
|
17
|
+
export declare const CLIENT_REVALIDATION_HEADER = "X-Rango-Client-Reval";
|
|
18
|
+
export interface ClientRevalidationDecisions {
|
|
19
|
+
/** Loader $$ids whose client predicate said false (keep held data). */
|
|
20
|
+
readonly skip: readonly string[];
|
|
21
|
+
/** Loader $$ids whose client predicate said true against a false default. */
|
|
22
|
+
readonly force: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export declare function encodeClientRevalidationDecisions(decisions: ClientRevalidationDecisions): string | null;
|
|
25
|
+
export declare function decodeClientRevalidationDecisions(headerValue: string | null): ClientRevalidationDecisions | null;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { SearchSchemaValue } from "../search-params.js";
|
|
2
|
+
import type { TrailingSlashMode } from "../types.js";
|
|
3
|
+
import type { PartialPrerenderProps, UrlPatterns } from "../urls/pattern-types.js";
|
|
4
|
+
import type { ClientTransitionConfig, ClientUrlPatterns } from "./types.js";
|
|
5
|
+
export interface ClientUrlReference {
|
|
6
|
+
readonly $$typeof: symbol;
|
|
7
|
+
readonly $$id: string;
|
|
8
|
+
}
|
|
9
|
+
export type ClientUrlDefinitionSource = ClientUrlReference | ClientUrlPatterns;
|
|
10
|
+
export interface ClientUrlProjectionOptions {
|
|
11
|
+
readonly search?: Readonly<Record<string, SearchSchemaValue>>;
|
|
12
|
+
readonly trailingSlash?: TrailingSlashMode;
|
|
13
|
+
/**
|
|
14
|
+
* The `ppr` path option, JSON-projected. Materialization passes it onto
|
|
15
|
+
* the group route's server `path()` verbatim, so the manifest entry
|
|
16
|
+
* carries it and the runtime shell capture/serve lanes engage exactly as
|
|
17
|
+
* for a hand-written server route (search is part of shell identity —
|
|
18
|
+
* the capture render seeds the key's own search, so group static parts
|
|
19
|
+
* may read useSearchParams).
|
|
20
|
+
*/
|
|
21
|
+
readonly ppr?: true | Readonly<PartialPrerenderProps>;
|
|
22
|
+
}
|
|
23
|
+
export interface ClientUrlProjectionRoute {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly pattern: string;
|
|
26
|
+
readonly name: string | null;
|
|
27
|
+
readonly options: ClientUrlProjectionOptions;
|
|
28
|
+
readonly loaderIds: readonly string[];
|
|
29
|
+
readonly hasLoading: boolean;
|
|
30
|
+
/** Indices into loaderIds of loaders declared loader(Def, { stream:
|
|
31
|
+
* "navigation" }); materialization passes the option through to the server
|
|
32
|
+
* loader() so document renders await them before first flush. Absent (=
|
|
33
|
+
* none) in projections serialized before stream support. */
|
|
34
|
+
readonly awaitedLoaderIndices?: readonly number[];
|
|
35
|
+
/** Data-only transition config (no `when` — server-tree only); absent in
|
|
36
|
+
* projections serialized before transition support. */
|
|
37
|
+
readonly transition?: Readonly<ClientTransitionConfig>;
|
|
38
|
+
}
|
|
39
|
+
export interface ClientUrlProjectionIntercept {
|
|
40
|
+
readonly slotName: `@${string}`;
|
|
41
|
+
/** Bare local target name; materialization re-dots it so the server
|
|
42
|
+
* intercept() helper composes it against the include's name prefix. */
|
|
43
|
+
readonly targetName: string;
|
|
44
|
+
readonly loaderIds: readonly string[];
|
|
45
|
+
readonly hasLoading: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface ClientUrlProjection {
|
|
48
|
+
readonly version: 1;
|
|
49
|
+
readonly routes: readonly ClientUrlProjectionRoute[];
|
|
50
|
+
/** Absent in projections serialized before intercept support; consumers
|
|
51
|
+
* must treat missing as empty. */
|
|
52
|
+
readonly intercepts?: readonly ClientUrlProjectionIntercept[];
|
|
53
|
+
}
|
|
54
|
+
export declare function serializeClientUrlPatterns(patterns: ClientUrlPatterns): ClientUrlProjection;
|
|
55
|
+
export declare function isClientUrlPatterns(value: unknown): value is ClientUrlPatterns;
|
|
56
|
+
export declare function isClientUrlReference(value: unknown): value is ClientUrlReference;
|
|
57
|
+
export declare function setClientUrlProjection(reference: string | ClientUrlReference, projection: ClientUrlProjection): void;
|
|
58
|
+
export declare function getClientUrlProjection(reference: string | ClientUrlReference): ClientUrlProjection | undefined;
|
|
59
|
+
export declare function clearClientUrlProjections(): void;
|
|
60
|
+
export declare function materializeClientUrlPatterns(reference: ClientUrlDefinitionSource, projection: ClientUrlProjection): UrlPatterns;
|
|
61
|
+
/**
|
|
62
|
+
* Adapt a clientUrls() source for `include()` mounting inside the canonical
|
|
63
|
+
* urls() tree. Materialization is DEFERRED into the returned handler: it
|
|
64
|
+
* resolves the discovery-installed projection at evaluation time (lazy include
|
|
65
|
+
* expansion, build manifest generation, dev per-request trie rebuild) — by
|
|
66
|
+
* then the routes-manifest bootstrap has installed projections, so registration
|
|
67
|
+
* order never matters. The include machinery applies the URL and route-name
|
|
68
|
+
* prefixes exactly as it does for any urls() module; surrounding RSC layouts,
|
|
69
|
+
* middleware scoping, and boundaries derive from the canonical server tree.
|
|
70
|
+
*/
|
|
71
|
+
export declare function clientUrlIncludePatterns(source: ClientUrlDefinitionSource): UrlPatterns;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { ComponentType, ReactNode } from "react";
|
|
2
|
+
import type { LoaderDefinition, LoaderOptions, TransitionConfig } from "../types.js";
|
|
3
|
+
import type { TrieMatchResult } from "../router/trie-matching.js";
|
|
4
|
+
import type { PathOptions } from "../urls/pattern-types.js";
|
|
5
|
+
import type { SearchSchema } from "../search-params.js";
|
|
6
|
+
import type { TypedLayoutItem, TypedRouteItem } from "../route-types.js";
|
|
7
|
+
import type { ExtractRoutes } from "../urls/type-extraction.js";
|
|
8
|
+
import type { UnnamedRoute } from "../urls/pattern-types.js";
|
|
9
|
+
declare const CLIENT_URL_ITEM_BRAND: unique symbol;
|
|
10
|
+
declare const CLIENT_URL_PATTERNS_BRAND: unique symbol;
|
|
11
|
+
/** Opaque value returned by a clientUrls() helper. */
|
|
12
|
+
export interface ClientUrlItem {
|
|
13
|
+
readonly [CLIENT_URL_ITEM_BRAND]: void;
|
|
14
|
+
}
|
|
15
|
+
export type ClientUrlItemInput = ClientUrlItem | readonly ClientUrlItemInput[];
|
|
16
|
+
export type ClientUrlItems = readonly ClientUrlItemInput[];
|
|
17
|
+
export type ClientUrlUse = () => ClientUrlItems;
|
|
18
|
+
export type ClientPathOptions<TName extends string = string, TSearch extends SearchSchema = SearchSchema> = Pick<PathOptions<TName, TSearch>, "name" | "search" | "trailingSlash" | "ppr">;
|
|
19
|
+
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
|
+
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.
|
|
27
|
+
*/
|
|
28
|
+
export interface ClientRevalidateArgs {
|
|
29
|
+
/** Full URL of the page being navigated away from (current location). */
|
|
30
|
+
readonly currentUrl: URL;
|
|
31
|
+
/** Full URL of the navigation target (equals currentUrl for actions). */
|
|
32
|
+
readonly nextUrl: URL;
|
|
33
|
+
/** Route params of the held client route (definition-local match). */
|
|
34
|
+
readonly currentParams: Record<string, string>;
|
|
35
|
+
/** Route params for the navigation target (definition-local match). */
|
|
36
|
+
readonly nextParams: Record<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* The locked default decision for this loader, computed client-side with
|
|
39
|
+
* the same rules the server would apply: `true` on actions and when
|
|
40
|
+
* params/search changed, `false` otherwise. Return it for default behavior
|
|
41
|
+
* plus your own conditions.
|
|
42
|
+
*/
|
|
43
|
+
readonly defaultShouldRevalidate: boolean;
|
|
44
|
+
/** True when this is a stale history-entry background revalidation. */
|
|
45
|
+
readonly stale: boolean;
|
|
46
|
+
/** True when revalidation is triggered by a server action. */
|
|
47
|
+
readonly isAction: boolean;
|
|
48
|
+
/** The triggering server action's id, when isAction. */
|
|
49
|
+
readonly actionId?: string;
|
|
50
|
+
}
|
|
51
|
+
export type ClientRevalidateFn = (args: ClientRevalidateArgs) => boolean;
|
|
52
|
+
export interface ClientUrlLoaderRecord {
|
|
53
|
+
readonly loader: LoaderDefinition<any, any>;
|
|
54
|
+
/** Client-run per-loader revalidation predicates; empty = locked defaults. */
|
|
55
|
+
readonly revalidate: readonly ClientRevalidateFn[];
|
|
56
|
+
/**
|
|
57
|
+
* loader(Def, { stream: "navigation" }): document renders await this loader
|
|
58
|
+
* before first flush (see {@link LoaderOptions}). Projected into the server
|
|
59
|
+
* tree, where the per-isSSR entry stamping applies — client navigations
|
|
60
|
+
* stream regardless.
|
|
61
|
+
*/
|
|
62
|
+
readonly stream?: "navigation";
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The data-only subset of TransitionConfig a clientUrls() route may declare:
|
|
66
|
+
* ViewTransition classes/name plus the boundary opt-out. The `when` gate is a
|
|
67
|
+
* server-executed predicate and stays in the server tree — it cannot cross the
|
|
68
|
+
* "use client" projection boundary.
|
|
69
|
+
*/
|
|
70
|
+
export type ClientTransitionConfig = Pick<TransitionConfig, "enter" | "exit" | "update" | "share" | "default" | "name" | "viewTransition">;
|
|
71
|
+
export interface ClientUrlRouteRecord {
|
|
72
|
+
readonly id: string;
|
|
73
|
+
readonly pattern: string;
|
|
74
|
+
readonly name: string | undefined;
|
|
75
|
+
readonly options: Readonly<ClientPathOptions> | undefined;
|
|
76
|
+
readonly component: ComponentType;
|
|
77
|
+
readonly layouts: readonly ComponentType[];
|
|
78
|
+
readonly loaders: readonly ClientUrlLoaderRecord[];
|
|
79
|
+
readonly loading: ReactNode | undefined;
|
|
80
|
+
readonly transition: Readonly<ClientTransitionConfig> | undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A restricted intercept declared inside clientUrls(). Compared to the server
|
|
84
|
+
* intercept() there is no `when` selector, no middleware, and the target must
|
|
85
|
+
* be a dot-local NAMED route in the same definition — every field is
|
|
86
|
+
* JSON-projectable, which is what makes the declaration legal in a
|
|
87
|
+
* "use client" module. `targetName` is stored bare (no leading dot).
|
|
88
|
+
*/
|
|
89
|
+
export interface ClientUrlInterceptRecord {
|
|
90
|
+
readonly slotName: `@${string}`;
|
|
91
|
+
readonly targetName: string;
|
|
92
|
+
readonly component: ComponentType;
|
|
93
|
+
readonly loaders: readonly ClientUrlLoaderRecord[];
|
|
94
|
+
readonly loading: ReactNode | undefined;
|
|
95
|
+
}
|
|
96
|
+
export interface ClientUrlHelpers {
|
|
97
|
+
readonly path: ClientPathFn;
|
|
98
|
+
readonly layout: ClientLayoutFn;
|
|
99
|
+
/**
|
|
100
|
+
* Attach a projected loader. The optional use callback may contain
|
|
101
|
+
* revalidate() only — a CLIENT-RUN per-loader predicate; its decision (not
|
|
102
|
+
* the function) is sent with the revalidation request.
|
|
103
|
+
*
|
|
104
|
+
* Pass `{ stream: "navigation" }` to await this loader before first flush
|
|
105
|
+
* on DOCUMENT requests (see {@link LoaderOptions}) — the opt-in for loaders
|
|
106
|
+
* whose data, handle pushes, or thrown notFound()/redirect() must be in the
|
|
107
|
+
* SSR'd HTML. Per-loader: a dynamic sibling keeps streaming. Under a
|
|
108
|
+
* `ppr` group route the flag BAKES: the loader executes at shell capture
|
|
109
|
+
* and its settled return freezes into the shell (nested promises stay
|
|
110
|
+
* live holes).
|
|
111
|
+
*/
|
|
112
|
+
readonly loader: <TData>(definition: LoaderDefinition<TData>, optionsOrUse?: LoaderOptions | ClientUrlUse, use?: ClientUrlUse) => ClientUrlItem;
|
|
113
|
+
readonly loading: (component: ReactNode) => ClientUrlItem;
|
|
114
|
+
/**
|
|
115
|
+
* Per-loader revalidation predicate, valid inside a loader() use callback
|
|
116
|
+
* only. Runs IN THE BROWSER with client-computable args; return true to
|
|
117
|
+
* re-run the loader, false to keep held data. Absent predicates (and
|
|
118
|
+
* requests that carry no decisions: no-JS, PE, prefetch, document loads)
|
|
119
|
+
* follow the locked server defaults.
|
|
120
|
+
*/
|
|
121
|
+
readonly revalidate: (fn: ClientRevalidateFn) => ClientUrlItem;
|
|
122
|
+
/**
|
|
123
|
+
* Declare an intercept for a named route in THIS definition. The target is
|
|
124
|
+
* dot-local (`.detail`); scoping is module-local — only navigations whose
|
|
125
|
+
* origin is inside this clientUrls() group render the intercept. `use` may
|
|
126
|
+
* contain loader() and loading() only.
|
|
127
|
+
*/
|
|
128
|
+
readonly intercept: (slotName: `@${string}`, targetName: `.${string}`, component: ComponentType, use?: ClientUrlUse) => ClientUrlItem;
|
|
129
|
+
/**
|
|
130
|
+
* Opt THIS route into transition-driven navigation: the canonical commit
|
|
131
|
+
* holds previous content instead of re-streaming the loading() fallback,
|
|
132
|
+
* and on experimental React the config's ViewTransition classes apply.
|
|
133
|
+
* Data-only — no `when` gate (server-executed; declare it in the server
|
|
134
|
+
* tree). Valid inside a path() use callback only.
|
|
135
|
+
*/
|
|
136
|
+
readonly transition: (config: ClientTransitionConfig) => ClientUrlItem;
|
|
137
|
+
}
|
|
138
|
+
export type ClientUrlBuilder<TItems extends ClientUrlItems = ClientUrlItems> = (helpers: ClientUrlHelpers) => TItems;
|
|
139
|
+
export interface ClientUrlPatterns<TRoutes extends Record<string, any> = Record<string, any>> {
|
|
140
|
+
readonly __brand: "client-urls";
|
|
141
|
+
readonly routes: readonly ClientUrlRouteRecord[];
|
|
142
|
+
readonly intercepts: readonly ClientUrlInterceptRecord[];
|
|
143
|
+
readonly [CLIENT_URL_PATTERNS_BRAND]: void;
|
|
144
|
+
readonly _routes?: TRoutes;
|
|
145
|
+
match(pathname: string): TrieMatchResult | null;
|
|
146
|
+
}
|
|
147
|
+
export {};
|