@rangojs/router 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rango.js +8 -3
- package/dist/testing/vitest.js +31 -1
- package/dist/types/browser/defer.d.ts +48 -0
- package/dist/types/browser/document-revealed.d.ts +17 -0
- package/dist/types/browser/event-controller.d.ts +7 -1
- package/dist/types/browser/navigation-transaction.d.ts +21 -7
- package/dist/types/browser/partial-update.d.ts +34 -5
- package/dist/types/browser/react/NavigationProvider.d.ts +13 -3
- package/dist/types/browser/react/filter-segment-order.d.ts +7 -0
- package/dist/types/browser/response-adapter.d.ts +7 -0
- package/dist/types/browser/types.d.ts +19 -9
- package/dist/types/browser/validate-redirect-origin.d.ts +11 -0
- package/dist/types/build/generate-route-types.d.ts +1 -1
- package/dist/types/build/route-types/router-processing.d.ts +1 -1
- package/dist/types/build/route-types/scan-filter.d.ts +16 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +16 -1
- package/dist/types/cache/cf/cf-cache-types.d.ts +23 -2
- package/dist/types/client-urls/client-urls.d.ts +1 -1
- package/dist/types/client-urls/hoisted-revalidate.d.ts +13 -0
- package/dist/types/client-urls/navigation.d.ts +0 -37
- package/dist/types/client-urls/revalidate-registry.d.ts +4 -0
- package/dist/types/client-urls/server-projection.d.ts +29 -1
- package/dist/types/client-urls/types.d.ts +34 -69
- package/dist/types/client.d.ts +0 -1
- package/dist/types/errors.d.ts +5 -0
- package/dist/types/handles/deferred-resolution.d.ts +2 -1
- package/dist/types/handles/pushed-by.d.ts +23 -0
- package/dist/types/loader-store.d.ts +8 -0
- package/dist/types/prefetch-markers.d.ts +11 -0
- package/dist/types/route-definition/helpers-types.d.ts +27 -0
- package/dist/types/router/is-action.d.ts +2 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +3 -2
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +241 -0
- package/dist/types/server/context.d.ts +21 -1
- package/dist/types/server/handle-store.d.ts +9 -1
- package/dist/types/server/request-context.d.ts +14 -1
- package/dist/types/server.d.ts +1 -0
- package/dist/types/testing/flight.entry.d.ts +1 -1
- package/dist/types/testing/index.d.ts +3 -3
- package/dist/types/testing/internal/action-id.d.ts +10 -1
- package/dist/types/testing/internal/client-urls-projection.d.ts +16 -0
- package/dist/types/testing/internal/test-action.d.ts +8 -0
- package/dist/types/testing/run-loader.d.ts +2 -1
- package/dist/types/testing/run-revalidate.d.ts +74 -0
- package/dist/types/testing/run-transition-when.d.ts +2 -3
- package/dist/types/testing/serve-shell-request.d.ts +38 -0
- package/dist/types/testing/vitest.d.ts +11 -0
- package/dist/types/types/boundaries.d.ts +9 -0
- package/dist/types/types/handler-context.d.ts +14 -0
- package/dist/types/types/loader-types.d.ts +30 -0
- package/dist/types/types/segments.d.ts +21 -4
- package/dist/types/urls/path-helper-types.d.ts +25 -4
- package/dist/types/urls/type-extraction.d.ts +6 -2
- package/dist/types/vite/discovery/discover-routers.d.ts +9 -0
- package/dist/types/vite/discovery/state.d.ts +11 -4
- package/dist/types/vite/plugins/client-urls-revalidate-hoist.d.ts +54 -0
- package/dist/types/vite/plugins/hoist/literal.d.ts +83 -0
- package/dist/types/vite/plugins/hoist/scope.d.ts +40 -0
- package/dist/types/vite/plugins/hoist/source.d.ts +41 -0
- package/dist/types/vite/plugins/transition-when-hoist.d.ts +8 -11
- package/dist/types/vite/router-discovery.d.ts +10 -0
- package/dist/vite/index.js +842 -308
- package/package.json +1 -1
- package/skills/caching/SKILL.md +42 -5
- package/skills/catalog.json +2 -2
- package/skills/client-urls/SKILL.md +113 -24
- package/skills/cloudflare/SKILL.md +14 -9
- package/skills/hooks/SKILL.md +11 -3
- package/skills/links/SKILL.md +24 -0
- package/skills/loader/SKILL.md +192 -1
- package/skills/migrate-nextjs/SKILL.md +2 -2
- package/skills/migrate-react-router/SKILL.md +10 -7
- package/skills/migrate-react-router/data-and-actions.md +1 -1
- package/skills/ppr/SKILL.md +13 -0
- package/skills/prerender/SKILL.md +22 -8
- package/skills/rango/SKILL.md +12 -6
- package/skills/route/SKILL.md +139 -0
- package/skills/testing/SKILL.md +3 -2
- package/skills/testing/client-components.md +1 -1
- package/skills/testing/predicates.md +67 -32
- package/skills/testing/serve-shell-request.md +88 -18
- package/skills/testing/setup.md +2 -2
- package/skills/typesafety/route-types.md +2 -2
- package/skills/view-transitions/SKILL.md +26 -0
- package/src/browser/defer.ts +82 -0
- package/src/browser/document-revealed.ts +52 -0
- package/src/browser/event-controller.ts +43 -32
- package/src/browser/navigation-bridge.ts +64 -14
- package/src/browser/navigation-client.ts +48 -36
- package/src/browser/navigation-store.ts +13 -0
- package/src/browser/navigation-transaction.ts +25 -8
- package/src/browser/partial-update.ts +528 -135
- package/src/browser/prefetch/fetch.ts +2 -1
- package/src/browser/react/NavigationProvider.tsx +47 -28
- package/src/browser/react/filter-segment-order.ts +13 -2
- package/src/browser/response-adapter.ts +20 -0
- package/src/browser/rsc-router.tsx +17 -45
- package/src/browser/server-action-bridge.ts +19 -63
- package/src/browser/types.ts +19 -9
- package/src/browser/validate-redirect-origin.ts +16 -0
- package/src/build/generate-route-types.ts +1 -0
- package/src/build/route-types/router-processing.ts +3 -6
- package/src/build/route-types/scan-filter.ts +37 -10
- package/src/cache/cf/cf-cache-store.ts +59 -21
- package/src/cache/cf/cf-cache-types.ts +24 -2
- package/src/cache/document-cache.ts +22 -1
- package/src/client-urls/client-urls.ts +22 -6
- package/src/client-urls/hoisted-revalidate.ts +25 -0
- package/src/client-urls/navigation.ts +0 -96
- package/src/client-urls/revalidate-registry.ts +30 -0
- package/src/client-urls/server-projection.ts +151 -65
- package/src/client-urls/types.ts +39 -71
- package/src/client.tsx +9 -5
- package/src/errors.ts +15 -0
- package/src/handles/deferred-resolution.ts +28 -5
- package/src/handles/pushed-by.ts +122 -0
- package/src/loader-store.ts +18 -7
- package/src/prefetch-markers.ts +13 -0
- package/src/route-content-wrapper.tsx +18 -4
- package/src/route-definition/dsl-helpers.ts +27 -4
- package/src/route-definition/helpers-types.ts +27 -1
- package/src/router/intercept-resolution.ts +6 -4
- package/src/router/is-action.ts +2 -1
- package/src/router/loader-resolution.ts +83 -4
- package/src/router/match-api.ts +36 -1
- package/src/router/match-middleware/background-revalidation.ts +11 -1
- package/src/router/match-middleware/cache-lookup.ts +29 -6
- package/src/router/match-middleware/cache-store.ts +17 -1
- package/src/router/match-result.ts +14 -2
- package/src/router/navigation-snapshot.ts +2 -1
- package/src/router/segment-resolution/fresh.ts +22 -18
- package/src/router/segment-resolution/loader-cache.ts +2 -1
- package/src/router/segment-resolution/loader-mask.ts +5 -3
- package/src/router/segment-resolution/prefetch-deferral.ts +543 -0
- package/src/router/segment-resolution/revalidation.ts +169 -60
- package/src/rsc/rsc-rendering.ts +50 -7
- package/src/rsc/shell-capture.ts +2 -1
- package/src/segment-loader-promise.ts +23 -20
- package/src/segment-system.tsx +60 -26
- package/src/server/context.ts +39 -5
- package/src/server/handle-store.ts +104 -8
- package/src/server/request-context.ts +21 -1
- package/src/server.ts +4 -0
- package/src/testing/action-form.ts +2 -11
- package/src/testing/e2e/page-helpers.ts +3 -1
- package/src/testing/flight.entry.ts +1 -0
- package/src/testing/index.ts +6 -3
- package/src/testing/internal/action-id.ts +16 -1
- package/src/testing/internal/client-urls-projection.ts +70 -0
- package/src/testing/internal/test-action.ts +25 -0
- package/src/testing/run-loader.ts +2 -1
- package/src/testing/run-revalidate.ts +142 -0
- package/src/testing/run-transition-when.ts +7 -8
- package/src/testing/serve-shell-request.ts +116 -6
- package/src/testing/vitest.ts +67 -1
- package/src/types/boundaries.ts +12 -0
- package/src/types/handler-context.ts +14 -0
- package/src/types/loader-types.ts +30 -0
- package/src/types/segments.ts +26 -4
- package/src/urls/path-helper-types.ts +27 -5
- package/src/urls/type-extraction.ts +30 -10
- package/src/use-loader.tsx +18 -13
- package/src/vite/discovery/client-urls-projection.ts +20 -21
- package/src/vite/discovery/discover-routers.ts +94 -26
- package/src/vite/discovery/state.ts +20 -4
- package/src/vite/discovery/virtual-module-codegen.ts +22 -17
- package/src/vite/plugins/client-urls-revalidate-hoist.ts +564 -0
- package/src/vite/plugins/hoist/literal.ts +417 -0
- package/src/vite/plugins/hoist/scope.ts +370 -0
- package/src/vite/plugins/hoist/source.ts +84 -0
- package/src/vite/plugins/transition-when-hoist.ts +113 -779
- package/src/vite/rango.ts +2 -0
- package/src/vite/router-discovery.ts +93 -32
- package/dist/types/client-urls/revalidate-chain.d.ts +0 -33
- package/dist/types/client-urls/revalidation-protocol.d.ts +0 -25
- package/dist/types/testing/run-client-revalidate.d.ts +0 -43
- package/src/client-urls/revalidate-chain.ts +0 -83
- package/src/client-urls/revalidation-protocol.ts +0 -56
- package/src/testing/run-client-revalidate.ts +0 -92
|
@@ -587,6 +587,19 @@ export interface RequestContext<TEnv = DefaultEnv, TParams = Record<string, stri
|
|
|
587
587
|
* document cache does not store that response (#978).
|
|
588
588
|
*/
|
|
589
589
|
_payloadVisitorTheme?: boolean;
|
|
590
|
+
/**
|
|
591
|
+
* @internal Set by the partial render when its payload carries deferred
|
|
592
|
+
* units (`prefetch: false`): what one page's prefetch left for the fill.
|
|
593
|
+
* The document cache does not store that response, whatever Cache-Control
|
|
594
|
+
* it ends up with (docs/design/prefetch-false.md, R7).
|
|
595
|
+
*/
|
|
596
|
+
_payloadDeferred?: boolean;
|
|
597
|
+
/**
|
|
598
|
+
* @internal What the request says it is: a `<Link>` prefetch or a fill
|
|
599
|
+
* (`prefetch: false`), read once at creation
|
|
600
|
+
* (segment-resolution/prefetch-deferral.ts requestKind).
|
|
601
|
+
*/
|
|
602
|
+
_requestKind?: "prefetch" | "fill";
|
|
590
603
|
/**
|
|
591
604
|
* Attach location state entries to the current response.
|
|
592
605
|
*
|
|
@@ -803,7 +816,7 @@ export interface RouteRecordWindow {
|
|
|
803
816
|
* This is the type exported to library consumers. Internal code should
|
|
804
817
|
* use the full RequestContext interface directly.
|
|
805
818
|
*/
|
|
806
|
-
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureUnrecordedLoaderPush" | "_shellCaptureLoaderLanes" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_prerenderWarm" | "_runAtRequestEntry" | "_routeRecordWindow" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_locationState" | "_routeName" | "_prevRouteKey" | "_inActionRevalidation" | "_reportedErrors" | "_renderErrors" | "_recoveredHandlerErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
819
|
+
export type PublicRequestContext<TEnv = DefaultEnv, TParams = Record<string, string>> = Omit<RequestContext<TEnv, TParams>, "cookie" | "cookies" | "_readCookie" | "_readCookies" | "setCookie" | "deleteCookie" | "_handleStore" | "_transitionWhenRefs" | "_pprReplayPostMatchReason" | "_cacheStore" | "_prerender" | "_onDemandProducer" | "_searchParamsFilter" | "_shellCaptureRun" | "_shellImplicitCache" | "_shellLoaderSeed" | "_shellCaptureLoaderRecords" | "_shellCaptureUnrecordedLoaderPush" | "_shellCaptureLoaderLanes" | "_resolvedCacheKeys" | "_shellKey" | "_shellForcedMiss" | "_prerenderWarm" | "_runAtRequestEntry" | "_routeRecordWindow" | "_shellFragmentPayload" | "_shellCaptureGuardTripped" | "_shellCaptureGuardTrippedLoaderId" | "_explicitTaggedStores" | "_requestTags" | "_recordTagOwners" | "_recordLoaderTags" | "_cacheProfiles" | "_onResponseCallbacks" | "_pendingBackgroundTasks" | "_themeConfig" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "_payloadDeferred" | "_requestKind" | "_locationState" | "_routeName" | "_prevRouteKey" | "_inActionRevalidation" | "_reportedErrors" | "_renderErrors" | "_recoveredHandlerErrors" | "_renderBarrier" | "_resolveRenderBarrier" | "_renderBarrierSegmentOrder" | "_treeHasStreaming" | "_renderBarrierWaiters" | "_handlerLoaderDeps" | "_awaitBeforeFlushLoaderIds" | "_renderBarrierHandleSnapshot" | "_renderBarrierGuardClosed" | "_reportBackgroundError" | "_debugPerformance" | "_metricsStore" | "_renderForeground" | "_activeRoutine" | "_renderDiagnosticsEnabled" | "_handlerStart" | "_tracing" | "_basename" | "_routerId" | "_versions" | "_setStatus" | "_rotateStateCookie" | "_setKeepCacheDirective" | "_freshReads" | "_setFreshReadsCookie" | "_requestRoot" | "_requestStart" | "_responseSent" | "_variables" | "_classifiedRoute" | "_requestMode" | "_cacheSignal" | "_dynamic" | "res">;
|
|
807
820
|
/**
|
|
808
821
|
* Marker for a waitUntil-scheduled fn whose task promise must NOT enter
|
|
809
822
|
* _pendingBackgroundTasks. Used by the PPR shell capture for its own task:
|
package/dist/types/server.d.ts
CHANGED
|
@@ -15,3 +15,4 @@ export { createRequestContext, type CreateRequestContextOptions, } from "./serve
|
|
|
15
15
|
export { isClientComponent, assertClientComponent } from "./component-utils.js";
|
|
16
16
|
export { enableTransitionWhenValidation } from "./transition-when-ref.js";
|
|
17
17
|
export { clearClientUrlProjections, setClientUrlProjection, type ClientUrlProjection, } from "./client-urls/server-projection.js";
|
|
18
|
+
export { registerClientUrlRevalidators } from "./client-urls/revalidate-registry.js";
|
|
@@ -33,4 +33,4 @@ export type { TestableHandler, RenderHandlerOptions, RenderHandlerResult, StateC
|
|
|
33
33
|
export { createActionForm } from "./action-form.js";
|
|
34
34
|
export type { CreateActionFormOptions } from "./action-form.js";
|
|
35
35
|
export { serveShellRequest, resetShellTestState, } from "./serve-shell-request.js";
|
|
36
|
-
export type { ServeShellRequestOptions, ServeShellRequestResult, ShellRequestHandles, } from "./serve-shell-request.js";
|
|
36
|
+
export type { ServeShellRequestAction, ServeShellRequestOptions, ServeShellRequestResult, ShellRequestHandles, } from "./serve-shell-request.js";
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* condition and would throw if pulled into this barrel.
|
|
27
27
|
*
|
|
28
28
|
* Layers:
|
|
29
|
-
* - Unit: runMiddleware, runLoader,
|
|
29
|
+
* - Unit: runMiddleware, runLoader, runRevalidate, runTransitionWhen
|
|
30
30
|
* - Integration: dispatch (request -> Response)
|
|
31
31
|
* - Cross-cut: assertCacheStatus, assertShellStatus, assertGeneratedRoutesMatch
|
|
32
32
|
* - Component: see @rangojs/router/testing/dom (renderRoute)
|
|
@@ -39,8 +39,8 @@ export { runLoader, runLoaderResult } from "./run-loader.js";
|
|
|
39
39
|
export type { RunLoaderOptions, RunLoaderResult, UseResolver, TestLoaderContext, } from "./run-loader.js";
|
|
40
40
|
export { runTransitionWhen } from "./run-transition-when.js";
|
|
41
41
|
export type { RunTransitionWhenAction, RunTransitionWhenLocation, RunTransitionWhenOptions, RunTransitionWhenResult, } from "./run-transition-when.js";
|
|
42
|
-
export {
|
|
43
|
-
export type {
|
|
42
|
+
export { runRevalidate } from "./run-revalidate.js";
|
|
43
|
+
export type { RunRevalidateAction, RunRevalidateOptions, } from "./run-revalidate.js";
|
|
44
44
|
export { dispatch } from "./dispatch.js";
|
|
45
45
|
export type { DispatchOptions } from "./dispatch.js";
|
|
46
46
|
export { createMemoryPrerenderStore } from "../prerender/memory-prerender-store.js";
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
/** An imported server action, as a testing primitive's `action` option takes it. */
|
|
2
|
+
export type ImportedAction = (...args: never[]) => unknown;
|
|
3
|
+
/**
|
|
4
|
+
* Normalizes a testing primitive's `action` option: a bare imported action or
|
|
5
|
+
* actionId string becomes `{ ref }`; the object form passes through.
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeTestAction<T extends {
|
|
8
|
+
ref?: ImportedAction | string;
|
|
9
|
+
}>(action: ImportedAction | string | T | undefined): T | undefined;
|
|
1
10
|
/**
|
|
2
11
|
* The id a testing primitive's `action` option names: a single imported
|
|
3
12
|
* server action (its `$id ?? $$id`, as the action boundary derives it) or a
|
|
4
13
|
* raw actionId string. A function without either id throws, naming the
|
|
5
14
|
* primitive.
|
|
6
15
|
*/
|
|
7
|
-
export declare function resolveTestActionId(action:
|
|
16
|
+
export declare function resolveTestActionId(action: ImportedAction | string | undefined, primitive: string): string | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install the projection of a `"use client"` clientUrls() module under its
|
|
3
|
+
* client reference id, as discovery installs it for an app
|
|
4
|
+
* (discoverClientUrlProjections in vite/discovery/client-urls-projection.ts):
|
|
5
|
+
* the same projection step, into the same registry include() materializes
|
|
6
|
+
* from. rangoUseClientTransform (testing/vitest.ts) appends a call to every
|
|
7
|
+
* such module, passing the module's own source evaluated without the
|
|
8
|
+
* transform, so a router under test mounts the group with no setup.
|
|
9
|
+
*
|
|
10
|
+
* A Vitest project runs no hoist plugin, so the source's revalidate()
|
|
11
|
+
* predicates are plain functions. Each is registered under a key named for
|
|
12
|
+
* its reference, route and loader, as the plugin's generated module registers
|
|
13
|
+
* its own, and the projection carries the keys: materialization attaches them
|
|
14
|
+
* and the server runs them, as in an app.
|
|
15
|
+
*/
|
|
16
|
+
export declare function installClientUrlsProjection(referenceId: string, source: Readonly<Record<string, unknown>>): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register `action` under its reference id, `<module id>#<export name>`,
|
|
3
|
+
* tagged as a server reference like a built "use server" export so it keeps
|
|
4
|
+
* its `$$id`, where the plugin-rsc stub's decodeAction / loadServerAction
|
|
5
|
+
* resolve it. `primitive` names the caller in the error for a malformed id.
|
|
6
|
+
* Loads the react-server build: callers run under the react-server condition.
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerTestAction(action: (...args: any[]) => unknown, id: string, primitive: string): void;
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
* - `ctx.reverse()` throws unless `routeMap` is provided (it does NOT fall back
|
|
21
21
|
* to the global route map — that would leak whichever routes another test
|
|
22
22
|
* registered).
|
|
23
|
-
* - `ctx.
|
|
23
|
+
* - `ctx.get(handle)` follows the production rule: reading a handle before
|
|
24
24
|
* `await ctx.rendered()` throws (pass `rendered` to mock the barrier).
|
|
25
|
+
* `ctx.use(handle)` is the push and needs no barrier.
|
|
25
26
|
* - `use cache` functions only cache (and only fire their taint/profile guards)
|
|
26
27
|
* when a `cacheStore` is provided — without one, registerCachedFunction
|
|
27
28
|
* bypasses (it checks for a store first). Pass `cacheStore`/`cacheProfiles`
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runRevalidate — unit-test revalidate() predicates: a urls() segment's, or a
|
|
3
|
+
* clientUrls() loader's (which the build moves to the server, where it runs
|
|
4
|
+
* the same way).
|
|
5
|
+
*
|
|
6
|
+
* Evaluates the predicate(s) through the router's own evaluateRevalidation
|
|
7
|
+
* (router/revalidation.ts) inside a seeded request context: the default
|
|
8
|
+
* decision, the argument object, boolean short-circuit, soft-verdict
|
|
9
|
+
* threading and the fail-open on a throw are the production code paths, not
|
|
10
|
+
* a re-implementation. Pass an array to test a chain in declaration order.
|
|
11
|
+
*/
|
|
12
|
+
import type { ShouldRevalidateFn } from "../types.js";
|
|
13
|
+
import { type ImportedAction } from "./internal/action-id.js";
|
|
14
|
+
import type { VarsInit } from "./internal/seed-vars.js";
|
|
15
|
+
type RevalidateArgs = Parameters<ShouldRevalidateFn<any, any>>[0];
|
|
16
|
+
/** The action fields a predicate receives on an action request. */
|
|
17
|
+
export interface RunRevalidateAction {
|
|
18
|
+
/** The triggering action: an imported server action or its actionId. */
|
|
19
|
+
ref?: ImportedAction | string;
|
|
20
|
+
/** `actionResult`: the action's return value. */
|
|
21
|
+
result?: unknown;
|
|
22
|
+
/** `formData`: the action's FormData argument. */
|
|
23
|
+
formData?: FormData;
|
|
24
|
+
/** `actionUrl`. Defaults to `currentUrl`. */
|
|
25
|
+
url?: string | URL;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for {@link runRevalidate}. Defaults model a same-URL navigation
|
|
29
|
+
* with no action, for a route-owned loader segment.
|
|
30
|
+
*/
|
|
31
|
+
export interface RunRevalidateOptions<TEnv = any> {
|
|
32
|
+
/** The page being left. Defaults to `http://localhost/`. */
|
|
33
|
+
currentUrl?: string | URL;
|
|
34
|
+
/** The destination. Defaults to `currentUrl`. */
|
|
35
|
+
nextUrl?: string | URL;
|
|
36
|
+
currentParams?: Record<string, string>;
|
|
37
|
+
/** Defaults to `currentParams`. */
|
|
38
|
+
nextParams?: Record<string, string>;
|
|
39
|
+
/**
|
|
40
|
+
* The triggering action: an imported server action (id via
|
|
41
|
+
* `$id ?? $$id`), an actionId string, or `{ ref, result, formData, url }`.
|
|
42
|
+
* Makes the request a POST, as an action request is.
|
|
43
|
+
*/
|
|
44
|
+
action?: ImportedAction | string | RunRevalidateAction;
|
|
45
|
+
/** Overrides the request method (`POST` with `action`, else `GET`). */
|
|
46
|
+
method?: string;
|
|
47
|
+
/** The segment the predicate is attached to. Defaults to `"loader"`. */
|
|
48
|
+
segmentType?: RevalidateArgs["segmentType"];
|
|
49
|
+
/**
|
|
50
|
+
* The segment belongs to the matched route (a route's own loaders, a
|
|
51
|
+
* clientUrls() group loader). Defaults to true; false models a layout's
|
|
52
|
+
* loader, which a navigation keeps by default.
|
|
53
|
+
*/
|
|
54
|
+
belongsToRoute?: boolean;
|
|
55
|
+
/** `stale`: a history-entry background revalidation. */
|
|
56
|
+
stale?: boolean;
|
|
57
|
+
/** `toRouteName` (and `routeName`). */
|
|
58
|
+
routeName?: string;
|
|
59
|
+
/** `fromRouteName`. */
|
|
60
|
+
fromRouteName?: string;
|
|
61
|
+
/** Environment bindings of the seeded context. */
|
|
62
|
+
env?: TEnv;
|
|
63
|
+
/** Variables a middleware would have set, readable with `context.get()`. */
|
|
64
|
+
vars?: VarsInit;
|
|
65
|
+
/** `context`, in place of the seeded request context. */
|
|
66
|
+
context?: RevalidateArgs["context"];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Run one revalidate() predicate, or a chain in declaration order, the way
|
|
70
|
+
* the router does for a request. Resolves to the final decision: true
|
|
71
|
+
* re-runs the segment, false keeps the client's copy.
|
|
72
|
+
*/
|
|
73
|
+
export declare function runRevalidate<TEnv = any>(fn: ShouldRevalidateFn<any, TEnv> | readonly ShouldRevalidateFn<any, TEnv>[], opts?: RunRevalidateOptions<TEnv>): Promise<boolean>;
|
|
74
|
+
export {};
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Synchronous: a transition predicate returns a boolean and has no I/O.
|
|
13
13
|
*/
|
|
14
|
+
import { type ImportedAction } from "./internal/action-id.js";
|
|
14
15
|
import type { RouteLocation, TransitionConfig, TransitionWhenContext, TransitionWhenFn, TransitionWhenKind } from "../types/segments.js";
|
|
15
|
-
type ImportedAction = (...args: never[]) => unknown;
|
|
16
16
|
/** A navigation side: a URL, or a partial RouteLocation. */
|
|
17
17
|
export type RunTransitionWhenLocation = string | URL | (Partial<Omit<RouteLocation, "url">> & {
|
|
18
18
|
url?: string | URL;
|
|
@@ -35,7 +35,7 @@ export interface RunTransitionWhenOptions {
|
|
|
35
35
|
/** The destination. Defaults to `from`; always `from` for "action" and "revalidate". */
|
|
36
36
|
to?: RunTransitionWhenLocation;
|
|
37
37
|
/**
|
|
38
|
-
* The triggering action (like
|
|
38
|
+
* The triggering action (like runRevalidate's): an imported server
|
|
39
39
|
* action (id via `$id ?? $$id`), an actionId string, or
|
|
40
40
|
* `{ ref, formData, result, error }`.
|
|
41
41
|
*/
|
|
@@ -50,4 +50,3 @@ export interface RunTransitionWhenResult {
|
|
|
50
50
|
context: TransitionWhenContext;
|
|
51
51
|
}
|
|
52
52
|
export declare function runTransitionWhen(whenOrConfig: TransitionWhenFn | TransitionConfig, opts?: RunTransitionWhenOptions): RunTransitionWhenResult;
|
|
53
|
-
export {};
|
|
@@ -63,10 +63,19 @@ export interface ServeShellRequestOptions<TEnv = any> {
|
|
|
63
63
|
* of a document GET: from `from` (default `/`) with `segments` mounted
|
|
64
64
|
* (default none), advertising fragment passthrough. The replay decision is
|
|
65
65
|
* `result.replayStatus`.
|
|
66
|
+
*
|
|
67
|
+
* `prefetch: true` sends it as a `<Link>` prefetch does (the
|
|
68
|
+
* `X-Rango-Prefetch` header), so `prefetch: false` loaders and `loading()`
|
|
69
|
+
* entries are deferred: `result.readDeferred()` lists them. `fill: true`
|
|
70
|
+
* sends the request the browser follows an adopted prefetch with
|
|
71
|
+
* (`_rsc_fill`): pass the ids the prefetch delivered, without the deferred
|
|
72
|
+
* ones, as `segments`, and the same URL as `from`.
|
|
66
73
|
*/
|
|
67
74
|
partial?: true | {
|
|
68
75
|
from?: string;
|
|
69
76
|
segments?: readonly string[];
|
|
77
|
+
prefetch?: boolean;
|
|
78
|
+
fill?: boolean;
|
|
70
79
|
};
|
|
71
80
|
/**
|
|
72
81
|
* POST this form as a submit before hydration: the no-JS request the
|
|
@@ -76,6 +85,29 @@ export interface ServeShellRequestOptions<TEnv = any> {
|
|
|
76
85
|
* Not with `partial`.
|
|
77
86
|
*/
|
|
78
87
|
form?: FormData;
|
|
88
|
+
/**
|
|
89
|
+
* Send the request a JS server action call makes from the page at `url`:
|
|
90
|
+
* a POST of `args` (encoded as the browser encodes them) for `ref`, with
|
|
91
|
+
* the page's mounted `segments` (default none), as
|
|
92
|
+
* browser/server-action-bridge.ts sends it. The response is the action's
|
|
93
|
+
* Flight payload (its return value and the re-rendered segments).
|
|
94
|
+
* Not with `partial` or `form`.
|
|
95
|
+
*/
|
|
96
|
+
action?: ServeShellRequestAction;
|
|
97
|
+
}
|
|
98
|
+
/** The JS server action call of {@link ServeShellRequestOptions.action}. */
|
|
99
|
+
export interface ServeShellRequestAction {
|
|
100
|
+
/** The server action. */
|
|
101
|
+
ref: (...args: any[]) => unknown;
|
|
102
|
+
/**
|
|
103
|
+
* Its reference id, `<module id>#<export name>`, as the build gives a
|
|
104
|
+
* "use server" export; registered so the handler loads `ref` by it.
|
|
105
|
+
*/
|
|
106
|
+
id: string;
|
|
107
|
+
/** The arguments the page calls it with. */
|
|
108
|
+
args?: readonly unknown[];
|
|
109
|
+
/** The segment ids the page holds (`_rsc_segments`). */
|
|
110
|
+
segments?: readonly string[];
|
|
79
111
|
}
|
|
80
112
|
/** A response's handle data, as the browser consumes it. */
|
|
81
113
|
export interface ShellRequestHandles {
|
|
@@ -133,6 +165,12 @@ export interface ServeShellRequestResult {
|
|
|
133
165
|
* values resolved. Undefined when no Flight was rendered.
|
|
134
166
|
*/
|
|
135
167
|
readHandles(): Promise<ShellRequestHandles | undefined>;
|
|
168
|
+
/**
|
|
169
|
+
* The ids of the segments `flight` marks deferred (a prefetch skipped
|
|
170
|
+
* them; the fill request renders them), in payload order. Empty when
|
|
171
|
+
* nothing was deferred, undefined when no Flight was rendered.
|
|
172
|
+
*/
|
|
173
|
+
readDeferred(): Promise<string[] | undefined>;
|
|
136
174
|
/**
|
|
137
175
|
* The form state the SSR render received (the `formState` render option),
|
|
138
176
|
* or undefined when it received none.
|
|
@@ -146,6 +146,10 @@ export declare function rangoTestConfig(opts?: RangoTestAliasOptions): RangoTest
|
|
|
146
146
|
/** A minimal Vite plugin shape (avoids a hard dependency on Vite's types). */
|
|
147
147
|
interface FlightTransformPlugin {
|
|
148
148
|
name: string;
|
|
149
|
+
resolveId: {
|
|
150
|
+
order: "pre";
|
|
151
|
+
handler(source: string, importer: string | undefined): string | undefined;
|
|
152
|
+
};
|
|
149
153
|
transform(code: string, id: string): Promise<{
|
|
150
154
|
code: string;
|
|
151
155
|
map: unknown;
|
|
@@ -202,6 +206,13 @@ interface FlightTransformPlugin {
|
|
|
202
206
|
* by the module's absolute path (the boundary id), the export name becoming the
|
|
203
207
|
* boundary name. Modules without the directive (server components) are untouched,
|
|
204
208
|
* so `renderToFlightString` of pure leaf trees is unaffected.
|
|
209
|
+
*
|
|
210
|
+
* A `"use client"` module whose default export is a `clientUrls()` definition
|
|
211
|
+
* also installs its server projection, as the rango plugin's discovery does for
|
|
212
|
+
* an app: the module imports its own source without this transform and projects
|
|
213
|
+
* it under its client reference. A router that mounts the group
|
|
214
|
+
* (`include("/shop", shopUrls)` or `.routes(shopUrls)`) then serves its routes
|
|
215
|
+
* through `serveShellRequest` and `dispatch` with no setup.
|
|
205
216
|
*/
|
|
206
217
|
export declare function rangoUseClientTransform(): FlightTransformPlugin;
|
|
207
218
|
/** The Vite plugin shape {@link rangoUseCacheTransform} returns. */
|
|
@@ -87,6 +87,15 @@ export type LoaderDataResult<T = unknown> = {
|
|
|
87
87
|
};
|
|
88
88
|
};
|
|
89
89
|
export declare function isLoaderDataResult(value: unknown): value is LoaderDataResult;
|
|
90
|
+
/**
|
|
91
|
+
* A loading skeleton is renderable only when it is a real ReactNode value;
|
|
92
|
+
* `false` counts as "not renderable". This is the three-term gate. The
|
|
93
|
+
* distinct two-term gate at the LoaderBoundary site (segment-system.tsx)
|
|
94
|
+
* deliberately treats `false` as "create a boundary without a
|
|
95
|
+
* RouteContentWrapper" (tree-structure.md), so it must NOT use this helper.
|
|
96
|
+
* Leaf module: shared by client (segment-system) and server (DSL, resolution).
|
|
97
|
+
*/
|
|
98
|
+
export declare function isRenderableLoading(loading: unknown): boolean;
|
|
90
99
|
export interface NotFoundInfo {
|
|
91
100
|
message: string;
|
|
92
101
|
segmentId: string;
|
|
@@ -372,6 +372,20 @@ export type InternalHandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch exte
|
|
|
372
372
|
* setupLoaderAccess.
|
|
373
373
|
*/
|
|
374
374
|
_bindLoaderCacheTags?: (loaderId: string, tags: Set<string>) => void;
|
|
375
|
+
/**
|
|
376
|
+
* @internal This match's `prefetch: false` plan: what a prefetch defers,
|
|
377
|
+
* whether the request is a fill, and the loaders that cannot call
|
|
378
|
+
* ctx.rendered(). Set by match-api.ts when the tree declares a flag or the
|
|
379
|
+
* request is a fill. See router/segment-resolution/prefetch-deferral.ts.
|
|
380
|
+
*/
|
|
381
|
+
_prefetchDeferral?: import("../router/segment-resolution/prefetch-deferral.js").PrefetchDeferral;
|
|
382
|
+
/**
|
|
383
|
+
* @internal Whether a loader was started in this request: a run of it (a
|
|
384
|
+
* handler's or another loader's ctx.use()) or its cache() binding. A
|
|
385
|
+
* prefetch delivers such a loader instead of deferring it. See
|
|
386
|
+
* setupLoaderAccess.
|
|
387
|
+
*/
|
|
388
|
+
_loaderStarted?: (loaderId: string) => boolean;
|
|
375
389
|
};
|
|
376
390
|
/**
|
|
377
391
|
* Generic params type - flexible object with string keys
|
|
@@ -175,6 +175,36 @@ export type LoaderFn<T, TParams = Record<string, string | undefined>, TEnv = Def
|
|
|
175
175
|
*/
|
|
176
176
|
export type LoaderOptions = {
|
|
177
177
|
ssr?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* `prefetch: false` keeps this loader out of prefetches. A `<Link>`
|
|
180
|
+
* prefetch (a partial request with `X-Rango-Prefetch`) does not execute it;
|
|
181
|
+
* the payload marks it deferred. A document request and a navigation with
|
|
182
|
+
* no prefetch to adopt run it as usual.
|
|
183
|
+
*
|
|
184
|
+
* A deferred loader never blocks the navigation that adopts the prefetch:
|
|
185
|
+
* it behaves like a loader that is still streaming. Its own `<Suspense>`
|
|
186
|
+
* shows at once; if the nearest boundary is the route's `loading()`, that
|
|
187
|
+
* shows; with no boundary React holds the page until the fill returns. The
|
|
188
|
+
* fill is the one follow-up request that runs the loader.
|
|
189
|
+
*
|
|
190
|
+
* The fill reads through the loader's own `cache()` and any `"use cache"`
|
|
191
|
+
* function it calls. A prefetch reads neither, by intent: looking would
|
|
192
|
+
* mean running the loader on a miss.
|
|
193
|
+
*
|
|
194
|
+
* The flag applies only to a segment the client does not have yet. A
|
|
195
|
+
* loader the client already holds (the same route with new params, say)
|
|
196
|
+
* runs in the prefetch when it revalidates, exactly as without the flag:
|
|
197
|
+
* a click that adopts a prefetch is never worse than the same click with
|
|
198
|
+
* no prefetch at all.
|
|
199
|
+
*
|
|
200
|
+
* Limits: a handler that awaits the loader with `ctx.use()` makes it run in
|
|
201
|
+
* the prefetch anyway; the loader cannot call `ctx.rendered()` (it throws
|
|
202
|
+
* on every request); on a `ppr` route the flag is ignored for an
|
|
203
|
+
* `ssr: false` loader (the bake lane), with a dev warning. In the fill
|
|
204
|
+
* request only deferred work and middleware run, so values a held handler
|
|
205
|
+
* would have set with `ctx.set()` are not visible.
|
|
206
|
+
*/
|
|
207
|
+
prefetch?: boolean;
|
|
178
208
|
};
|
|
179
209
|
/**
|
|
180
210
|
* Options for fetchable loaders
|
|
@@ -158,6 +158,15 @@ export interface ResolvedSegment {
|
|
|
158
158
|
*/
|
|
159
159
|
awaitBeforeFlush?: true;
|
|
160
160
|
parallelLoading?: ReactNode;
|
|
161
|
+
/**
|
|
162
|
+
* A prefetch skipped this segment's work (`prefetch: false`): a loader
|
|
163
|
+
* carries no `loaderData`, a layout/route/parallel unit carries
|
|
164
|
+
* `component: null` and its fallback. The browser shows the fallback and
|
|
165
|
+
* sends a fill request for it (browser/partial-update.ts); until that
|
|
166
|
+
* lands the segment is a placeholder, never a held copy. Only ever on a
|
|
167
|
+
* prefetch response: see docs/design/prefetch-false.md.
|
|
168
|
+
*/
|
|
169
|
+
deferred?: true;
|
|
161
170
|
loaderDataPromise?: Promise<any[]> | any[];
|
|
162
171
|
loaderIds?: string[];
|
|
163
172
|
/**
|
|
@@ -228,10 +237,12 @@ export interface MatchResult {
|
|
|
228
237
|
/**
|
|
229
238
|
* Every segment id whose handler actually ran on the server this request,
|
|
230
239
|
* including ones with `component === null` that get filtered out of
|
|
231
|
-
* `segments`/`diff` to avoid wasted bytes
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
240
|
+
* `segments`/`diff` to avoid wasted bytes, and every loader segment that
|
|
241
|
+
* ran. Drives the client's handle merge (handles/pushed-by.ts) — a slot
|
|
242
|
+
* that re-resolves and pushes nothing must clear its previous handle
|
|
243
|
+
* bucket, but `diff` doesn't carry it because the segment payload doesn't
|
|
244
|
+
* either; a loader that ran replaces its pushes, one that did not keeps
|
|
245
|
+
* them. A superset of `diff`.
|
|
235
246
|
*/
|
|
236
247
|
resolvedIds: string[];
|
|
237
248
|
/**
|
|
@@ -279,3 +290,9 @@ export interface MatchResult {
|
|
|
279
290
|
params: Record<string, string>;
|
|
280
291
|
}>;
|
|
281
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* A `prefetch: false` placeholder (ResolvedSegment.deferred): a segment whose
|
|
295
|
+
* work a prefetch skipped, waiting for its fill. Never a held copy of the
|
|
296
|
+
* segment it stands for.
|
|
297
|
+
*/
|
|
298
|
+
export declare function isPlaceholder(segment: Pick<ResolvedSegment, "deferred">): boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { ErrorBoundaryHandler, ExtractParams, Handler, HandlerContext, LoaderDefinition, LoaderOptions, MiddlewareFn, NotFoundBoundaryHandler, PartialCacheOptions, ShouldRevalidateFn, TransitionConfig } from "../types.js";
|
|
3
|
-
import type { AllUseItems, TypedLayoutItem, ParallelItem, InterceptItem, MiddlewareItem, RevalidateItem, LoaderItem, LoadingItem, ErrorBoundaryItem, NotFoundBoundaryItem, LayoutUseItem, RouteUseItem, ResponseRouteUseItem, ParallelUseItem, InterceptUseItem, LoaderUseItem, TypedCacheItem,
|
|
3
|
+
import type { AllUseItems, TypedLayoutItem, ParallelItem, InterceptItem, MiddlewareItem, RevalidateItem, LoaderItem, LoadingItem, ErrorBoundaryItem, NotFoundBoundaryItem, LayoutUseItem, RouteUseItem, ResponseRouteUseItem, ParallelUseItem, InterceptUseItem, LoaderUseItem, TypedCacheItem, 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";
|
|
6
6
|
import type { StaticHandlerDefinition, StaticHandlerRef } from "../static-handler.js";
|
|
@@ -158,13 +158,34 @@ export type PathHelpers<TEnv> = {
|
|
|
158
158
|
* flag BAKES: the loader executes at shell capture and its settled return
|
|
159
159
|
* freezes into the shell (nested promises stay live holes) — the pre-flush
|
|
160
160
|
* promise applied to the prelude.
|
|
161
|
+
*
|
|
162
|
+
* Pass `{ prefetch: false }` to keep the loader out of prefetches: a
|
|
163
|
+
* prefetch skips it and the click that adopts the prefetch fetches it in
|
|
164
|
+
* one follow-up request (see {@link LoaderOptions}). Only on a segment the
|
|
165
|
+
* client does not have yet: a loader the client already holds runs in the
|
|
166
|
+
* prefetch when it revalidates.
|
|
161
167
|
*/
|
|
162
168
|
loader: <TData>(loaderDef: LoaderDefinition<TData>, optionsOrUse?: LoaderOptions | (() => LoaderUseItem[]), use?: () => LoaderUseItem[]) => LoaderItem;
|
|
163
169
|
/**
|
|
164
|
-
* Attach a loading component to the current route/layout
|
|
170
|
+
* Attach a loading component to the current route/layout.
|
|
171
|
+
*
|
|
172
|
+
* `{ ssr: false }` skips the fallback on document requests. `{ prefetch:
|
|
173
|
+
* false }` keeps what the fallback covers out of prefetches, when this
|
|
174
|
+
* entry's segment is new to the client: the entry's handler, its loaders,
|
|
175
|
+
* its orphan layouts and parallel slots and, for a layout, every deeper
|
|
176
|
+
* entry. The click that adopts the prefetch shows the fallback and fetches
|
|
177
|
+
* them in one follow-up request, which reads cache() and "use cache" as
|
|
178
|
+
* any request does (a prefetch reads neither for skipped work). A segment
|
|
179
|
+
* the client already holds is never deferred: a prefetch renders it as
|
|
180
|
+
* usual when it revalidates, and what is below it follows its own flags.
|
|
181
|
+
* To keep a child out of prefetches while moving inside a section, flag
|
|
182
|
+
* the child's own loading(). An entry whose handler output is stored
|
|
183
|
+
* (cache(), ppr, Prerender/Static) is served as usual and only its loaders
|
|
184
|
+
* are skipped.
|
|
165
185
|
*/
|
|
166
186
|
loading: (component: ReactNode | (() => ReactNode), options?: {
|
|
167
187
|
ssr?: boolean;
|
|
188
|
+
prefetch?: boolean;
|
|
168
189
|
}) => LoadingItem;
|
|
169
190
|
/**
|
|
170
191
|
* Attach an error boundary to catch errors in this segment
|
|
@@ -199,8 +220,8 @@ export type PathHelpers<TEnv> = {
|
|
|
199
220
|
* the browser (never on the server); see TransitionWhenFn.
|
|
200
221
|
*/
|
|
201
222
|
transition: {
|
|
202
|
-
():
|
|
203
|
-
(config: TransitionConfig):
|
|
223
|
+
(): TypedTransitionItem<{}, {}>;
|
|
224
|
+
(config: TransitionConfig): TypedTransitionItem<{}, {}>;
|
|
204
225
|
<const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(children: () => TChildren): TypedTransitionItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
|
|
205
226
|
<const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(config: TransitionConfig, children: () => TChildren): TypedTransitionItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
|
|
206
227
|
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { JsonSerialize } from "../serialize.js";
|
|
2
2
|
import type { TypedRouteItem, TypedIncludeItem, TypedLayoutItem, TypedCacheItem, TypedTransitionItem } from "../route-types.js";
|
|
3
3
|
import type { LocalOnlyInclude, UnnamedRoute } from "./pattern-types.js";
|
|
4
|
+
/** Drops string index signatures, keeping literal and template keys. */
|
|
5
|
+
type StripStringIndex<T> = {
|
|
6
|
+
[K in keyof T as string extends K ? never : K]: T[K];
|
|
7
|
+
};
|
|
4
8
|
/**
|
|
5
9
|
* Prefix route names with a given prefix (e.g., "blog" + "post" = "blog.post")
|
|
6
10
|
*
|
|
@@ -52,7 +56,7 @@ type ExtractRoutesFromItem<T> = T extends TypedRouteItem<infer TName, infer TPat
|
|
|
52
56
|
readonly path: TPattern;
|
|
53
57
|
readonly search: TSearch;
|
|
54
58
|
};
|
|
55
|
-
} : {} : T extends TypedIncludeItem<infer TRoutes, infer TNamePrefix, infer TUrlPrefix> ? TNamePrefix extends LocalOnlyInclude ? {} : TNamePrefix extends string ? TUrlPrefix extends string ? PrefixRoutes<PrefixPatterns<TRoutes, TUrlPrefix>, TNamePrefix> : PrefixRoutes<TRoutes, TNamePrefix> : TUrlPrefix extends string ? PrefixPatterns<TRoutes, TUrlPrefix> : TRoutes : T extends TypedLayoutItem<infer TChildRoutes> ? TChildRoutes : T extends TypedCacheItem<infer TChildRoutes> ? TChildRoutes : T extends TypedTransitionItem<infer TChildRoutes> ? TChildRoutes : {};
|
|
59
|
+
} : {} : T extends TypedIncludeItem<infer TRoutes, infer TNamePrefix, infer TUrlPrefix> ? TNamePrefix extends LocalOnlyInclude ? {} : TNamePrefix extends string ? TUrlPrefix extends string ? PrefixRoutes<PrefixPatterns<TRoutes, TUrlPrefix>, TNamePrefix> : PrefixRoutes<TRoutes, TNamePrefix> : TUrlPrefix extends string ? PrefixPatterns<TRoutes, TUrlPrefix> : TRoutes : T extends TypedLayoutItem<infer TChildRoutes> ? StripStringIndex<TChildRoutes> : T extends TypedCacheItem<infer TChildRoutes> ? StripStringIndex<TChildRoutes> : T extends TypedTransitionItem<infer TChildRoutes> ? StripStringIndex<TChildRoutes> : {};
|
|
56
60
|
/**
|
|
57
61
|
* Extract routes from an array of items using mapped types.
|
|
58
62
|
* Uses UnionToIntersection to combine routes without recursive tuple processing,
|
|
@@ -82,7 +86,7 @@ type PrefixKeys<T extends Record<string, unknown>, TPrefix extends string> = TPr
|
|
|
82
86
|
*/
|
|
83
87
|
type ExtractResponsesFromItem<T> = T extends TypedRouteItem<infer TName, any, infer TData> ? TName extends string ? string extends TName ? {} : TName extends UnnamedRoute ? {} : {
|
|
84
88
|
[K in TName]: TData;
|
|
85
|
-
} : {} : T extends TypedIncludeItem<any, infer TNamePrefix, any, infer TResponses> ? TNamePrefix extends LocalOnlyInclude ? {} : TNamePrefix extends string ? TResponses extends Record<string, unknown> ? PrefixKeys<TResponses, TNamePrefix> : {} : TResponses extends Record<string, unknown> ? TResponses : {} : T extends TypedLayoutItem<any, infer TChildResponses> ? TChildResponses extends Record<string, unknown> ?
|
|
89
|
+
} : {} : T extends TypedIncludeItem<any, infer TNamePrefix, any, infer TResponses> ? TNamePrefix extends LocalOnlyInclude ? {} : TNamePrefix extends string ? TResponses extends Record<string, unknown> ? PrefixKeys<TResponses, TNamePrefix> : {} : TResponses extends Record<string, unknown> ? TResponses : {} : T extends TypedLayoutItem<any, infer TChildResponses> ? StripStringIndex<TChildResponses> extends infer R extends Record<string, unknown> ? R : {} : T extends TypedCacheItem<any, infer TChildResponses> ? StripStringIndex<TChildResponses> extends infer R extends Record<string, unknown> ? R : {} : T extends TypedTransitionItem<any, infer TChildResponses> ? StripStringIndex<TChildResponses> extends infer R extends Record<string, unknown> ? R : {} : {};
|
|
86
90
|
/**
|
|
87
91
|
* Extract responses from an array of items using mapped types.
|
|
88
92
|
* Parallel to ExtractRoutesFromItems.
|
|
@@ -13,5 +13,14 @@ import type { DiscoveryState } from "./state.js";
|
|
|
13
13
|
*
|
|
14
14
|
* Returns the imported `@rangojs/router/server` module so the caller
|
|
15
15
|
* can access the RouterRegistry and manifest setters.
|
|
16
|
+
*
|
|
17
|
+
* A pass reads the router registry and installs clientUrls projections on ONE
|
|
18
|
+
* `@rangojs/router/server` instance, and checks that the runner still serves
|
|
19
|
+
* it. A runner full reload during the pass (a watched-file change at boot)
|
|
20
|
+
* splits the realm: a router module bound to the old instance registers there
|
|
21
|
+
* while urls modules re-evaluate against a fresh one, so include() looks its
|
|
22
|
+
* projection up in the fresh, empty Map ("include() could not resolve the
|
|
23
|
+
* server projection"). Such a pass is redone, at most
|
|
24
|
+
* MAX_DISCOVERY_PASSES times; the redo evaluates the entry in one realm.
|
|
16
25
|
*/
|
|
17
26
|
export declare function discoverRouters(state: DiscoveryState, rscEnv: any, ssrEnv?: any): Promise<any>;
|
|
@@ -188,14 +188,21 @@ export interface DiscoveryState {
|
|
|
188
188
|
/** Cleanup function for build-time env resources (e.g., miniflare). */
|
|
189
189
|
buildEnvDispose?: (() => Promise<void> | void) | null;
|
|
190
190
|
/**
|
|
191
|
-
* Set when the most recent HMR re-discovery
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* rediscovery trigger
|
|
191
|
+
* Set when the most recent discovery threw: an HMR re-discovery, or the
|
|
192
|
+
* cold dev discovery on a main RSC runner. Cleared on the next successful
|
|
193
|
+
* discovery. While set, the route-file watcher treats any in-scan source
|
|
194
|
+
* change as a rediscovery trigger (recovery mode).
|
|
195
195
|
*/
|
|
196
196
|
lastDiscoveryError?: {
|
|
197
197
|
message: string;
|
|
198
198
|
at: number;
|
|
199
199
|
} | null;
|
|
200
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Whether the route-file watcher can re-run runtime discovery. A committed
|
|
203
|
+
* manifest is the usual precondition. A failed cold discovery commits none,
|
|
204
|
+
* so on a main RSC runner its recorded failure qualifies too; without that
|
|
205
|
+
* the dev server stayed broken until a restart.
|
|
206
|
+
*/
|
|
207
|
+
export declare function canRefreshRuntimeDiscovery(state: Pick<DiscoveryState, "perRouterManifests" | "lastDiscoveryError">, hasMainRunner: boolean): boolean;
|
|
201
208
|
export declare function createDiscoveryState(entryPath: string | undefined, opts: PluginOptions | undefined): DiscoveryState & ClientUrlDiscoveryState;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
/**
|
|
4
|
+
* The key of the predicate `source` declared in `relativeFile` (relative to
|
|
5
|
+
* the project root): a hash of the file and the predicate's syntax, so the
|
|
6
|
+
* same predicate gets one key in every environment and however it is
|
|
7
|
+
* formatted.
|
|
8
|
+
*/
|
|
9
|
+
export declare function revalidateKey(relativeFile: string, source: string): string;
|
|
10
|
+
interface HoistClientUrlsRevalidateDeps {
|
|
11
|
+
/** Project root: keys hash the file relative to it. */
|
|
12
|
+
readonly root: string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether a module a predicate imports is a "use client" module beyond its
|
|
15
|
+
* specifier (the plugin resolves it and reads its directive prologue).
|
|
16
|
+
*/
|
|
17
|
+
isClientModule?(source: string): Promise<boolean> | boolean;
|
|
18
|
+
}
|
|
19
|
+
interface HoistClientUrlsRevalidateResult {
|
|
20
|
+
/** The module with each predicate replaced by its marker. */
|
|
21
|
+
readonly code: string;
|
|
22
|
+
readonly map: ReturnType<MagicString["generateMap"]>;
|
|
23
|
+
/** The server module that registers every hoisted predicate. */
|
|
24
|
+
readonly module: string;
|
|
25
|
+
/** The keys, in declaration order, duplicates removed. */
|
|
26
|
+
readonly keys: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Hoist every clientUrls() `revalidate()` predicate of a "use client"
|
|
30
|
+
* module. Returns null when there is none. Throws, naming file:line, for a
|
|
31
|
+
* predicate that is not pure.
|
|
32
|
+
*/
|
|
33
|
+
export declare function hoistClientUrlsRevalidates(code: string, id: string, deps: HoistClientUrlsRevalidateDeps): Promise<HoistClientUrlsRevalidateResult | null>;
|
|
34
|
+
/** The file a `?rango-revalidate` id names, or null. */
|
|
35
|
+
export declare function parseHoistedRevalidateId(id: string): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* The plugins: a pre transform that hoists in every environment (markers in
|
|
38
|
+
* the client and SSR copies, the server module recorded from the RSC
|
|
39
|
+
* transform) and serves `?rango-revalidate`, and a post transform that
|
|
40
|
+
* appends its import to the RSC client-reference proxy.
|
|
41
|
+
*
|
|
42
|
+
* `load` serves the module the RSC transform emitted, which hoisted the
|
|
43
|
+
* pipeline code; the disk source is re-hoisted only when the transform has
|
|
44
|
+
* not seen the current file (loadEmittedOrDisk). A file whose edit removed
|
|
45
|
+
* every predicate serves an empty module to a proxy that still imports it.
|
|
46
|
+
*
|
|
47
|
+
* The transform's code filter skips a module that never mentions clientUrls,
|
|
48
|
+
* so a file that stops doing so would keep its `emitted` entry: watchChange
|
|
49
|
+
* drops it, together with the cached "use client" answer for an edited
|
|
50
|
+
* dependency (isClientModule memoizes per resolved file; buildStart resets
|
|
51
|
+
* it).
|
|
52
|
+
*/
|
|
53
|
+
export declare function clientUrlsRevalidateHoistPlugin(): Plugin[];
|
|
54
|
+
export {};
|