@rangojs/router 0.5.2 → 0.6.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 +62 -0
- package/dist/types/client-urls/types.d.ts +144 -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/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 +10 -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/vite/index.js +5313 -2365
- package/package.json +1 -1
- 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 +698 -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 +579 -0
- package/src/client-urls/types.ts +195 -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 +47 -0
- package/src/router/segment-resolution/helpers.ts +9 -11
- package/src/router/segment-resolution/loader-cache.ts +14 -24
- package/src/router/segment-resolution/revalidation.ts +20 -1
- 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 +14 -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/virtual-entries.ts +12 -3
- package/src/vite/router-discovery.ts +163 -12
|
@@ -33,12 +33,29 @@ export interface RscPayload {
|
|
|
33
33
|
/** Merged route params from the matched route */
|
|
34
34
|
params?: Record<string, string>;
|
|
35
35
|
slots?: Record<string, SlotState>;
|
|
36
|
+
/**
|
|
37
|
+
* Intercept TARGET route names reachable from this location as a
|
|
38
|
+
* navigation origin (see MatchResult.interceptTargets). The browser-local
|
|
39
|
+
* clientUrls matcher declines optimistic presentation for these.
|
|
40
|
+
*/
|
|
41
|
+
interceptTargets?: string[];
|
|
36
42
|
/** Root layout component for browser-side re-renders (client component reference) */
|
|
37
43
|
rootLayout?: React.ComponentType<{
|
|
38
44
|
children: React.ReactNode;
|
|
39
45
|
}>;
|
|
40
46
|
/** Handle data accumulated across route segments (async generator that yields on each push) */
|
|
41
47
|
handles?: AsyncGenerator<HandleData, void, unknown>;
|
|
48
|
+
/**
|
|
49
|
+
* Document-lane late handle channel: full-state updates for pushes landing
|
|
50
|
+
* AFTER the handler barrier (streaming loader bodies writing handles
|
|
51
|
+
* mid-body). `handles` above is drained to completion in blocking
|
|
52
|
+
* positions (SSR seed, pre-hydration), so late pushes need this separate
|
|
53
|
+
* generator, consumed non-blocking post-hydration (rsc-router.tsx).
|
|
54
|
+
* Empty/instantly-complete when no auxiliary-lane work is pending at the
|
|
55
|
+
* handler barrier. Full payloads only — partial payloads' `handles`
|
|
56
|
+
* generator streams to full settle already.
|
|
57
|
+
*/
|
|
58
|
+
handlesLate?: AsyncGenerator<HandleData, void, unknown>;
|
|
42
59
|
/** RSC version string for cache invalidation */
|
|
43
60
|
version?: string;
|
|
44
61
|
/** Cloudflare dev worker generation used for stale-document convergence. */
|
|
@@ -147,6 +164,17 @@ export interface SSRRenderOptions {
|
|
|
147
164
|
* - `"allReady"` — await `stream.allReady` before returning.
|
|
148
165
|
*/
|
|
149
166
|
streamMode?: import("../router/router-options.js").SSRStreamMode;
|
|
167
|
+
/**
|
|
168
|
+
* The live request's query string (`url.search`, `?`-prefixed or empty).
|
|
169
|
+
* Seeds the SSR navigation store so `useSearchParams` (and
|
|
170
|
+
* `useNavigation().location`) carry real values during document renders.
|
|
171
|
+
* Out-of-band by design — never payload metadata, which cached/prerendered
|
|
172
|
+
* payloads replay; search is not route identity. The build-time prerender
|
|
173
|
+
* pass passes none — build shells capture bare pathnames and serve
|
|
174
|
+
* search-less requests only (runtime ppr captures seed the shell key's
|
|
175
|
+
* search; see ShellCaptureOptions.search in the SSR entry).
|
|
176
|
+
*/
|
|
177
|
+
search?: string;
|
|
150
178
|
}
|
|
151
179
|
/**
|
|
152
180
|
* SSR module interface for HTML rendering
|
|
@@ -164,6 +192,7 @@ export interface SSRModule {
|
|
|
164
192
|
captureShellHTML?: (rscStream: ReadableStream<Uint8Array>, options: {
|
|
165
193
|
quiesce: Promise<void>;
|
|
166
194
|
maxWaitMs?: number;
|
|
195
|
+
search?: string;
|
|
167
196
|
}) => Promise<{
|
|
168
197
|
prelude: Uint8Array;
|
|
169
198
|
postponed: string | null;
|
|
@@ -179,6 +208,7 @@ export interface SSRModule {
|
|
|
179
208
|
resumeShellHTML?: (rscStream: ReadableStream<Uint8Array>, options: {
|
|
180
209
|
postponed: string | null;
|
|
181
210
|
nonce?: string;
|
|
211
|
+
search?: string;
|
|
182
212
|
}) => Promise<ReadableStream<Uint8Array>>;
|
|
183
213
|
}
|
|
184
214
|
/**
|
|
@@ -17,6 +17,8 @@ export interface RenderSegmentsOptions {
|
|
|
17
17
|
* from cache without showing loading skeletons.
|
|
18
18
|
*/
|
|
19
19
|
forceAwait?: boolean;
|
|
20
|
+
/** Seeded descendant client-route pending state for testing. */
|
|
21
|
+
outletPending?: boolean;
|
|
20
22
|
/**
|
|
21
23
|
* Intercept segments to inject into the tree.
|
|
22
24
|
* These are parallel segments from intercept routes that need to be
|
|
@@ -82,6 +82,16 @@ export type LoaderEntry = {
|
|
|
82
82
|
revalidate: ShouldRevalidateFn<any, any>[];
|
|
83
83
|
/** Cache config for this specific loader (loaders are NOT cached by default) */
|
|
84
84
|
cache?: EntryCacheConfig;
|
|
85
|
+
/**
|
|
86
|
+
* Document renders await this loader before segment resolution returns
|
|
87
|
+
* (loader(Def, { stream: "navigation" })), so its data, handle pushes, and
|
|
88
|
+
* thrown notFound()/redirect() deterministically precede first flush.
|
|
89
|
+
* Resolved at DSL-evaluation time from ctx.isSSR — entries are cached
|
|
90
|
+
* per-isSSR (router/manifest.ts cache key), so the flag is already
|
|
91
|
+
* request-mode-correct when resolveLoaders (fresh.ts) reads it and never
|
|
92
|
+
* appears on navigation-lane entries.
|
|
93
|
+
*/
|
|
94
|
+
awaitBeforeFlush?: true;
|
|
85
95
|
};
|
|
86
96
|
/**
|
|
87
97
|
* Segments state for intercept context
|
|
@@ -49,6 +49,24 @@ export interface HandleStore {
|
|
|
49
49
|
* to onError and telemetry.
|
|
50
50
|
*/
|
|
51
51
|
onError?: (error: Error) => void;
|
|
52
|
+
/**
|
|
53
|
+
* Track a promise on the AUXILIARY (loader) settlement lane. Aux tracking
|
|
54
|
+
* keeps the store OPEN for pushes (a mid-body `ctx.handle(H)(...)` from a
|
|
55
|
+
* streaming loader is legal until this lane drains) WITHOUT joining
|
|
56
|
+
* `settled` — the handler barrier that rendered()-readers, the document
|
|
57
|
+
* handle snapshot, and prerender/cache collection wait on. Two lanes exist
|
|
58
|
+
* because loader bodies stream: joining them to `settled` would block SSR
|
|
59
|
+
* markup and hydration on the slowest loader (ssr-root.tsx and
|
|
60
|
+
* rsc-router.tsx both drain the document handle stream in blocking
|
|
61
|
+
* positions), and would self-deadlock any loader awaiting ctx.rendered().
|
|
62
|
+
*/
|
|
63
|
+
trackAuxiliary<T>(promise: Promise<T>): Promise<T>;
|
|
64
|
+
/**
|
|
65
|
+
* Promise that resolves when the store is sealed AND BOTH lanes (handler +
|
|
66
|
+
* auxiliary) have drained. Late-push legality and default stream completion
|
|
67
|
+
* key on this, not on `settled`.
|
|
68
|
+
*/
|
|
69
|
+
readonly fullySettled: Promise<void>;
|
|
52
70
|
/**
|
|
53
71
|
* Push handle data for a specific handle and segment.
|
|
54
72
|
* Multiple pushes to the same handle/segment accumulate in an array.
|
|
@@ -57,15 +75,28 @@ export interface HandleStore {
|
|
|
57
75
|
push(handleName: string, segmentId: string, data: unknown): void;
|
|
58
76
|
/**
|
|
59
77
|
* Get all collected handle data after all handlers have settled.
|
|
60
|
-
* Waits for `settled
|
|
78
|
+
* Waits for `settled` (handler lane), then returns the data at that point.
|
|
61
79
|
*/
|
|
62
80
|
getData(): Promise<HandleData>;
|
|
63
81
|
/**
|
|
64
82
|
* Get an async iterator that yields handle data on each push.
|
|
65
|
-
*
|
|
83
|
+
* Completes at the chosen settlement barrier: "fullySettled" (default —
|
|
84
|
+
* nav/action payloads, whose consumer applies each yield progressively) or
|
|
85
|
+
* "settled" (the document lane, whose consumers drain to completion in
|
|
86
|
+
* blocking positions and must not wait on loader bodies).
|
|
66
87
|
* Each yield contains the full accumulated state (not just the delta).
|
|
88
|
+
* Safe for concurrent consumers (per-consumer version cursor).
|
|
89
|
+
*/
|
|
90
|
+
stream(until?: "settled" | "fullySettled"): AsyncGenerator<HandleData, void, unknown>;
|
|
91
|
+
/**
|
|
92
|
+
* Document-lane late channel: yields full-state updates for pushes that
|
|
93
|
+
* land AFTER the handler barrier (streaming loader bodies), completing at
|
|
94
|
+
* fullySettled. Returns without yielding when the auxiliary lane is empty
|
|
95
|
+
* by the time `settled` resolves. The client consumes this post-hydration
|
|
96
|
+
* (rsc-router.tsx) and merges via the same application path as nav-lane
|
|
97
|
+
* progressive handle updates.
|
|
67
98
|
*/
|
|
68
|
-
|
|
99
|
+
streamLate(): AsyncGenerator<HandleData, void, unknown>;
|
|
69
100
|
/**
|
|
70
101
|
* Get handle data for a specific segment (for caching).
|
|
71
102
|
* Returns data in format: { handleName: [values...] }
|
|
@@ -507,6 +507,16 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
507
507
|
* rendered() and a handler already awaits it, we can detect the deadlock.
|
|
508
508
|
*/
|
|
509
509
|
_handlerLoaderDeps?: Set<string>;
|
|
510
|
+
/**
|
|
511
|
+
* @internal Loader IDs ($$id) whose entries carry `awaitBeforeFlush`
|
|
512
|
+
* (loader(Def, { stream: "navigation" })): segment resolution awaits these
|
|
513
|
+
* before returning, so the render barrier cannot resolve until they settle.
|
|
514
|
+
* rendered() checks this set to fail fast — a flagged loader awaiting the
|
|
515
|
+
* barrier is a guaranteed cycle, not a race. Registered by resolveLoaders
|
|
516
|
+
* (fresh.ts) before loader kickoff; only ever populated on document renders
|
|
517
|
+
* (the flag is stamped per-isSSR at DSL evaluation).
|
|
518
|
+
*/
|
|
519
|
+
_awaitBeforeFlushLoaderIds?: Set<string>;
|
|
510
520
|
/**
|
|
511
521
|
* @internal Cached HandleData snapshot built at barrier resolution time.
|
|
512
522
|
* Avoids rebuilding the snapshot on every loader ctx.use(handle) call.
|
|
@@ -588,7 +598,7 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
588
598
|
* This is the type exported to library consumers. Internal code should
|
|
589
599
|
* use the full RequestContext interface directly.
|
|
590
600
|
*/
|
|
591
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhen" | "_pprTransitionDecisions" | "_pprReplayPostMatchReason" | "_cacheStore" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureHandleLiveness" | "_shellCaptureLoaderHandleValues" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_locationState" | "_routeName" | "_prevRouteKey" | "_gateCurrentUrl" | "_gateCurrentParams" | "_gateActionId" | "_gateActionUrl" | "_gateActionResult" | "_gateFormData" | "_inActionRevalidation" | "_reportedErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
601
|
+
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhen" | "_pprTransitionDecisions" | "_pprReplayPostMatchReason" | "_cacheStore" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureHandleLiveness" | "_shellCaptureLoaderHandleValues" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_locationState" | "_routeName" | "_prevRouteKey" | "_gateCurrentUrl" | "_gateCurrentParams" | "_gateActionId" | "_gateActionUrl" | "_gateActionResult" | "_gateFormData" | "_inActionRevalidation" | "_reportedErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
592
602
|
/**
|
|
593
603
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
594
604
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
package/dist/types/server.d.ts
CHANGED
|
@@ -13,3 +13,4 @@ export { registerRouteMap, setCachedManifest, clearCachedManifest, clearAllRoute
|
|
|
13
13
|
export { registerLoaderById, setLoaderImports, } from "./server/loader-registry.js";
|
|
14
14
|
export { createRequestContext, type CreateRequestContextOptions, } from "./server/request-context.js";
|
|
15
15
|
export { isClientComponent, assertClientComponent } from "./component-utils.js";
|
|
16
|
+
export { clearClientUrlProjections, setClientUrlProjection, type ClientUrlProjection, } from "./client-urls/server-projection.js";
|
|
@@ -82,6 +82,14 @@ export interface SSRRenderOptions {
|
|
|
82
82
|
* - `"allReady"` — await `stream.allReady` before returning.
|
|
83
83
|
*/
|
|
84
84
|
streamMode?: import("../router/router-options.js").SSRStreamMode;
|
|
85
|
+
/**
|
|
86
|
+
* The live request's query string (`?`-prefixed or empty). Seeds the SSR
|
|
87
|
+
* navigation store location so `useSearchParams` carries real values
|
|
88
|
+
* during document renders. Absent on the build-time prerender pass —
|
|
89
|
+
* build shells capture bare pathnames and serve search-less requests
|
|
90
|
+
* only (runtime captures own the search variants, seeded per key).
|
|
91
|
+
*/
|
|
92
|
+
search?: string;
|
|
85
93
|
}
|
|
86
94
|
/**
|
|
87
95
|
* SSR dependencies from external packages
|
|
@@ -169,6 +177,13 @@ interface ShellCaptureOptions {
|
|
|
169
177
|
quiesce: Promise<void>;
|
|
170
178
|
/** Upper bound on how long to wait for `quiesce`. Default SHELL_CAPTURE_MAX_WAIT_MS. */
|
|
171
179
|
maxWaitMs?: number;
|
|
180
|
+
/**
|
|
181
|
+
* The SHELL KEY's search string (`?`-prefixed, sorted, cache.searchParams
|
|
182
|
+
* filter applied — shellSearchSeed in rsc/shell-serve.ts), seeding the SSR
|
|
183
|
+
* store so static-part `useSearchParams` reads bake markup consistent with
|
|
184
|
+
* the shell's own key. MUST equal the resume pass's seed for the same key.
|
|
185
|
+
*/
|
|
186
|
+
search?: string;
|
|
172
187
|
}
|
|
173
188
|
/**
|
|
174
189
|
* Result of a successful shell capture. `prelude` is the raw prelude bytes;
|
|
@@ -188,6 +203,13 @@ interface ShellResumeOptions {
|
|
|
188
203
|
postponed: string | null;
|
|
189
204
|
/** Nonce for CSP. */
|
|
190
205
|
nonce?: string;
|
|
206
|
+
/**
|
|
207
|
+
* The SHELL KEY's search string — same derivation as the capture pass
|
|
208
|
+
* (shellSearchSeed). A HIT shares the capture's key, so seeding the same
|
|
209
|
+
* string keeps the resume tree identical to the captured tree above the
|
|
210
|
+
* postponed holes.
|
|
211
|
+
*/
|
|
212
|
+
search?: string;
|
|
191
213
|
}
|
|
192
214
|
/**
|
|
193
215
|
* Create an SSR handler that converts RSC streams to HTML.
|
|
@@ -48,6 +48,16 @@ export interface SsrRootOptions {
|
|
|
48
48
|
* they postpone below the root.
|
|
49
49
|
*/
|
|
50
50
|
onPayloadSettled?: () => void;
|
|
51
|
+
/**
|
|
52
|
+
* The query string seeding the SSR store location (`?`-prefixed or
|
|
53
|
+
* empty), so `useSearchParams`/`useNavigation` carry real values during
|
|
54
|
+
* document renders. Live fizz passes the request's raw search. The shell
|
|
55
|
+
* capture and resume passes pass the SHELL KEY's search (sorted,
|
|
56
|
+
* cache.searchParams filter applied — search is part of shell identity):
|
|
57
|
+
* a HIT shares the capture's key, so both passes seed the SAME string and
|
|
58
|
+
* the resume tree matches the captured tree above the postponed holes.
|
|
59
|
+
*/
|
|
60
|
+
search?: string;
|
|
51
61
|
}
|
|
52
62
|
/**
|
|
53
63
|
* Build the closure component that deserializes the Flight payload, consumes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Component-render testing: `renderRoute`, the React-Testing-Library-style stub
|
|
5
5
|
* for client components that read router context (useParams / useReverse /
|
|
6
|
-
* Outlet / useNavigation / useLoader).
|
|
6
|
+
* Outlet / useOutlet / useNavigation / useLoader).
|
|
7
7
|
*
|
|
8
8
|
* Separate from the main `@rangojs/router/testing` barrel so unit suites that
|
|
9
9
|
* only test loaders, middleware, or `dispatch` never reference React, the
|
|
@@ -19,18 +19,19 @@
|
|
|
19
19
|
* props crossing the RSC boundary), loader execution on the server,
|
|
20
20
|
* middleware, or handler ordering. Those are renderServerTree / renderHandler
|
|
21
21
|
* / e2e territory.
|
|
22
|
-
* - Loader data, location state,
|
|
23
|
-
* client context (see the `loaders` / `locationState` /
|
|
24
|
-
* nothing is executed on the server.
|
|
25
|
-
*
|
|
22
|
+
* - Loader data, location state, handle output, and outlet pending state are
|
|
23
|
+
* SEEDED directly into client context (see the `loaders` / `locationState` /
|
|
24
|
+
* `handles` / `outletPending` options) — nothing is executed on the server.
|
|
25
|
+
* This exercises the context read path, not the run path.
|
|
26
26
|
* - navigate() commits synchronously, so it does NOT drive the navigation
|
|
27
27
|
* lifecycle: useNavigation().state, useLinkStatus().pending, and
|
|
28
28
|
* useAction().state stay "idle". Assert pending/loading/submitting transition
|
|
29
29
|
* states with renderServerTree / e2e instead (navigate() warns once if used).
|
|
30
30
|
* What it DOES cover: client hooks that read NavigationProvider /
|
|
31
31
|
* OutletContext — useParams, useReverse, useHref, useMount, useNavigation,
|
|
32
|
-
* useRouter, usePathname, useSearchParams, Outlet nesting
|
|
33
|
-
*
|
|
32
|
+
* useRouter, usePathname, useSearchParams, Outlet/useOutlet nesting and seeded
|
|
33
|
+
* descendant pending state, useLoader/useFetchLoader (seeded data),
|
|
34
|
+
* useLocationState (seeded), and useHandle (seeded).
|
|
34
35
|
* Basename-mounted apps: pass the `basename` option so useRouter().basename,
|
|
35
36
|
* <Link> prefixing, and useMount/useHref resolve against the mount prefix
|
|
36
37
|
* (without it they resolve at the root "/"). For an include("/shop", ...)
|
|
@@ -96,6 +97,15 @@ export interface RenderRouteOptions {
|
|
|
96
97
|
* the read path is exercised without executing any loader.
|
|
97
98
|
*/
|
|
98
99
|
loaderData?: Record<string, unknown>;
|
|
100
|
+
/**
|
|
101
|
+
* Descendant client-route pending state to seed into each synthetic segment's
|
|
102
|
+
* production OutletProvider, so `useOutlet().pending` can be tested alongside
|
|
103
|
+
* `useOutlet().content`. Defaults to false.
|
|
104
|
+
*
|
|
105
|
+
* This is a seeded outlet-context value only. It does not model arbitrary
|
|
106
|
+
* Suspense, navigation, or action pending state.
|
|
107
|
+
*/
|
|
108
|
+
outletPending?: boolean;
|
|
99
109
|
/**
|
|
100
110
|
* Loaders to seed by REFERENCE — the robust way to test a component that calls
|
|
101
111
|
* `useLoader(loader)`. A real `createLoader()` handle has an empty `$$id` in a
|
|
@@ -52,6 +52,7 @@ export type TestLoaderContext<TEnv = any> = Omit<LoaderContext<any, TEnv>, "reve
|
|
|
52
52
|
reverse: (name: string, params?: Record<string, string>, search?: Record<string, unknown>) => string;
|
|
53
53
|
get: {
|
|
54
54
|
<T>(contextVar: ContextVar<T>): T | undefined;
|
|
55
|
+
<TData, TAccumulated = TData[]>(handle: Handle<TData, TAccumulated>): TAccumulated;
|
|
55
56
|
<T = unknown>(key: string): T | undefined;
|
|
56
57
|
};
|
|
57
58
|
};
|
|
@@ -182,5 +183,13 @@ export interface RunLoaderResult<T> {
|
|
|
182
183
|
locationState: Record<string, unknown>;
|
|
183
184
|
/** The resolved rango state cookie name seeded for the run (default `rango-state_router_0`). */
|
|
184
185
|
stateCookieName: string;
|
|
186
|
+
/**
|
|
187
|
+
* Handle writes the loader made via `ctx.use(SomeHandle)({...})`, in push
|
|
188
|
+
* order. A `.defer()` resolver's value is recorded when the resolver runs.
|
|
189
|
+
*/
|
|
190
|
+
handlePushes: Array<{
|
|
191
|
+
handle: Handle<any, any>;
|
|
192
|
+
value: unknown;
|
|
193
|
+
}>;
|
|
185
194
|
}
|
|
186
195
|
export declare function runLoaderResult<T>(loader: RunnableLoader<T>, opts?: RunLoaderOptions): Promise<RunLoaderResult<T>>;
|
|
@@ -63,6 +63,28 @@ export type LoaderDataResult<T = unknown> = {
|
|
|
63
63
|
ok: false;
|
|
64
64
|
error: ErrorInfo;
|
|
65
65
|
fallback: ReactNode | null;
|
|
66
|
+
/**
|
|
67
|
+
* Loader threw notFound() (DataNotFoundError). `fallback` carries the
|
|
68
|
+
* SERVER-RENDERED not-found UI (nearest notFoundBoundary → router
|
|
69
|
+
* notFound option → default), so the client swaps to 404 presentation
|
|
70
|
+
* with zero extra round trips. Routed by decodeLoaderEntry via
|
|
71
|
+
* LOADER_NOT_FOUND_FALLBACK, not the error-fallback marker.
|
|
72
|
+
*/
|
|
73
|
+
notFound?: true;
|
|
74
|
+
/**
|
|
75
|
+
* Loader threw redirect(...) (a 3xx Response). `to` is resolved through
|
|
76
|
+
* the soft-redirect same-origin rules BEFORE leaving the server
|
|
77
|
+
* (resolveSoftRedirectUrl), so unsafe targets never reach the wire. The
|
|
78
|
+
* client navigates (replace) when the entry decodes. `state` is the
|
|
79
|
+
* resolved `redirect(url, { state })` record (`__rsc_ls_*` keys) — it
|
|
80
|
+
* travels on the marker because a streaming loader settles after
|
|
81
|
+
* payload metadata flushed; the redirect navigation merges it at the
|
|
82
|
+
* target entry.
|
|
83
|
+
*/
|
|
84
|
+
redirect?: {
|
|
85
|
+
to: string;
|
|
86
|
+
state?: Record<string, unknown>;
|
|
87
|
+
};
|
|
66
88
|
};
|
|
67
89
|
export declare function isLoaderDataResult(value: unknown): value is LoaderDataResult;
|
|
68
90
|
export interface NotFoundInfo {
|
|
@@ -6,6 +6,6 @@ export { isLoaderDataResult } from "./boundaries.js";
|
|
|
6
6
|
export type { MiddlewareFn, ScopedRouteMap, Handler, HandlerContext, InternalHandlerContext, GenericParams, RevalidateParams, ShouldRevalidateFn, ActionRef, RouteKeys, ExtractRouteParams, HandlersForRouteMap, Revalidate, Middleware, } from "./handler-context.js";
|
|
7
7
|
export type { ViewTransitionClass, TransitionConfig, TransitionWhenFn, TransitionWhenContext, ResolvedSegment, SegmentMetadata, SlotState, RootLayoutProps, MatchResult, } from "./segments.js";
|
|
8
8
|
export type { LazyIncludeContext, RouteEntry } from "./route-entry.js";
|
|
9
|
-
export type { LoaderContext, LoaderFn, FetchableLoaderOptions, LoadOptions, LoaderDefinition, } from "./loader-types.js";
|
|
9
|
+
export type { LoaderContext, LoaderFn, FetchableLoaderOptions, LoaderOptions, LoadOptions, LoaderDefinition, } from "./loader-types.js";
|
|
10
10
|
export type { CacheContext, CacheOptions, PartialCacheOptions, EntryCacheConfig, } from "./cache-types.js";
|
|
11
11
|
export type { ErrorPhase, OnErrorContext, OnErrorCallback, } from "./error-types.js";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ContextVar } from "../context-var.js";
|
|
2
2
|
import type { Handle } from "../handle.js";
|
|
3
|
+
import type { HandlePush } from "../defer.js";
|
|
3
4
|
import type { MiddlewareFn } from "../router/middleware.js";
|
|
4
5
|
import type { ScopedReverseFunction } from "../reverse.js";
|
|
5
6
|
import type { SearchSchema, ResolveSearchSchema } from "../search-params.js";
|
|
@@ -41,24 +42,50 @@ export type LoaderContext<TParams = Record<string, string | undefined>, TEnv = D
|
|
|
41
42
|
*/
|
|
42
43
|
routeParams: Record<string, string>;
|
|
43
44
|
search: {} extends TSearch ? {} : ResolveSearchSchema<TSearch>;
|
|
45
|
+
/**
|
|
46
|
+
* Read a context variable — or READ collected handle data after
|
|
47
|
+
* `await ctx.rendered()` (the rendered-barrier contract; handle reads
|
|
48
|
+
* moved here from ctx.use(handle), which is now the write).
|
|
49
|
+
*/
|
|
44
50
|
get: {
|
|
45
51
|
<T>(contextVar: ContextVar<T>): T | undefined;
|
|
52
|
+
<TData, TAccumulated = TData[]>(handle: Handle<TData, TAccumulated>): TAccumulated;
|
|
46
53
|
} & (<K extends keyof DefaultVars>(key: K) => DefaultVars[K]);
|
|
47
54
|
/**
|
|
48
|
-
* Access another loader's data, or
|
|
55
|
+
* Access another loader's data, or WRITE handle data (meta, breadcrumbs, …)
|
|
56
|
+
* — handler parity: `ctx.use(Meta)({ title })` pushes exactly like it does
|
|
57
|
+
* in a handler. Handle READS live on `ctx.get(handle)` (after rendered()).
|
|
49
58
|
*
|
|
50
59
|
* For loaders: returns a promise (loaders run in parallel).
|
|
51
|
-
* For handles: returns
|
|
60
|
+
* For handles: returns the push function, legal for the whole body,
|
|
61
|
+
* streaming loaders included. Delivery is async by the race model: pushes
|
|
62
|
+
* that settle before the handler barrier ride the SSR handle snapshot;
|
|
63
|
+
* later ones stream to the client and apply post-hydration (document lane)
|
|
64
|
+
* or progressively (navigation/action lanes). To guarantee a loader's
|
|
65
|
+
* handles are in the SSR'd document, register it as
|
|
66
|
+
* `loader(Def, { stream: "navigation" })` so the document render awaits it
|
|
67
|
+
* (see {@link LoaderOptions}).
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* export const ProductLoader = createLoader(async (ctx) => {
|
|
72
|
+
* "use server";
|
|
73
|
+
* const product = await getProduct(ctx.params.slug);
|
|
74
|
+
* ctx.use(Meta)({ title: product.name });
|
|
75
|
+
* ctx.use(Breadcrumbs)({ label: product.name });
|
|
76
|
+
* return product;
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
52
79
|
*/
|
|
53
80
|
use: {
|
|
54
81
|
<T, TLoaderParams = any>(loader: LoaderDefinition<T, TLoaderParams>): Promise<T>;
|
|
55
|
-
<TData, TAccumulated = TData[]>(handle: Handle<TData, TAccumulated>):
|
|
82
|
+
<TData, TAccumulated = TData[]>(handle: Handle<TData, TAccumulated>): HandlePush<TData>;
|
|
56
83
|
};
|
|
57
84
|
/**
|
|
58
85
|
* **Experimental.** Wait for all non-loader segments to settle.
|
|
59
86
|
*
|
|
60
87
|
* After the returned promise resolves, handle data is available via
|
|
61
|
-
* `ctx.
|
|
88
|
+
* `ctx.get(handle)`. Supported in DSL loaders, including on streaming
|
|
62
89
|
* trees that use `loading()` — the barrier waits for the streaming
|
|
63
90
|
* handlers to finish pushing before it resolves. Throws if called from a
|
|
64
91
|
* handler-invoked loader, or if a handler is already awaiting this loader
|
|
@@ -70,7 +97,7 @@ export type LoaderContext<TParams = Record<string, string | undefined>, TEnv = D
|
|
|
70
97
|
* const PricesLoader = createLoader(async (ctx) => {
|
|
71
98
|
* "use server";
|
|
72
99
|
* await ctx.rendered();
|
|
73
|
-
* const products = ctx.
|
|
100
|
+
* const products = ctx.get(Products); // reads handle data
|
|
74
101
|
* return pricing.getLive(products.map(p => p.id));
|
|
75
102
|
* });
|
|
76
103
|
* ```
|
|
@@ -121,6 +148,31 @@ export type LoaderContext<TParams = Record<string, string | undefined>, TEnv = D
|
|
|
121
148
|
* ```
|
|
122
149
|
*/
|
|
123
150
|
export type LoaderFn<T, TParams = Record<string, string | undefined>, TEnv = DefaultEnv> = (ctx: LoaderContext<TParams, TEnv>) => Promise<T> | T;
|
|
151
|
+
/**
|
|
152
|
+
* Delivery mode for a DSL-registered loader: `loader(Def, { stream })`.
|
|
153
|
+
*
|
|
154
|
+
* Default (omitted): the loader streams on every render. Its data, its
|
|
155
|
+
* `ctx.use(Handle)` pushes, and any `notFound()`/`redirect()` it throws may land
|
|
156
|
+
* AFTER the document Response is constructed, so none of them are guaranteed to
|
|
157
|
+
* be in the SSR'd HTML.
|
|
158
|
+
*
|
|
159
|
+
* `"navigation"` narrows streaming to client navigations only: on a DOCUMENT
|
|
160
|
+
* request the loader is awaited before first flush. `useLoader` still suspends,
|
|
161
|
+
* but on an already-settled promise, so no fallback paints. This is the
|
|
162
|
+
* SSR-completeness opt-in — the name is about WHERE streaming still applies, not
|
|
163
|
+
* about disabling it. Choose it when the loader feeds something that must exist
|
|
164
|
+
* in the document: `<head>` meta via a handle, or a real 404 status (an awaited
|
|
165
|
+
* `notFound()` deterministically precedes Response construction, where the
|
|
166
|
+
* streamed default only wins that race opportunistically). It does NOT change
|
|
167
|
+
* PPR capture behavior: capture renders mask loaders and skip this await.
|
|
168
|
+
*
|
|
169
|
+
* Scoped per LOADER, not per segment: a baked loader alongside a deliberately
|
|
170
|
+
* dynamic sibling awaits only itself, and the sibling keeps streaming behind its
|
|
171
|
+
* `loading()`/Suspense boundary.
|
|
172
|
+
*/
|
|
173
|
+
export type LoaderOptions = {
|
|
174
|
+
stream?: "navigation";
|
|
175
|
+
};
|
|
124
176
|
/**
|
|
125
177
|
* Options for fetchable loaders
|
|
126
178
|
*
|
|
@@ -221,6 +221,13 @@ export interface MatchResult {
|
|
|
221
221
|
* Slots are used for intercepting routes during soft navigation
|
|
222
222
|
*/
|
|
223
223
|
slots?: Record<string, SlotState>;
|
|
224
|
+
/**
|
|
225
|
+
* Intercept TARGET route names reachable when this location is a navigation
|
|
226
|
+
* origin (chain walk of the matched entry, when-conditionals included).
|
|
227
|
+
* Shipped in payload metadata so the browser-local clientUrls matcher can
|
|
228
|
+
* decline its optimistic presentation for targets an intercept would claim.
|
|
229
|
+
*/
|
|
230
|
+
interceptTargets?: string[];
|
|
224
231
|
/**
|
|
225
232
|
* Redirect URL for trailing slash normalization.
|
|
226
233
|
* When set, the RSC handler should return a 308 redirect to this URL
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
import type { ErrorBoundaryHandler, ExtractParams, Handler, HandlerContext, LoaderDefinition, MiddlewareFn, NotFoundBoundaryHandler, PartialCacheOptions, ShouldRevalidateFn, TransitionConfig } from "../types.js";
|
|
2
|
+
import type { ErrorBoundaryHandler, ExtractParams, Handler, HandlerContext, LoaderDefinition, LoaderOptions, MiddlewareFn, NotFoundBoundaryHandler, PartialCacheOptions, ShouldRevalidateFn, TransitionConfig } from "../types.js";
|
|
3
3
|
import type { AllUseItems, TypedLayoutItem, ParallelItem, InterceptItem, MiddlewareItem, RevalidateItem, LoaderItem, LoadingItem, ErrorBoundaryItem, NotFoundBoundaryItem, LayoutUseItem, RouteUseItem, ResponseRouteUseItem, ParallelUseItem, InterceptUseItem, LoaderUseItem, TypedCacheItem, TransitionItem, TypedTransitionItem, TypedRouteItem, TypedIncludeItem, UseItems } from "../route-types.js";
|
|
4
4
|
import type { SearchSchema } from "../search-params.js";
|
|
5
5
|
import type { PrerenderHandlerDefinition, PassthroughHandlerDefinition } from "../prerender.js";
|
|
@@ -7,6 +7,7 @@ import type { StaticHandlerDefinition, StaticHandlerRef } from "../static-handle
|
|
|
7
7
|
import type { ResponseHandler, ResponseHandlerContext, TextResponseHandler } from "./response-types.js";
|
|
8
8
|
import type { UnnamedRoute, LocalOnlyInclude, PathOptions, UrlPatterns, IncludeOptions } from "./pattern-types.js";
|
|
9
9
|
import type { ExtractRoutes, ExtractResponses } from "./type-extraction.js";
|
|
10
|
+
import type { ClientUrlPatterns } from "../client-urls/types.js";
|
|
10
11
|
/**
|
|
11
12
|
* Base path function signature for defining routes with URL patterns.
|
|
12
13
|
*/
|
|
@@ -45,7 +46,7 @@ type IncludeResolved<TEnv, TRoutes extends Record<string, any>, TResponses exten
|
|
|
45
46
|
default: UrlPatterns<TEnv, TRoutes, TResponses>;
|
|
46
47
|
};
|
|
47
48
|
/** include() argument: an eager `urls()` value or an async provider thunk. */
|
|
48
|
-
export type IncludeArg<TEnv, TRoutes extends Record<string, any>, TResponses extends Record<string, unknown>> = UrlPatterns<TEnv, TRoutes, TResponses> | (() => IncludeResolved<TEnv, TRoutes, TResponses> | Promise<IncludeResolved<TEnv, TRoutes, TResponses>>);
|
|
49
|
+
export type IncludeArg<TEnv, TRoutes extends Record<string, any>, TResponses extends Record<string, unknown>> = UrlPatterns<TEnv, TRoutes, TResponses> | ClientUrlPatterns<TRoutes> | (() => IncludeResolved<TEnv, TRoutes, TResponses> | Promise<IncludeResolved<TEnv, TRoutes, TResponses>>);
|
|
49
50
|
/**
|
|
50
51
|
* Base include function signature.
|
|
51
52
|
*/
|
|
@@ -145,9 +146,14 @@ export type PathHelpers<TEnv> = {
|
|
|
145
146
|
*/
|
|
146
147
|
revalidate: (fn: ShouldRevalidateFn<any, TEnv>) => RevalidateItem;
|
|
147
148
|
/**
|
|
148
|
-
* Attach a data loader to the current route/layout
|
|
149
|
+
* Attach a data loader to the current route/layout.
|
|
150
|
+
*
|
|
151
|
+
* Pass `{ stream: "navigation" }` to await this loader before first flush
|
|
152
|
+
* on DOCUMENT requests (see {@link LoaderOptions}) — the opt-in for loaders
|
|
153
|
+
* whose data, handle pushes, or thrown notFound()/redirect() must be in the
|
|
154
|
+
* SSR'd HTML. Per-loader: a dynamic sibling keeps streaming.
|
|
149
155
|
*/
|
|
150
|
-
loader: <TData>(loaderDef: LoaderDefinition<TData>, use?: () => LoaderUseItem[]) => LoaderItem;
|
|
156
|
+
loader: <TData>(loaderDef: LoaderDefinition<TData>, optionsOrUse?: LoaderOptions | (() => LoaderUseItem[]), use?: () => LoaderUseItem[]) => LoaderItem;
|
|
151
157
|
/**
|
|
152
158
|
* Attach a loading component to the current route/layout
|
|
153
159
|
*/
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type ClientUrlProjection } from "../../client-urls/server-projection.js";
|
|
2
|
+
import type { DiscoveryState } from "./state.js";
|
|
3
|
+
interface ClientUrlSsrEnvironment {
|
|
4
|
+
readonly runner?: {
|
|
5
|
+
import(id: string): Promise<Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
interface ClientUrlProjectionServerModule {
|
|
9
|
+
clearClientUrlProjections(): void;
|
|
10
|
+
setClientUrlProjection(referenceId: string, projection: ClientUrlProjection): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function recordClientUrlsModule(state: DiscoveryState, code: string, id: string): void;
|
|
13
|
+
export declare function resolveClientUrlsSource(state: DiscoveryState, referenceId: string): string | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Deterministic filesystem discovery of clientUrls modules. Transform-based
|
|
16
|
+
* recording only sees modules that some environment actually loads — a
|
|
17
|
+
* clientUrls module not yet reachable from any transformed graph at discovery
|
|
18
|
+
* time (cold ordering, a mount added before its first import is served) would
|
|
19
|
+
* never be recorded and its include would fail with empty projections. Walking
|
|
20
|
+
* the project source (the same walk static route-type generation performs)
|
|
21
|
+
* makes recording independent of module-graph timing. The transform hooks
|
|
22
|
+
* still record too — they refresh dev HMR edits between scans.
|
|
23
|
+
*/
|
|
24
|
+
export declare function scanForClientUrlModules(state: DiscoveryState): void;
|
|
25
|
+
/**
|
|
26
|
+
* Lenient pre-entry projection refresh. Re-serializes every RECORDED clientUrls
|
|
27
|
+
* module before the discovery pass imports the entry, so routers re-created by
|
|
28
|
+
* that import materialize against the CURRENT module contents.
|
|
29
|
+
*
|
|
30
|
+
* Scar: node-preset HMR served stale client-urls routes after a route-shape
|
|
31
|
+
* edit — the clientUrls module is an HMR-accepted client boundary in the rsc
|
|
32
|
+
* graph, and the strict registry-driven pass below only runs AFTER the entry
|
|
33
|
+
* import, so `.routes(reference)` materialized the previous pass's projection.
|
|
34
|
+
*
|
|
35
|
+
* Errors are deliberately swallowed per source (a module mid-edit keeps its
|
|
36
|
+
* last-known projection); the strict discoverClientUrlProjections() pass still
|
|
37
|
+
* surfaces real failures afterwards. No-ops on cold start (nothing recorded
|
|
38
|
+
* yet) and when the SSR runner is unavailable.
|
|
39
|
+
*/
|
|
40
|
+
export declare function refreshRecordedClientUrlProjections(state: DiscoveryState, ssrEnv: ClientUrlSsrEnvironment | undefined, serverMod: ClientUrlProjectionServerModule): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Strict projection discovery over every RECORDED clientUrls module. Recorded
|
|
43
|
+
* modules — not router references — are the source of truth: include() mounts
|
|
44
|
+
* materialize lazily from the projection registry, so there is no router-level
|
|
45
|
+
* reference list to consult. Serializes every source before atomically
|
|
46
|
+
* installing the new projections (a failure preserves last-known state).
|
|
47
|
+
*
|
|
48
|
+
* A recorded source whose file no longer exists is dropped silently
|
|
49
|
+
* (recordClientUrlsModule never un-records, so deletions must self-heal here).
|
|
50
|
+
* A present-but-broken module is a hard error: it is part of the app graph.
|
|
51
|
+
*/
|
|
52
|
+
export declare function discoverClientUrlProjections(state: DiscoveryState, ssrEnv: ClientUrlSsrEnvironment | undefined, serverMod: ClientUrlProjectionServerModule): Promise<void>;
|
|
53
|
+
export {};
|
|
@@ -14,4 +14,4 @@ import type { DiscoveryState } from "./state.js";
|
|
|
14
14
|
* Returns the imported `@rangojs/router/server` module so the caller
|
|
15
15
|
* can access the RouterRegistry and manifest setters.
|
|
16
16
|
*/
|
|
17
|
-
export declare function discoverRouters(state: DiscoveryState, rscEnv: any): Promise<any>;
|
|
17
|
+
export declare function discoverRouters(state: DiscoveryState, rscEnv: any, ssrEnv?: any): Promise<any>;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* to all extracted helper functions.
|
|
7
7
|
*/
|
|
8
8
|
import type { ScanFilter } from "../../build/generate-route-types.js";
|
|
9
|
+
import type { ClientUrlProjection } from "../../client-urls/server-projection.js";
|
|
9
10
|
export declare const VIRTUAL_ROUTES_MANIFEST_ID = "virtual:rsc-router/routes-manifest";
|
|
10
11
|
export interface PluginOptions {
|
|
11
12
|
enableBuildPrerender?: boolean;
|
|
@@ -81,6 +82,10 @@ export interface ShellPrerenderCandidate {
|
|
|
81
82
|
captureTimeout?: number;
|
|
82
83
|
};
|
|
83
84
|
}
|
|
85
|
+
export interface ClientUrlDiscoveryState {
|
|
86
|
+
clientUrlSourceByReferenceId: Map<string, string>;
|
|
87
|
+
clientUrlProjectionMap: Map<string, ClientUrlProjection>;
|
|
88
|
+
}
|
|
84
89
|
export interface DiscoveryState {
|
|
85
90
|
resolvedEntryPath: string | undefined;
|
|
86
91
|
projectRoot: string;
|
|
@@ -107,6 +112,8 @@ export interface DiscoveryState {
|
|
|
107
112
|
perRouterTrieMap: Map<string, any>;
|
|
108
113
|
perRouterPrecomputedMap: Map<string, PrecomputedEntry[]>;
|
|
109
114
|
perRouterManifestDataMap: Map<string, Record<string, string>>;
|
|
115
|
+
clientUrlSourceByReferenceId?: Map<string, string>;
|
|
116
|
+
clientUrlProjectionMap?: Map<string, ClientUrlProjection>;
|
|
110
117
|
prerenderManifestEntries: Record<string, string> | null;
|
|
111
118
|
staticManifestEntries: Record<string, string> | null;
|
|
112
119
|
/**
|
|
@@ -160,4 +167,4 @@ export interface DiscoveryState {
|
|
|
160
167
|
at: number;
|
|
161
168
|
} | null;
|
|
162
169
|
}
|
|
163
|
-
export declare function createDiscoveryState(entryPath: string | undefined, opts: PluginOptions | undefined): DiscoveryState;
|
|
170
|
+
export declare function createDiscoveryState(entryPath: string | undefined, opts: PluginOptions | undefined): DiscoveryState & ClientUrlDiscoveryState;
|