@rangojs/router 0.24.4 → 0.25.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/README.md +1 -0
- package/dist/bin/rango.js +363 -39
- package/dist/testing/vitest.js +37 -4
- package/dist/types/browser/event-controller.d.ts +24 -5
- package/dist/types/browser/intercept-utils.d.ts +5 -2
- package/dist/types/browser/merge-segment-loaders.d.ts +0 -23
- package/dist/types/browser/navigation-transaction.d.ts +5 -5
- package/dist/types/browser/partial-update.d.ts +21 -13
- package/dist/types/browser/prefetch/cache.d.ts +8 -0
- package/dist/types/browser/rango-marker.d.ts +7 -0
- package/dist/types/browser/react/filter-segment-order.d.ts +10 -0
- package/dist/types/browser/react/use-handle.d.ts +20 -0
- package/dist/types/browser/react/use-href.d.ts +6 -0
- package/dist/types/browser/react/use-router.d.ts +6 -1
- package/dist/types/browser/response-adapter.d.ts +5 -3
- package/dist/types/browser/scroll-restoration.d.ts +9 -3
- package/dist/types/browser/segment-reconciler.d.ts +10 -13
- package/dist/types/browser/types.d.ts +38 -8
- package/dist/types/build/route-types/per-module-writer.d.ts +12 -0
- package/dist/types/cache/cf/cf-shell-frame.d.ts +2 -0
- package/dist/types/cache/types.d.ts +8 -0
- package/dist/types/client-urls/client-urls.d.ts +6 -2
- package/dist/types/client-urls/revalidate-registry.d.ts +1 -1
- package/dist/types/client-urls/server-projection.d.ts +9 -5
- package/dist/types/client-urls/types.d.ts +29 -16
- package/dist/types/client.d.ts +2 -2
- package/dist/types/client.rsc.d.ts +2 -2
- package/dist/types/decode-loader-results.d.ts +28 -7
- package/dist/types/href-client.d.ts +3 -1
- package/dist/types/index.rsc.d.ts +1 -1
- package/dist/types/loader-redirect.d.ts +2 -3
- package/dist/types/outlet-context.d.ts +7 -6
- package/dist/types/prefetch-markers.d.ts +14 -5
- package/dist/types/route-content-wrapper.d.ts +17 -14
- package/dist/types/route-definition/helpers-types.d.ts +7 -2
- package/dist/types/route-definition/resolve-handler-use.d.ts +6 -1
- package/dist/types/route-definition/rewrite.d.ts +48 -5
- package/dist/types/route-types.d.ts +2 -2
- package/dist/types/router/handler-context.d.ts +14 -2
- package/dist/types/router/intercept-resolution.d.ts +19 -46
- package/dist/types/router/lazy-includes.d.ts +7 -0
- package/dist/types/router/match-middleware/intercept-resolution.d.ts +2 -2
- package/dist/types/router/middleware.d.ts +0 -16
- package/dist/types/router/navigation-snapshot.d.ts +2 -0
- package/dist/types/router/prefetch-cache-ttl.d.ts +8 -11
- package/dist/types/router/revalidation.d.ts +8 -1
- package/dist/types/router/router-context.d.ts +4 -16
- package/dist/types/router/router-interfaces.d.ts +0 -6
- package/dist/types/router/router-options.d.ts +4 -7
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +31 -8
- package/dist/types/router/segment-resolution/revalidation.d.ts +38 -4
- package/dist/types/router/segment-resolution.d.ts +1 -1
- package/dist/types/router/segment-wrappers.d.ts +3 -5
- package/dist/types/router/substitute-pattern-params.d.ts +3 -2
- package/dist/types/router/tracing.d.ts +2 -2
- package/dist/types/rsc/full-payload.d.ts +14 -2
- package/dist/types/rsc/helpers.d.ts +8 -0
- package/dist/types/rsc/manifest-init.d.ts +20 -0
- package/dist/types/rsc/prefetch-render-error.d.ts +22 -0
- package/dist/types/rsc/progressive-enhancement.d.ts +20 -0
- package/dist/types/rsc/rewrite-passes.d.ts +12 -2
- package/dist/types/rsc/server-action.d.ts +6 -0
- package/dist/types/rsc/shell-capture-constants.d.ts +10 -1
- package/dist/types/rsc/shell-capture.d.ts +7 -0
- package/dist/types/rsc/types.d.ts +5 -0
- package/dist/types/segment-system.d.ts +15 -0
- package/dist/types/server/context.d.ts +64 -4
- package/dist/types/server/request-context.d.ts +41 -4
- package/dist/types/server/request-headers.d.ts +12 -0
- package/dist/types/server/rewrite-trail.d.ts +8 -1
- package/dist/types/testing/e2e/index.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +1 -1
- package/dist/types/testing/index.d.ts +1 -1
- package/dist/types/testing/internal/client-urls-projection.d.ts +4 -3
- package/dist/types/testing/render-route.d.ts +21 -11
- package/dist/types/testing/run-loader.d.ts +7 -0
- package/dist/types/testing/run-middleware.d.ts +7 -0
- package/dist/types/testing/run-revalidate.d.ts +5 -4
- package/dist/types/testing/serve-shell-request.d.ts +41 -4
- package/dist/types/testing/shell-status.d.ts +17 -0
- package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
- package/dist/types/testing/vitest.d.ts +10 -1
- package/dist/types/thenable-status.d.ts +0 -6
- package/dist/types/types/handler-context.d.ts +12 -1
- package/dist/types/types/loader-types.d.ts +4 -3
- package/dist/types/types/route-entry.d.ts +2 -1
- package/dist/types/urls/path-helper-types.d.ts +4 -2
- package/dist/types/vite/discovery/client-urls-projection.d.ts +55 -5
- package/dist/types/vite/discovery/state.d.ts +20 -0
- package/dist/types/vite/plugins/client-urls-revalidate-hoist.d.ts +28 -16
- package/dist/types/vite/plugins/hoist/source.d.ts +8 -7
- package/dist/types/vite/plugins/virtual-entries.d.ts +6 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +7 -0
- package/dist/vite/index.js +6816 -6547
- package/package.json +1 -1
- package/skills/app-structure/SKILL.md +255 -0
- package/skills/app-structure/content-site.md +333 -0
- package/skills/app-structure/e-commerce.md +435 -0
- package/skills/app-structure/large-app.md +885 -0
- package/skills/app-structure/multi-app.md +280 -0
- package/skills/breadcrumbs/SKILL.md +6 -1
- package/skills/caching/SKILL.md +3 -1
- package/skills/catalog.json +12 -0
- package/skills/client-urls/SKILL.md +185 -32
- package/skills/composability/SKILL.md +10 -8
- package/skills/handler-use/SKILL.md +48 -9
- package/skills/hooks/handle-and-actions.md +104 -0
- package/skills/hooks/navigation.md +24 -10
- package/skills/hooks/urls.md +1 -1
- package/skills/i18n/SKILL.md +2 -1
- package/skills/intercept/SKILL.md +60 -29
- package/skills/layout/SKILL.md +6 -3
- package/skills/links/SKILL.md +151 -17
- package/skills/loader/SKILL.md +32 -10
- package/skills/middleware/SKILL.md +111 -15
- package/skills/observability/SKILL.md +11 -0
- package/skills/parallel/SKILL.md +5 -5
- package/skills/ppr/SKILL.md +43 -8
- package/skills/prerender/SKILL.md +1 -2
- package/skills/rango/SKILL.md +3 -0
- package/skills/response-routes/SKILL.md +4 -1
- package/skills/scripts/SKILL.md +12 -1
- package/skills/server-actions/SKILL.md +60 -20
- package/skills/testing/SKILL.md +1 -0
- package/skills/testing/client-components.md +13 -10
- package/skills/testing/loader.md +25 -24
- package/skills/testing/middleware.md +11 -11
- package/skills/testing/response-routes.md +4 -1
- package/skills/testing/serve-shell-request.md +85 -21
- package/skills/ux-architecture/SKILL.md +980 -0
- package/skills/view-transitions/SKILL.md +43 -10
- package/src/__augment-tests__/augmented.check.ts +28 -0
- package/src/browser/event-controller.ts +44 -18
- package/src/browser/intercept-utils.ts +3 -2
- package/src/browser/merge-segment-loaders.ts +0 -85
- package/src/browser/navigation-bridge.ts +112 -84
- package/src/browser/navigation-client.ts +20 -15
- package/src/browser/navigation-store.ts +4 -2
- package/src/browser/navigation-transaction.ts +9 -8
- package/src/browser/partial-update.ts +90 -32
- package/src/browser/prefetch/cache.ts +8 -0
- package/src/browser/prefetch/fetch.ts +13 -3
- package/src/browser/rango-marker.ts +13 -0
- package/src/browser/react/NavigationProvider.tsx +25 -7
- package/src/browser/react/filter-segment-order.ts +13 -0
- package/src/browser/react/use-action.ts +9 -15
- package/src/browser/react/use-handle.ts +63 -71
- package/src/browser/react/use-href.tsx +24 -5
- package/src/browser/react/use-link-status.ts +1 -1
- package/src/browser/react/use-navigation.ts +30 -40
- package/src/browser/react/use-router.ts +37 -6
- package/src/browser/react/use-segments.ts +8 -12
- package/src/browser/response-adapter.ts +11 -5
- package/src/browser/rsc-router.tsx +3 -1
- package/src/browser/scroll-restoration.ts +34 -20
- package/src/browser/segment-reconciler.ts +11 -29
- package/src/browser/server-action-bridge.ts +52 -16
- package/src/browser/types.ts +40 -8
- package/src/build/generate-manifest.ts +12 -1
- package/src/build/route-types/codegen.ts +6 -2
- package/src/build/route-types/per-module-writer.ts +94 -61
- package/src/cache/cache-runtime.ts +9 -0
- package/src/cache/cache-scope.ts +2 -1
- package/src/cache/cf/cf-cache-store.ts +2 -0
- package/src/cache/cf/cf-shell-frame.ts +3 -0
- package/src/cache/types.ts +8 -0
- package/src/cache/vercel/vercel-cache-store.ts +6 -1
- package/src/client-urls/client-urls.ts +202 -153
- package/src/client-urls/revalidate-registry.ts +12 -3
- package/src/client-urls/server-projection.ts +137 -66
- package/src/client-urls/types.ts +30 -15
- package/src/client.rsc.tsx +11 -1
- package/src/client.tsx +9 -1
- package/src/decode-loader-results.ts +64 -31
- package/src/href-client.ts +3 -1
- package/src/index.rsc.ts +1 -0
- package/src/index.ts +12 -4
- package/src/loader-redirect.tsx +2 -3
- package/src/outlet-context.ts +7 -6
- package/src/prefetch-markers.ts +15 -5
- package/src/reverse.ts +3 -3
- package/src/route-content-wrapper.tsx +19 -17
- package/src/route-definition/dsl-helpers.ts +27 -7
- package/src/route-definition/helpers-types.ts +7 -2
- package/src/route-definition/resolve-handler-use.ts +23 -10
- package/src/route-definition/rewrite.ts +86 -19
- package/src/route-types.ts +1 -2
- package/src/router/find-match.ts +37 -1
- package/src/router/handler-context.ts +85 -40
- package/src/router/intercept-resolution.ts +161 -307
- package/src/router/lazy-includes.ts +43 -27
- package/src/router/loader-resolution.ts +21 -1
- package/src/router/manifest.ts +6 -8
- package/src/router/match-api.ts +11 -1
- package/src/router/match-middleware/background-revalidation.ts +2 -4
- package/src/router/match-middleware/cache-lookup.ts +16 -20
- package/src/router/match-middleware/intercept-resolution.ts +41 -60
- package/src/router/match-result.ts +31 -2
- package/src/router/middleware.ts +6 -147
- package/src/router/navigation-snapshot.ts +38 -2
- package/src/router/prefetch-cache-ttl.ts +10 -18
- package/src/router/prerender-match.ts +2 -1
- package/src/router/revalidation.ts +24 -3
- package/src/router/router-context.ts +5 -18
- package/src/router/router-interfaces.ts +0 -7
- package/src/router/router-options.ts +4 -7
- package/src/router/segment-resolution/fresh.ts +6 -2
- package/src/router/segment-resolution/helpers.ts +7 -1
- package/src/router/segment-resolution/prefetch-deferral.ts +62 -12
- package/src/router/segment-resolution/revalidation.ts +75 -35
- package/src/router/segment-resolution.ts +0 -1
- package/src/router/segment-wrappers.ts +8 -13
- package/src/router/substitute-pattern-params.ts +3 -2
- package/src/router/tracing.ts +2 -2
- package/src/router.ts +2 -9
- package/src/rsc/full-payload.ts +26 -4
- package/src/rsc/handler.ts +83 -41
- package/src/rsc/helpers.ts +13 -0
- package/src/rsc/manifest-init.ts +56 -3
- package/src/rsc/prefetch-render-error.ts +38 -0
- package/src/rsc/progressive-enhancement.ts +161 -211
- package/src/rsc/rewrite-passes.ts +56 -9
- package/src/rsc/rsc-rendering.ts +79 -23
- package/src/rsc/server-action.ts +25 -2
- package/src/rsc/shell-capture-constants.ts +22 -0
- package/src/rsc/shell-capture.ts +11 -0
- package/src/rsc/types.ts +5 -0
- package/src/segment-system.tsx +125 -119
- package/src/server/context.ts +96 -5
- package/src/server/handle-store.ts +3 -2
- package/src/server/request-context.ts +42 -3
- package/src/server/request-headers.ts +32 -0
- package/src/server/rewrite-trail.ts +55 -9
- package/src/ssr/ssr-root.tsx +6 -10
- package/src/testing/dispatch.ts +4 -5
- package/src/testing/e2e/index.ts +1 -0
- package/src/testing/flight.entry.ts +1 -0
- package/src/testing/index.ts +1 -0
- package/src/testing/internal/client-urls-projection.ts +31 -11
- package/src/testing/render-route.tsx +83 -40
- package/src/testing/run-loader.ts +26 -2
- package/src/testing/run-middleware.ts +10 -0
- package/src/testing/run-revalidate.ts +13 -6
- package/src/testing/serve-shell-request.ts +77 -4
- package/src/testing/shell-status.ts +40 -0
- package/src/testing/vitest-stubs/version.ts +1 -0
- package/src/testing/vitest.ts +74 -7
- package/src/thenable-status.ts +0 -11
- package/src/types/handler-context.ts +12 -1
- package/src/types/loader-types.ts +4 -3
- package/src/types/route-entry.ts +2 -1
- package/src/urls/include-helper.ts +38 -11
- package/src/urls/path-helper-types.ts +4 -2
- package/src/vite/discovery/client-urls-projection.ts +205 -16
- package/src/vite/discovery/discover-routers.ts +2 -2
- package/src/vite/discovery/prerender-collection.ts +2 -6
- package/src/vite/discovery/state.ts +26 -0
- package/src/vite/plugins/client-urls-revalidate-hoist.ts +190 -77
- package/src/vite/plugins/expose-internal-ids.ts +46 -40
- package/src/vite/plugins/hoist/source.ts +8 -7
- package/src/vite/plugins/transition-when-hoist.ts +1 -0
- package/src/vite/plugins/version-plugin.ts +7 -0
- package/src/vite/plugins/version.d.ts +7 -0
- package/src/vite/plugins/virtual-entries.ts +20 -0
- package/src/vite/rango.ts +4 -1
- package/src/vite/router-discovery.ts +39 -7
- package/src/vite/utils/prerender-utils.ts +17 -0
|
@@ -8,7 +8,7 @@ import type { ResolveSegmentOptions } from "./segment-resolution.js";
|
|
|
8
8
|
* Revalidation context passed to segment resolution
|
|
9
9
|
*/
|
|
10
10
|
export interface RevalidationContext {
|
|
11
|
-
clientSegmentIds:
|
|
11
|
+
clientSegmentIds: ReadonlySet<string>;
|
|
12
12
|
prevParams: Record<string, string>;
|
|
13
13
|
request: Request;
|
|
14
14
|
prevUrl: URL;
|
|
@@ -20,7 +20,7 @@ export interface RevalidationContext {
|
|
|
20
20
|
actionResult?: any;
|
|
21
21
|
formData?: FormData;
|
|
22
22
|
};
|
|
23
|
-
stale
|
|
23
|
+
stale?: boolean;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Result from intercept lookup
|
|
@@ -61,7 +61,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
61
61
|
id: string;
|
|
62
62
|
}>;
|
|
63
63
|
resolveInterceptEntry: (intercept: InterceptEntry, entry: EntryData, params: Record<string, string>, handlerContext: HandlerContext<any, TEnv>, belongsToRoute: boolean, revalidationContext?: RevalidationContext, options?: {
|
|
64
|
-
|
|
64
|
+
background?: boolean;
|
|
65
65
|
}) => Promise<ResolvedSegment[]>;
|
|
66
66
|
collectWithMarkers?: <T>(gen: AsyncGenerator<T | {
|
|
67
67
|
__type: "id";
|
|
@@ -111,19 +111,7 @@ export interface RouterContext<TEnv = any> {
|
|
|
111
111
|
}>;
|
|
112
112
|
telemetry?: TelemetrySink;
|
|
113
113
|
requestId?: string;
|
|
114
|
-
resolveInterceptLoadersOnly?: (intercept: InterceptEntry, entry: EntryData,
|
|
115
|
-
clientSegmentIds: Set<string>;
|
|
116
|
-
prevParams: Record<string, string>;
|
|
117
|
-
request: Request;
|
|
118
|
-
prevUrl: URL;
|
|
119
|
-
nextUrl: URL;
|
|
120
|
-
routeKey: string;
|
|
121
|
-
actionContext?: any;
|
|
122
|
-
stale?: boolean;
|
|
123
|
-
}) => Promise<{
|
|
124
|
-
loaderDataPromise: Promise<any[]> | any[];
|
|
125
|
-
loaderIds: string[];
|
|
126
|
-
} | null>;
|
|
114
|
+
resolveInterceptLoadersOnly?: (intercept: InterceptEntry, entry: EntryData, handlerContext: HandlerContext<any, TEnv>, belongsToRoute: boolean, revalidationContext: RevalidationContext) => Promise<ResolvedSegment[]>;
|
|
127
115
|
}
|
|
128
116
|
/**
|
|
129
117
|
* Get router dependencies from AsyncLocalStorage context
|
|
@@ -296,12 +296,6 @@ export interface RangoInternal<TEnv = any, TRoutes extends Record<string, unknow
|
|
|
296
296
|
* Always includes at least the "default" profile.
|
|
297
297
|
*/
|
|
298
298
|
readonly cacheProfiles: Record<string, import("../cache/profile-registry.js").CacheProfile>;
|
|
299
|
-
/**
|
|
300
|
-
* Cache-Control header value for prefetch responses.
|
|
301
|
-
* False means no caching of prefetch responses.
|
|
302
|
-
* Derived from prefetchCacheTTL.
|
|
303
|
-
*/
|
|
304
|
-
readonly prefetchCacheControl: string | false;
|
|
305
299
|
/**
|
|
306
300
|
* TTL in milliseconds for the client-side in-memory prefetch cache.
|
|
307
301
|
* 0 means caching is disabled.
|
|
@@ -510,15 +510,12 @@ export interface RangoOptions<TEnv = any> {
|
|
|
510
510
|
*/
|
|
511
511
|
version?: string;
|
|
512
512
|
/**
|
|
513
|
-
* TTL (in seconds) for the in-memory prefetch cache
|
|
514
|
-
* Cache-Control header on prefetch responses.
|
|
513
|
+
* TTL (in seconds) for the client-side in-memory prefetch cache.
|
|
515
514
|
*
|
|
516
515
|
* Controls how long prefetch responses are kept in the client-side
|
|
517
|
-
* in-memory cache
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
* intercept targets gets no prefetch `Cache-Control`: whether its
|
|
521
|
-
* response is the modal or the full page depends on the source page.
|
|
516
|
+
* in-memory cache. Prefetch responses carry no `Cache-Control`, so the
|
|
517
|
+
* browser's HTTP cache does not keep them: a prefetch whose render failed
|
|
518
|
+
* after its 200 went out would otherwise answer later requests.
|
|
522
519
|
*
|
|
523
520
|
* The cache is automatically invalidated on server actions regardless
|
|
524
521
|
* of TTL, so this is primarily a staleness safety net.
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* force a same-route render from an intercept source (match-api.ts), and a
|
|
25
25
|
* unit deferred on that ground would be dropped from the response as held.
|
|
26
26
|
*/
|
|
27
|
-
import { type EntryData, type LoaderEntry } from "../../server/context.js";
|
|
27
|
+
import { type EntryData, type InterceptEntry, type LoaderEntry } from "../../server/context.js";
|
|
28
28
|
import type { HandlerContext } from "../../types.js";
|
|
29
29
|
import type { CacheScope } from "../../cache/cache-scope.js";
|
|
30
30
|
/**
|
|
@@ -148,33 +148,42 @@ export interface DeferredLoader {
|
|
|
148
148
|
* in the tree declares `prefetch: false`.
|
|
149
149
|
*/
|
|
150
150
|
export declare function resolveDeferralScope(entries: readonly EntryData[]): DeferralScope;
|
|
151
|
+
/**
|
|
152
|
+
* The deferral scope of a request that resolves `intercept`: its own flagged
|
|
153
|
+
* loaders, nothing of the target chain. The chain's layouts below the
|
|
154
|
+
* declaring entry render in that request and its `matched` leaves them out
|
|
155
|
+
* (match-result.ts), so a hole there would stand for a segment outside the
|
|
156
|
+
* page. A flagged loading() inside intercept() defers nothing: the slot is
|
|
157
|
+
* never a unit. Memoized on the entry (replaced with its manifest on HMR).
|
|
158
|
+
*/
|
|
159
|
+
export declare function resolveInterceptDeferralScope(intercept: InterceptEntry): DeferralScope;
|
|
151
160
|
/**
|
|
152
161
|
* Which half of the feature a partial request is, if either (`fill` and
|
|
153
162
|
* `prefetch` are requestKind's answer). Both halves are GETs: a request of
|
|
154
163
|
* another method that carries either marker is a normal request. A prefetch
|
|
155
164
|
* defers only on a plain GET navigation: an action re-renders what it
|
|
156
|
-
* changed,
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* runs the full match): each one states its own reason.
|
|
165
|
+
* changed, and a shell capture is never a prefetch whatever the request that
|
|
166
|
+
* scheduled it sent. The conditions overlap today (an action is a POST, a
|
|
167
|
+
* capture runs the full match): each one states its own reason.
|
|
160
168
|
*/
|
|
161
169
|
export declare function partialDeferralMode(request: {
|
|
162
170
|
fill: boolean;
|
|
163
171
|
prefetch: boolean;
|
|
164
172
|
method: string;
|
|
165
173
|
isAction: boolean;
|
|
166
|
-
isIntercept: boolean;
|
|
167
174
|
isShellCapture: boolean;
|
|
168
175
|
}): PrefetchDeferral["mode"];
|
|
176
|
+
export declare const NOTHING_HELD: ReadonlySet<string>;
|
|
169
177
|
/**
|
|
170
178
|
* The plan for one match, or undefined when the tree declares no flag and the
|
|
171
179
|
* request is not a fill (the common case: nothing to carry). `held` is the
|
|
172
|
-
* client's segment ids as the request listed them.
|
|
180
|
+
* client's segment ids as the request listed them. `scope` is the chain's
|
|
181
|
+
* unless the request resolves an intercept (resolveInterceptDeferralScope).
|
|
173
182
|
*/
|
|
174
183
|
export declare function planPrefetchDeferral(entries: readonly EntryData[], mode: PrefetchDeferral["mode"], matched: {
|
|
175
184
|
pr?: boolean;
|
|
176
185
|
od?: boolean;
|
|
177
|
-
}, cacheScope: CacheScope | null | undefined, held?: ReadonlySet<string
|
|
186
|
+
}, cacheScope: CacheScope | null | undefined, held?: ReadonlySet<string>, scope?: DeferralScope): PrefetchDeferral | undefined;
|
|
178
187
|
export declare function getPrefetchDeferral(ctx: HandlerContext<any, any> | undefined): PrefetchDeferral | undefined;
|
|
179
188
|
/** The request is a fill: a held segment is skipped without consulting anything. */
|
|
180
189
|
export declare function isFillRequest(ctx: HandlerContext<any, any>): boolean;
|
|
@@ -186,6 +195,20 @@ export declare function isFillRequest(ctx: HandlerContext<any, any>): boolean;
|
|
|
186
195
|
* deciding site resolves with.
|
|
187
196
|
*/
|
|
188
197
|
export declare function fillSends(ctx: HandlerContext<any, any>, segmentId: string, held: ReadonlySet<string>): boolean | undefined;
|
|
198
|
+
/**
|
|
199
|
+
* A fill that resolves an intercept sends only what the client lacks of the
|
|
200
|
+
* intercept: a target-chain entry (by id) or stored segment it does not hold
|
|
201
|
+
* lies outside the intercept's `matched` (match-result.ts), so the fill skips
|
|
202
|
+
* it. The intercept's own segments are never skipped.
|
|
203
|
+
*/
|
|
204
|
+
export declare function interceptFillSkips(match: {
|
|
205
|
+
handlerContext: HandlerContext<any, any>;
|
|
206
|
+
isIntercept: boolean;
|
|
207
|
+
clientSegmentSet: ReadonlySet<string>;
|
|
208
|
+
}, segment: string | {
|
|
209
|
+
id: string;
|
|
210
|
+
namespace?: string;
|
|
211
|
+
}): boolean;
|
|
189
212
|
/** PrefetchDeferral.record, or all of it open when the match has no plan. */
|
|
190
213
|
export declare function recordUse(ctx: HandlerContext<any, any> | undefined): RecordUse;
|
|
191
214
|
/**
|
|
@@ -5,14 +5,48 @@
|
|
|
5
5
|
* Mirrors the fresh path but adds revalidation awareness: only re-resolves
|
|
6
6
|
* segments whose revalidate() predicate returns true.
|
|
7
7
|
*/
|
|
8
|
-
import { type EntryData } from "../../server/context";
|
|
8
|
+
import { type EntryData, type LoaderEntry } from "../../server/context";
|
|
9
9
|
import type { HandlerContext, ResolvedSegment, ShouldRevalidateFn } from "../../types";
|
|
10
10
|
import type { SegmentResolutionDeps, SegmentRevalidationResult, ActionContext } from "../types.js";
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* A deferred loader something started in this request (a handler that awaits
|
|
13
|
+
* it with ctx.use(), or another loader) ran in the prefetch whatever its flag
|
|
14
|
+
* says: deliver that run instead of having the fill run it a second time. A
|
|
15
|
+
* reader starts it through its registration (prefetch-deferral.ts
|
|
16
|
+
* startDeferredLoader), so the delivery's resolveLoaderData finds the same
|
|
17
|
+
* run or cache() binding. Called once resolution has awaited every handler it
|
|
18
|
+
* awaits; a streamed handler that reads the loader later is not seen, and
|
|
19
|
+
* that loader runs again in the fill.
|
|
14
20
|
*/
|
|
15
|
-
export declare function
|
|
21
|
+
export declare function deliverStartedLoaders<TEnv>(ctx: HandlerContext<any, TEnv>, segments: ResolvedSegment[]): void;
|
|
22
|
+
/**
|
|
23
|
+
* Whose loaders a resolveOwnerLoaders call resolves: a route entry's (or the
|
|
24
|
+
* entry its loaders are inherited into), or an intercept's, whose loaders are
|
|
25
|
+
* loader segments of its slot (`${parent}.${slot}D${i}.${$$id}`).
|
|
26
|
+
*/
|
|
27
|
+
export interface LoaderOwner {
|
|
28
|
+
readonly loaders: readonly LoaderEntry[];
|
|
29
|
+
/** The segments' namespace: the entry id, or `intercept:${routeName}`. */
|
|
30
|
+
readonly namespace: string;
|
|
31
|
+
/** The segment id the loader ids extend and the handle pushes file under. */
|
|
32
|
+
readonly segmentPrefix: string;
|
|
33
|
+
/** Where a loader error renders (wrapLoaderPromise). */
|
|
34
|
+
readonly boundary: EntryData;
|
|
35
|
+
/**
|
|
36
|
+
* resolveLoaderData's PPR bake/seed key for every loader (loader-cache.ts).
|
|
37
|
+
* False for an intercept: never a document.
|
|
38
|
+
*/
|
|
39
|
+
readonly bakeLane: boolean;
|
|
40
|
+
readonly traceSource: "loader" | "intercept-loader";
|
|
41
|
+
}
|
|
42
|
+
/** A route entry as a LoaderOwner, under `shortCodeOverride` when inherited. */
|
|
43
|
+
export declare function ownerOf(entry: EntryData, shortCodeOverride?: string): LoaderOwner;
|
|
44
|
+
/**
|
|
45
|
+
* The partial lane's one loader funnel: each loader is a segment, run when
|
|
46
|
+
* the client lacks it, asked its revalidate() when held, kept outright in a
|
|
47
|
+
* fill (fillSends), deferred in a prefetch that defers it (defersLoader).
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveOwnerLoaders<TEnv>(owner: LoaderOwner, ctx: HandlerContext<any, TEnv>, belongsToRoute: boolean, clientSegmentIds: ReadonlySet<string>, prevParams: Record<string, string>, request: Request, prevUrl: URL, nextUrl: URL, routeKey: string, deps: SegmentResolutionDeps<TEnv>, actionContext?: ActionContext, stale?: boolean): Promise<{
|
|
16
50
|
segments: ResolvedSegment[];
|
|
17
51
|
matchedIds: string[];
|
|
18
52
|
}>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { handleHandlerResult, warnOnStreamedResponse, buildLoaderErrorContext, } from "./segment-resolution/helpers.js";
|
|
2
2
|
export { resolveLoaders, type ResolveSegmentOptions, resolveSegment, resolveOrphanLayout, resolveParallelEntry, resolveAllSegments, resolveLoadersOnly, } from "./segment-resolution/fresh.js";
|
|
3
|
-
export {
|
|
3
|
+
export { resolveLoadersOnlyWithRevalidation, buildEntryRevalidateMap, resolveParallelSegmentsWithRevalidation, resolveEntryHandlerWithRevalidation, resolveSegmentWithRevalidation, resolveOrphanLayoutWithRevalidation, resolveAllSegmentsWithRevalidation, } from "./segment-resolution/revalidation.js";
|
|
@@ -2,6 +2,7 @@ import type { EntryData, InterceptEntry } from "../server/context";
|
|
|
2
2
|
import type { HandlerContext, ResolvedSegment, ShouldRevalidateFn } from "../types";
|
|
3
3
|
import type { SegmentResolutionDeps } from "./types.js";
|
|
4
4
|
import type { ResolveSegmentOptions } from "./segment-resolution.js";
|
|
5
|
+
import type { RevalidationContext } from "./router-context.js";
|
|
5
6
|
import type { InterceptSelectorContext } from "../server/context";
|
|
6
7
|
export interface SegmentWrappers<TEnv = any> {
|
|
7
8
|
resolveAllSegments: (entries: EntryData[], routeKey: string, params: Record<string, string>, context: HandlerContext<any, TEnv>, loaderPromises: Map<string, Promise<any>>, options?: ResolveSegmentOptions) => Promise<ResolvedSegment[]>;
|
|
@@ -36,12 +37,9 @@ export interface SegmentWrappers<TEnv = any> {
|
|
|
36
37
|
entry: EntryData;
|
|
37
38
|
} | null;
|
|
38
39
|
resolveInterceptEntry: (interceptEntry: InterceptEntry, parentEntry: EntryData, params: Record<string, string>, context: HandlerContext<any, TEnv>, belongsToRoute?: boolean, revalidationContext?: any, options?: {
|
|
39
|
-
|
|
40
|
+
background?: boolean;
|
|
40
41
|
}) => Promise<ResolvedSegment[]>;
|
|
41
|
-
resolveInterceptLoadersOnly: (interceptEntry: InterceptEntry, parentEntry: EntryData,
|
|
42
|
-
loaderDataPromise: Promise<any[]> | any[];
|
|
43
|
-
loaderIds: string[];
|
|
44
|
-
} | null>;
|
|
42
|
+
resolveInterceptLoadersOnly: (interceptEntry: InterceptEntry, parentEntry: EntryData, context: HandlerContext<any, TEnv>, belongsToRoute: boolean, revalidationContext: RevalidationContext) => Promise<ResolvedSegment[]>;
|
|
45
43
|
}
|
|
46
44
|
/**
|
|
47
45
|
* Create thin wrapper functions that bind segmentDeps to extracted
|
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
* omit when absent.
|
|
18
18
|
*
|
|
19
19
|
* Shared by `ctx.reverse()` (server), `createReverse()` (typed runtime
|
|
20
|
-
* helper),
|
|
21
|
-
*
|
|
20
|
+
* helper), `useReverse()` (client hook), and the include() mount fill of
|
|
21
|
+
* `useHref()` and relative `useRouter().push`. The behavior must stay
|
|
22
|
+
* identical across all of them.
|
|
22
23
|
*/
|
|
23
24
|
export declare function substitutePatternParams(pattern: string, params: Record<string, string | undefined>, routeName: string): string;
|
|
24
25
|
/**
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
* registry; do not call traceSpan directly from new code.
|
|
25
25
|
*
|
|
26
26
|
* Phase coverage (all via observePhase): rango.request (span-only; handler:total
|
|
27
|
-
* metered directly), rango.middleware (span-only
|
|
28
|
-
*
|
|
27
|
+
* metered directly), rango.middleware (span-only; pre/post metered directly),
|
|
28
|
+
* rango.action (action:<id>; server-action
|
|
29
29
|
* execution, JS + no-JS/PE), rango.loader (loader:<id>; single metering site at
|
|
30
30
|
* useLoader, plus the fetchable path), rango.handler (span-only, one per segment
|
|
31
31
|
* route/layout handler execution; the handler:<id> perf metric is owned by the
|
|
@@ -28,10 +28,22 @@ export declare function buildFullPayload(m: MatchResult, ctx: HandlerContext<any
|
|
|
28
28
|
* bar) agree on `usePathname()` and `useSearchParams()`. A render other
|
|
29
29
|
* visitors may be served shows `url`, the target, as a direct visit does: a
|
|
30
30
|
* shell capture, and a render the document cache stores (its key is the
|
|
31
|
-
* target)
|
|
31
|
+
* target), except a visitor-keyed shell capture, whose key covers the
|
|
32
|
+
* visitor's URL. Any other render that shows the visitor's URL marks
|
|
32
33
|
* `_payloadVisitorLocation`, and the document cache does not store it.
|
|
33
34
|
*/
|
|
34
|
-
export declare function renderedLocation(reqCtx: Pick<RequestContext<any>, "_variables" | "_shellCaptureRun" | "_documentCacheRender" | "_payloadVisitorLocation" | "res"> | undefined, url: URL): URL;
|
|
35
|
+
export declare function renderedLocation(reqCtx: Pick<RequestContext<any>, "_variables" | "_shellCaptureRun" | "_shellCaptureForVisitor" | "_documentCacheRender" | "_payloadVisitorLocation" | "res"> | undefined, url: URL): URL;
|
|
36
|
+
/**
|
|
37
|
+
* A payload's `pathname` (renderedLocation) and, when middleware rewrote the
|
|
38
|
+
* request, `rewriteTarget`: the path and search the route rendered (the
|
|
39
|
+
* trail's last URL). The browser keeps it per history entry and sends it
|
|
40
|
+
* back as `_rsc_rt`, so the next request from the page diffs against the
|
|
41
|
+
* route that rendered it (navigation-snapshot.ts resolveNavigation, #1144).
|
|
42
|
+
*/
|
|
43
|
+
export declare function payloadLocation(reqCtx: Parameters<typeof renderedLocation>[0], url: URL): {
|
|
44
|
+
pathname: string;
|
|
45
|
+
rewriteTarget?: string;
|
|
46
|
+
};
|
|
35
47
|
/**
|
|
36
48
|
* The theme a document payload carries as `metadata.initialTheme` (the
|
|
37
49
|
* ThemeProvider's first state), read with no identity guard: it is the
|
|
@@ -117,6 +117,14 @@ export declare function buildRouteMiddlewareEntries<TEnv>(routeMiddleware: Array
|
|
|
117
117
|
entry: MiddlewareEntry<TEnv>;
|
|
118
118
|
params: Record<string, string>;
|
|
119
119
|
}>;
|
|
120
|
+
/**
|
|
121
|
+
* The request route middleware sees around the render after a server action
|
|
122
|
+
* or a no-JS form post: the page's GET (URL, headers without body framing or
|
|
123
|
+
* content-type, signal, workerd `cf`; no body). Route middleware never wraps the action,
|
|
124
|
+
* only that render, so it decides as for a GET of the page: a rewrite it
|
|
125
|
+
* skips for mutations still moves the render to its target (#1145).
|
|
126
|
+
*/
|
|
127
|
+
export declare function actionRenderRequest(request: Request): Request;
|
|
120
128
|
/**
|
|
121
129
|
* Merge stub headers from the request context onto an existing Response in
|
|
122
130
|
* place, then drain onResponse callbacks. Used when a Response cannot flow
|
|
@@ -4,6 +4,26 @@
|
|
|
4
4
|
* Builds a fresh route trie from every registered URL-pattern mount for
|
|
5
5
|
* dev/HMR scenarios where the manifest exists but the trie needs rebuilding.
|
|
6
6
|
*/
|
|
7
|
+
/** True when the trie installed for `router.id` was built from this router. */
|
|
8
|
+
export declare function isRouterTrieBuiltFrom(router: {
|
|
9
|
+
id?: string;
|
|
10
|
+
}): boolean;
|
|
11
|
+
/** The router fields ensureRouterTrie reads. */
|
|
12
|
+
export interface TrieSource {
|
|
13
|
+
id?: string;
|
|
14
|
+
urlpatterns?: unknown;
|
|
15
|
+
routeMap: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Install the trie `router` matches through, as a request finds it: the build
|
|
19
|
+
* manifest's trie when one is registered for its id, otherwise one built from
|
|
20
|
+
* its routes the way the dev handler builds it (rsc/handler.ts). Ids can repeat
|
|
21
|
+
* across router objects (tests), and another object's trie names other routes,
|
|
22
|
+
* so a trie this object did not build is rebuilt. Seeds the per-router manifest
|
|
23
|
+
* from `router.routeMap` when neither source set one, for reverse(). testing's
|
|
24
|
+
* dispatch matches through it, never the regex fallback alone (#1104, #1107).
|
|
25
|
+
*/
|
|
26
|
+
export declare function ensureRouterTrie(router: TrieSource): Promise<void>;
|
|
7
27
|
/**
|
|
8
28
|
* Build a fresh route trie from the router's URL-pattern mounts and store it in
|
|
9
29
|
* the per-router cache. Also sets the per-router manifest and merges into the
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A prefetch whose render reported an error is not kept (#1170).
|
|
3
|
+
*
|
|
4
|
+
* WHY: its 200 left with the headers before a streamed part failed, so the
|
|
5
|
+
* client stored the error boundary as a healthy prefetch, served it to a
|
|
6
|
+
* click and respawned it. The status cannot change any more, and the body
|
|
7
|
+
* cannot end with an error: workerd delivers an errored body as a clean end,
|
|
8
|
+
* and in Chromium the error drops the rows a click that adopted the prefetch
|
|
9
|
+
* has not decoded yet (a Flight "network error" in place of the page).
|
|
10
|
+
*
|
|
11
|
+
* So the body ends cleanly with one more row, PREFETCH_FAILED_ROW, which the
|
|
12
|
+
* Flight decoder skips and teeWithCompletion (browser/response-adapter.ts)
|
|
13
|
+
* reads as a stream that did not end cleanly: the client evicts the prefetch
|
|
14
|
+
* and never respawns it. Prefetch responses carry no Cache-Control, so the
|
|
15
|
+
* browser HTTP cache keeps none of it either.
|
|
16
|
+
*
|
|
17
|
+
* The errors are the render's `_renderErrors`: a Flight error row, a streamed
|
|
18
|
+
* handler recovered into its boundary, a loader that threw (redirect() and
|
|
19
|
+
* notFound() are not errors). Each is recorded before Flight writes the row
|
|
20
|
+
* that carries it, so the list is complete once Flight closes the stream.
|
|
21
|
+
*/
|
|
22
|
+
export declare function markPrefetchOnRenderError(response: Response, renderErrors: readonly unknown[]): Response;
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { getRequestContext } from "../server/request-context.js";
|
|
9
9
|
import type { MiddlewareFn } from "../router/middleware.js";
|
|
10
|
+
import type { ReactFormState } from "./types.js";
|
|
11
|
+
import type { MatchResult } from "../types.js";
|
|
10
12
|
import type { HandlerContext } from "./handler-context.js";
|
|
11
13
|
export interface PeRouteMiddlewareInfo {
|
|
12
14
|
routeMiddleware?: Array<{
|
|
@@ -17,3 +19,21 @@ export interface PeRouteMiddlewareInfo {
|
|
|
17
19
|
routeReverse?: (name: string, params?: Record<string, string>, search?: Record<string, unknown>) => string;
|
|
18
20
|
}
|
|
19
21
|
export declare function handleProgressiveEnhancement<TEnv>(ctx: HandlerContext<TEnv>, request: Request, env: TEnv, url: URL, isAction: boolean, handleStore: ReturnType<typeof getRequestContext>["_handleStore"], nonce: string | undefined, routeMwInfo?: PeRouteMiddlewareInfo): Promise<Response | null>;
|
|
22
|
+
/** What a no-JS form post's action left for the re-render (`_actionRan`). */
|
|
23
|
+
export interface FormActionOutcome {
|
|
24
|
+
reactFormState: ReactFormState | null;
|
|
25
|
+
directActionId: string | null;
|
|
26
|
+
/** The action threw, or the form body did not parse. */
|
|
27
|
+
failure?: PeFailure;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A failed no-JS form post and the error boundary matched for it. The boundary
|
|
31
|
+
* renders in place of the page, inside route middleware as the JS path renders
|
|
32
|
+
* its own (server-action.ts `errorBoundary`). With none, the page re-renders
|
|
33
|
+
* with 500, the JS path's status for the same boundaryless error.
|
|
34
|
+
*/
|
|
35
|
+
export interface PeFailure {
|
|
36
|
+
error: unknown;
|
|
37
|
+
actionId: string | null | undefined;
|
|
38
|
+
boundary: MatchResult | null;
|
|
39
|
+
}
|
|
@@ -32,8 +32,18 @@ export interface RewritePass {
|
|
|
32
32
|
/**
|
|
33
33
|
* Move the request context to `rewrite`'s target for the next pass: check
|
|
34
34
|
* that this request can be rewritten, resolve the target, count the hop,
|
|
35
|
-
* then rebase the context. Throws the site error for a
|
|
36
|
-
*
|
|
35
|
+
* then rebase the context. Throws the site error for a loader fetch, a
|
|
36
|
+
* refused mutation or one whose body middleware read before its action ran,
|
|
37
|
+
* a resolution error, and RewriteLoopError.
|
|
38
|
+
*
|
|
39
|
+
* A mutation moves too (#1145). Before its action ran (a rewrite from global
|
|
40
|
+
* middleware) it moves with its body, and the target's pass runs the action
|
|
41
|
+
* after the target's global middleware, as a direct post there would. After
|
|
42
|
+
* it ran (route middleware wraps only the re-render), the target's pass
|
|
43
|
+
* re-renders from `reqCtx._actionRan`. `disallowMutations()` refuses the
|
|
44
|
+
* first, so a lock never runs a mutation; the second is already committed,
|
|
45
|
+
* and refusing it reports an error for a write that happened, so the caller
|
|
46
|
+
* retries it.
|
|
37
47
|
*/
|
|
38
48
|
export declare function applyRewrite(rewrite: Rewrite, passRequest: Request, reqCtx: RequestContext<any>, routeMap: Record<string, string>, basename: string | undefined): RewritePass;
|
|
39
49
|
/** The response to a rewrite loop. */
|
|
@@ -53,6 +53,12 @@ export interface ActionContinuation {
|
|
|
53
53
|
* or an ActionContinuation for the revalidation phase.
|
|
54
54
|
*/
|
|
55
55
|
export declare function executeServerAction<TEnv>(ctx: HandlerContext<TEnv>, request: Request, env: TEnv, url: URL, actionId: string, handleStore: ReturnType<typeof getRequestContext>["_handleStore"]): Promise<Response | ActionContinuation>;
|
|
56
|
+
/**
|
|
57
|
+
* The continuation for a rewrite pass after the action ran (#1145): a failed
|
|
58
|
+
* action's error boundary is re-matched on the target, since the one pass 1
|
|
59
|
+
* matched (or missed) is the rewriting route's.
|
|
60
|
+
*/
|
|
61
|
+
export declare function continuationForRewritePass<TEnv>(ctx: HandlerContext<TEnv>, request: Request, env: TEnv, continuation: ActionContinuation): Promise<ActionContinuation>;
|
|
56
62
|
/**
|
|
57
63
|
* Phase 2: Revalidate after action.
|
|
58
64
|
*
|
|
@@ -41,7 +41,7 @@ export declare const PPR_REPLAY_STATUS_HEADER: string;
|
|
|
41
41
|
* producer (rsc-rendering.ts) and the parser (testing/shell-status.ts): a
|
|
42
42
|
* reason the parser does not list parses as null.
|
|
43
43
|
*/
|
|
44
|
-
export declare const PPR_REPLAY_BYPASS_REASONS: readonly ["method", "dynamic", "nonce", "store-unavailable", "passive-read-unsupported", "no-navigation-context", "prerender-store", "intercept", "cache-disabled", "read-error", "no-entry", "invalid-version", "corrupt-entry", "no-segment-snapshot", "snapshot-miss", "explicit-cache-hit"];
|
|
44
|
+
export declare const PPR_REPLAY_BYPASS_REASONS: readonly ["method", "dynamic", "nonce", "store-unavailable", "passive-read-unsupported", "no-navigation-context", "prerender-store", "intercept", "cache-disabled", "read-error", "no-entry", "invalid-version", "corrupt-entry", "no-segment-snapshot", "snapshot-miss", "explicit-cache-hit", "rewritten"];
|
|
45
45
|
/** One of {@link PPR_REPLAY_BYPASS_REASONS}. */
|
|
46
46
|
export type PprReplayBypassReason = (typeof PPR_REPLAY_BYPASS_REASONS)[number];
|
|
47
47
|
/**
|
|
@@ -84,6 +84,15 @@ export declare function buildShellKey(routerId: string, url: URL, filter?: Searc
|
|
|
84
84
|
* replayed to gold's navigations. Encoded, it holds no `:` or `|`.
|
|
85
85
|
*/
|
|
86
86
|
export declare function partitionShellKey(key: string, partition: string): string;
|
|
87
|
+
/**
|
|
88
|
+
* The shell key of a `rewrite(...).shell("visitor")` request: the visitor's
|
|
89
|
+
* URL, partitioned by `rw:` + the target's path and search (both searches
|
|
90
|
+
* filtered and sorted, shellSearchSeed). The visitor's URL keeps two public
|
|
91
|
+
* URLs of one target apart; the target keeps a conditional rewrite (an A/B
|
|
92
|
+
* arm, a lock) apart from the URL's own shell. The route's own partition
|
|
93
|
+
* composes after it.
|
|
94
|
+
*/
|
|
95
|
+
export declare function visitorShellKey(routerId: string, visitor: URL, target: URL, filter?: SearchParamsFilter): string;
|
|
87
96
|
/**
|
|
88
97
|
* The navigation-only entry beside a document shell key (a cold partial
|
|
89
98
|
* request's capture, rsc-rendering.ts). A suffix after the (encoded)
|
|
@@ -330,6 +330,13 @@ export interface ShellCaptureDescriptor {
|
|
|
330
330
|
debugSink?: (event: ShellCaptureDebugEvent) => void;
|
|
331
331
|
/** Store the snapshot for navigation replay, never the captured HTML prelude. */
|
|
332
332
|
navigationOnly?: true;
|
|
333
|
+
/**
|
|
334
|
+
* Set for a shell keyed by the visitor's URL (`rewrite(...).shell("visitor")`,
|
|
335
|
+
* visitorShellKey): the capture renders the visitor's location
|
|
336
|
+
* (`RequestContext._shellCaptureForVisitor`) and stores it as
|
|
337
|
+
* ShellCacheEntry.pathname.
|
|
338
|
+
*/
|
|
339
|
+
pathname?: string;
|
|
333
340
|
/**
|
|
334
341
|
* lastStoredCaptureSeq(key) when a document request read the store and
|
|
335
342
|
* missed. The request schedules its capture only after rendering the MISS,
|
|
@@ -16,6 +16,11 @@ import type { ResolvedThemeConfig, Theme } from "../theme/types.js";
|
|
|
16
16
|
export interface RscPayload {
|
|
17
17
|
metadata?: {
|
|
18
18
|
pathname: string;
|
|
19
|
+
/**
|
|
20
|
+
* Path and search of the URL the route rendered for, when middleware
|
|
21
|
+
* rewrote the request there (full-payload.ts payloadLocation).
|
|
22
|
+
*/
|
|
23
|
+
rewriteTarget?: string;
|
|
19
24
|
segments: ResolvedSegment[];
|
|
20
25
|
/** Router instance ID. When this changes between navigations, the client
|
|
21
26
|
* discards cached segments and does a full tree replacement (app switch). */
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { type ReactNode, type ComponentType } from "react";
|
|
2
2
|
import type { ResolvedSegment, RootLayoutProps } from "./types.js";
|
|
3
3
|
export declare function restoreParallelLoaderMarkers(segments: ResolvedSegment[]): ResolvedSegment[];
|
|
4
|
+
/**
|
|
5
|
+
* An intercept's loaders arrive as loader segments of its slot
|
|
6
|
+
* (`${slot.id}D${i}.${$$id}`, router/intercept-resolution.ts). Folded back
|
|
7
|
+
* onto the slot before the tree walk, as one aggregate the slot's
|
|
8
|
+
* LoaderBoundary reads (client.tsx renderSlotContent): walked as loaders they
|
|
9
|
+
* would attach to the slot's parent, whose subtree (the page under the modal)
|
|
10
|
+
* would change shape and remount. Any other loader segment passes through; a
|
|
11
|
+
* list with nothing to fold is returned as it is, synchronously.
|
|
12
|
+
* The slot is a new object (rule 6, suspense-contract.md); its aggregate is
|
|
13
|
+
* memoized on the loaders' data (rule 1). Settled before the commit when
|
|
14
|
+
* nothing in it is deferred and the slot has no loading() or the lane settles
|
|
15
|
+
* loaders (forceAwait, action): a modal with no loading() commits whole, as
|
|
16
|
+
* when the server awaited its loaders.
|
|
17
|
+
*/
|
|
18
|
+
export declare function foldInterceptLoaders(segments: ResolvedSegment[], settleLoaders: boolean): ResolvedSegment[] | Promise<ResolvedSegment[]>;
|
|
4
19
|
/**
|
|
5
20
|
* Options for renderSegments
|
|
6
21
|
*/
|
|
@@ -61,6 +61,12 @@ export type EntryPropCommon = {
|
|
|
61
61
|
cache?: EntryCacheConfig;
|
|
62
62
|
/** URL prefix from include() scope, used for MountContext on client */
|
|
63
63
|
mountPath?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Include scope the entry's handler and loaders resolve `ctx.reverse(".name")`
|
|
66
|
+
* in. Structural entries only (layout, cache, parallel, wrapping
|
|
67
|
+
* middleware); a route resolves from its own name. See ReverseScope.
|
|
68
|
+
*/
|
|
69
|
+
reverseScope?: ReverseScope;
|
|
64
70
|
/** clientUrls() group key (PathOptions.clientGroup); route entries only. */
|
|
65
71
|
clientGroup?: string;
|
|
66
72
|
};
|
|
@@ -129,6 +135,13 @@ export type LoaderEntry = {
|
|
|
129
135
|
* (router/segment-resolution/prefetch-deferral.ts).
|
|
130
136
|
*/
|
|
131
137
|
prefetch?: false;
|
|
138
|
+
/**
|
|
139
|
+
* The declaring layout's / parallel's / cache()'s include scope, for the
|
|
140
|
+
* loader body's `ctx.reverse(".name")` (its DSL kickoff carries it,
|
|
141
|
+
* runInsideLoaderScope). Unset on a route's loaders: they resolve from the
|
|
142
|
+
* route's name.
|
|
143
|
+
*/
|
|
144
|
+
reverseScope?: ReverseScope;
|
|
132
145
|
};
|
|
133
146
|
/**
|
|
134
147
|
* Segments state for intercept context
|
|
@@ -192,7 +205,6 @@ export type InterceptEntry = {
|
|
|
192
205
|
slotName: `@${string}`;
|
|
193
206
|
routeName: string;
|
|
194
207
|
handler: ReactNode | Handler<any, any, any>;
|
|
195
|
-
middleware: MiddlewareFn<any, any>[];
|
|
196
208
|
loader: LoaderEntry[];
|
|
197
209
|
loading?: ReactNode | false;
|
|
198
210
|
transition?: TransitionConfig;
|
|
@@ -267,10 +279,21 @@ export type EntryData = ({
|
|
|
267
279
|
/** Cache entries create cache boundaries and render like layouts (with Outlet) */
|
|
268
280
|
handler: ReactNode | Handler<any, any, any>;
|
|
269
281
|
} & EntryPropCommon & EntryPropDatas & EntryPropSegments & EntryPropRender);
|
|
282
|
+
/**
|
|
283
|
+
* Where an include()'s handler runs in the route tree. Hidden include-scope
|
|
284
|
+
* names (`$prefix_*`) derive from it, never from counter state, so build
|
|
285
|
+
* discovery and runtime expansion name every include the same (#1104).
|
|
286
|
+
*/
|
|
287
|
+
export interface IncludeScopePosition {
|
|
288
|
+
/** Sibling indexes of the enclosing includes, "_"-joined ("" at a mount root). */
|
|
289
|
+
scopePath?: string;
|
|
290
|
+
/** The scopePath tail since the nearest include that added a name segment. */
|
|
291
|
+
hiddenScopePath?: string;
|
|
292
|
+
}
|
|
270
293
|
/**
|
|
271
294
|
* Tracked include info for build-time manifest generation
|
|
272
295
|
*/
|
|
273
|
-
export interface TrackedInclude {
|
|
296
|
+
export interface TrackedInclude extends IncludeScopePosition {
|
|
274
297
|
prefix: string;
|
|
275
298
|
fullPrefix: string;
|
|
276
299
|
namePrefix?: string;
|
|
@@ -290,7 +313,7 @@ export type CachedHeaderScope = {
|
|
|
290
313
|
/**
|
|
291
314
|
* Context stored in AsyncLocalStorage
|
|
292
315
|
*/
|
|
293
|
-
interface HelperContext {
|
|
316
|
+
interface HelperContext extends IncludeScopePosition {
|
|
294
317
|
manifest: Map<string, EntryData>;
|
|
295
318
|
namespace: string;
|
|
296
319
|
parent: EntryData | null;
|
|
@@ -399,6 +422,37 @@ export declare function getNamePrefix(): string | undefined;
|
|
|
399
422
|
* Returns true at root or inside { name: "" } includes, false inside named includes.
|
|
400
423
|
*/
|
|
401
424
|
export declare function getRootScoped(): boolean;
|
|
425
|
+
/**
|
|
426
|
+
* The include scope a segment's dot-local `ctx.reverse(".name")` resolves in.
|
|
427
|
+
*
|
|
428
|
+
* One handler ctx serves every segment of a request and is built from the
|
|
429
|
+
* matched route's name (match-api.ts), so a parent module's layout resolved
|
|
430
|
+
* `.settings` from the matched CHILD module's prefix first: on
|
|
431
|
+
* `/acme/web/issues` the account layout's `.settings` hit the project
|
|
432
|
+
* module's route. Structural entries (layout, cache, parallel, wrapping
|
|
433
|
+
* middleware) and the loaders they declare capture the scope where the DSL
|
|
434
|
+
* defined them. Their handler gets a ctx whose `reverse` carries it
|
|
435
|
+
* (withReverseScope, router/handler-context.ts), and their loaders' DSL
|
|
436
|
+
* kickoff carries it in the loader scope (runInsideLoaderScope) for the
|
|
437
|
+
* loader ctx the executor builds. Global names and mount-param autofill do
|
|
438
|
+
* not change.
|
|
439
|
+
*/
|
|
440
|
+
export interface ReverseScope {
|
|
441
|
+
/** Include name prefix ("account.project"); undefined outside named includes. */
|
|
442
|
+
readonly prefix: string | undefined;
|
|
443
|
+
/** getRootScoped() where the segment was defined: bare-name fallback allowed. */
|
|
444
|
+
readonly rootScoped: boolean;
|
|
445
|
+
}
|
|
446
|
+
/** The ReverseScope of the DSL position being evaluated. */
|
|
447
|
+
export declare function getReverseScope(): ReverseScope;
|
|
448
|
+
/**
|
|
449
|
+
* A createReverseFunction result (router/handler-context.ts). The internal
|
|
450
|
+
* 4th argument resolves dot names in a segment's ReverseScope instead of the
|
|
451
|
+
* route's name.
|
|
452
|
+
*/
|
|
453
|
+
export type ScopableReverse = (name: string, hrefParams?: Record<string, string>, search?: Record<string, unknown>, segmentScope?: ReverseScope) => string;
|
|
454
|
+
/** `reverse` with dot names resolved in `scope`, if any. */
|
|
455
|
+
export declare function scopeReverse(reverse: ScopableReverse, scope: ReverseScope | undefined): ScopableReverse;
|
|
402
456
|
/**
|
|
403
457
|
* Stamp build-time scope identity onto a Static() definition at mount time.
|
|
404
458
|
* The bake collector (prerender-collection.ts) renders defs OUTSIDE any
|
|
@@ -689,7 +743,13 @@ export declare function assertCachedHeaderWriteAllowed(surface: string, surfaceP
|
|
|
689
743
|
* are bypassed because loaders are always fresh (never cached) and
|
|
690
744
|
* their side effects (setCookie, header, etc.) are safe.
|
|
691
745
|
*/
|
|
692
|
-
export declare function runInsideLoaderScope<T>(fn: () => T, loaderId?: string): T;
|
|
746
|
+
export declare function runInsideLoaderScope<T>(fn: () => T, loaderId?: string, reverseScope?: ReverseScope): T;
|
|
747
|
+
/**
|
|
748
|
+
* The ReverseScope of the DSL loader kickoff around this call: a loader the
|
|
749
|
+
* kickoff starts, and one its body starts with ctx.use(), resolve dot names
|
|
750
|
+
* in it. A handler's ctx.use(Loader) runs outside any kickoff: none.
|
|
751
|
+
*/
|
|
752
|
+
export declare function getLoaderReverseScope(): ReverseScope | undefined;
|
|
693
753
|
/**
|
|
694
754
|
* The loader whose run a handle push here belongs to, for the browser's
|
|
695
755
|
* merge of a partial response (handles/pushed-by.ts): the DSL loader
|