@rangojs/router 0.27.0 → 0.29.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 +1 -1
- package/dist/types/__internal.d.ts +7 -1
- package/dist/types/browser/action-fence.d.ts +2 -1
- package/dist/types/browser/event-controller.d.ts +8 -2
- package/dist/types/browser/history-state.d.ts +3 -9
- package/dist/types/browser/navigation-store.d.ts +8 -6
- package/dist/types/browser/partial-update.d.ts +11 -0
- package/dist/types/browser/react/filter-segment-order.d.ts +2 -2
- package/dist/types/browser/react/use-action.d.ts +7 -2
- package/dist/types/browser/react/use-handle.d.ts +19 -16
- package/dist/types/browser/react/use-link-status.d.ts +5 -2
- package/dist/types/browser/segment-reconciler.d.ts +32 -4
- package/dist/types/browser/types.d.ts +24 -5
- package/dist/types/browser/wire-protocol.d.ts +26 -0
- package/dist/types/cache/cache-key-utils.d.ts +11 -5
- package/dist/types/cache/cache-scope.d.ts +34 -22
- package/dist/types/cache/cf/cf-cache-constants.d.ts +2 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +47 -65
- package/dist/types/cache/cf/cf-kv-utils.d.ts +1 -1
- package/dist/types/cache/handle-snapshot.d.ts +9 -4
- package/dist/types/cache/segment-codec.d.ts +14 -0
- package/dist/types/cache/shell-snapshot.d.ts +1 -1
- package/dist/types/cache/taint.d.ts +5 -3
- package/dist/types/cache/types.d.ts +7 -3
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +8 -6
- package/dist/types/prefetch-markers.d.ts +5 -14
- package/dist/types/prerender/store.d.ts +31 -0
- package/dist/types/prerender/warm-request.d.ts +3 -3
- package/dist/types/prerender.d.ts +2 -2
- package/dist/types/route-name.d.ts +5 -0
- package/dist/types/router/error-handling.d.ts +11 -5
- package/dist/types/router/instrument.d.ts +4 -3
- package/dist/types/router/intercept-resolution.d.ts +25 -9
- package/dist/types/router/match-context.d.ts +6 -11
- package/dist/types/router/match-handlers.d.ts +2 -6
- package/dist/types/router/match-middleware/background-revalidation.d.ts +13 -22
- package/dist/types/router/match-middleware/cache-lookup.d.ts +34 -86
- package/dist/types/router/match-middleware/segment-resolution.d.ts +8 -6
- package/dist/types/router/navigation-snapshot.d.ts +7 -0
- package/dist/types/router/prerender-match.d.ts +21 -6
- package/dist/types/router/preview-match.d.ts +2 -7
- package/dist/types/router/request-classification.d.ts +5 -0
- package/dist/types/router/router-context.d.ts +7 -46
- package/dist/types/router/router-interfaces.d.ts +8 -14
- package/dist/types/router/segment-resolution/helpers.d.ts +19 -3
- package/dist/types/router/segment-resolution/loader-cache.d.ts +3 -3
- package/dist/types/router/segment-resolution/loader-mask.d.ts +4 -4
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +20 -18
- package/dist/types/router/segment-resolution/resolution-pass.d.ts +95 -0
- package/dist/types/router/segment-resolution/revalidation.d.ts +82 -31
- package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +2 -0
- package/dist/types/router/segment-resolution.d.ts +1 -2
- package/dist/types/router/segment-wrappers.d.ts +11 -48
- package/dist/types/router/telemetry.d.ts +2 -0
- package/dist/types/router/types.d.ts +11 -1
- package/dist/types/rsc/full-payload.d.ts +2 -2
- package/dist/types/rsc/handler-context.d.ts +6 -6
- package/dist/types/rsc/json-route-result.d.ts +5 -9
- package/dist/types/rsc/request-stages.d.ts +203 -0
- package/dist/types/rsc/response-cache-serve.d.ts +7 -12
- package/dist/types/rsc/response-route-handler.d.ts +2 -2
- package/dist/types/rsc/routine-plan.d.ts +1 -1
- package/dist/types/rsc/server-action.d.ts +2 -2
- package/dist/types/rsc/shell-capture-constants.d.ts +1 -1
- package/dist/types/rsc/shell-capture.d.ts +132 -15
- package/dist/types/rsc/shell-serve.d.ts +37 -12
- package/dist/types/server/context.d.ts +9 -8
- package/dist/types/server/handle-store.d.ts +16 -0
- package/dist/types/server/render-pass.d.ts +72 -0
- package/dist/types/server/request-context.d.ts +53 -104
- package/dist/types/server/rewrite-trail.d.ts +2 -2
- package/dist/types/testing/dispatch.d.ts +35 -18
- package/dist/types/testing/render-route.d.ts +43 -8
- package/dist/types/testing/serve-shell-request.d.ts +8 -1
- package/dist/types/types/cache-types.d.ts +6 -3
- package/dist/types/types/error-types.d.ts +30 -3
- package/dist/types/types/handler-context.d.ts +9 -1
- package/dist/types/types/segments.d.ts +1 -1
- package/dist/types/vite/discovery/build-discovery-phase.d.ts +40 -0
- package/dist/types/vite/discovery/build-env.d.ts +22 -0
- package/dist/types/vite/discovery/bundle-scan-phase.d.ts +12 -0
- package/dist/types/vite/discovery/dev-prerender-cache.d.ts +3 -2
- package/dist/types/vite/discovery/dev-server-phase.d.ts +26 -0
- package/dist/types/vite/discovery/discovery-errors.d.ts +1 -1
- package/dist/types/vite/discovery/state.d.ts +12 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +1 -1
- package/dist/types/vite/plugins/virtual-entries.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +8 -47
- package/dist/types/vite/temp-rsc-server.d.ts +39 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +9 -0
- package/dist/types/wire-params.d.ts +39 -0
- package/dist/vite/index.js +3822 -3727
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +8 -5
- package/skills/caching/SKILL.md +37 -18
- package/skills/client-urls/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +13 -1
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/hooks/SKILL.md +1 -1
- package/skills/hooks/data.md +8 -1
- package/skills/hooks/handle-and-actions.md +33 -2
- package/skills/hooks/navigation.md +121 -15
- package/skills/hooks/state.md +6 -4
- package/skills/hooks/urls.md +16 -5
- package/skills/intercept/SKILL.md +23 -7
- package/skills/middleware/SKILL.md +18 -0
- package/skills/observability/SKILL.md +30 -0
- package/skills/ppr/SKILL.md +18 -3
- package/skills/prerender/SKILL.md +39 -15
- package/skills/rango/SKILL.md +5 -1
- package/skills/server-actions/SKILL.md +15 -1
- package/skills/testing/client-components.md +25 -18
- package/skills/testing/response-routes.md +6 -4
- package/skills/testing/serve-shell-request.md +7 -7
- package/skills/use-cache/SKILL.md +46 -8
- package/skills/view-transitions/SKILL.md +1 -1
- package/src/__internal.ts +7 -1
- package/src/browser/action-fence.ts +2 -1
- package/src/browser/connection-warmup.ts +3 -1
- package/src/browser/event-controller.ts +37 -13
- package/src/browser/history-state.ts +6 -12
- package/src/browser/navigation-bridge.ts +59 -26
- package/src/browser/navigation-client.ts +20 -25
- package/src/browser/navigation-store.ts +25 -27
- package/src/browser/navigation-transaction.ts +4 -1
- package/src/browser/network-error-handler.ts +4 -0
- package/src/browser/partial-update.ts +33 -6
- package/src/browser/prefetch/cache.ts +2 -1
- package/src/browser/prefetch/fetch.ts +8 -16
- package/src/browser/prefetch/queue.ts +4 -4
- package/src/browser/react/NavigationProvider.tsx +2 -1
- package/src/browser/react/filter-segment-order.ts +2 -2
- package/src/browser/react/use-action.ts +24 -48
- package/src/browser/react/use-handle.ts +22 -18
- package/src/browser/react/use-link-status.ts +48 -60
- package/src/browser/react/use-navigation.ts +92 -41
- package/src/browser/rsc-router.tsx +1 -0
- package/src/browser/segment-reconciler.ts +109 -53
- package/src/browser/server-action-bridge.ts +81 -61
- package/src/browser/types.ts +25 -5
- package/src/browser/wire-protocol.ts +43 -0
- package/src/cache/cache-key-utils.ts +11 -5
- package/src/cache/cache-runtime.ts +132 -75
- package/src/cache/cache-scope.ts +110 -64
- package/src/cache/cf/cf-cache-constants.ts +2 -2
- package/src/cache/cf/cf-cache-store.ts +486 -874
- package/src/cache/cf/cf-kv-utils.ts +1 -1
- package/src/cache/document-cache.ts +64 -46
- package/src/cache/handle-snapshot.ts +19 -7
- package/src/cache/read-through-swr.ts +20 -18
- package/src/cache/segment-codec.ts +55 -0
- package/src/cache/shell-snapshot.ts +2 -2
- package/src/cache/tag-invalidation.ts +6 -2
- package/src/cache/taint.ts +5 -3
- package/src/cache/types.ts +7 -3
- package/src/cache/vercel/vercel-cache-store.ts +243 -310
- package/src/handles/pushed-by.ts +1 -1
- package/src/prefetch-markers.ts +5 -16
- package/src/prerender/store.ts +76 -0
- package/src/prerender/warm-request.ts +8 -4
- package/src/prerender.ts +2 -2
- package/src/route-name.ts +8 -0
- package/src/router/error-handling.ts +22 -10
- package/src/router/instrument.ts +4 -3
- package/src/router/intercept-resolution.ts +82 -75
- package/src/router/loader-resolution.ts +5 -4
- package/src/router/match-api.ts +5 -5
- package/src/router/match-context.ts +23 -12
- package/src/router/match-handlers.ts +8 -20
- package/src/router/match-middleware/background-revalidation.ts +46 -57
- package/src/router/match-middleware/cache-lookup.ts +677 -726
- package/src/router/match-middleware/cache-store.ts +4 -8
- package/src/router/match-middleware/intercept-resolution.ts +3 -23
- package/src/router/match-middleware/segment-resolution.ts +34 -61
- package/src/router/middleware.ts +69 -11
- package/src/router/navigation-snapshot.ts +14 -4
- package/src/router/prerender-match.ts +100 -44
- package/src/router/preview-match.ts +6 -41
- package/src/router/request-classification.ts +13 -7
- package/src/router/route-snapshot.ts +2 -5
- package/src/router/router-context.ts +10 -95
- package/src/router/router-interfaces.ts +8 -14
- package/src/router/segment-resolution/helpers.ts +49 -13
- package/src/router/segment-resolution/loader-cache.ts +15 -9
- package/src/router/segment-resolution/loader-mask.ts +5 -5
- package/src/router/segment-resolution/prefetch-deferral.ts +30 -27
- package/src/router/segment-resolution/resolution-pass.ts +139 -0
- package/src/router/segment-resolution/revalidation.ts +939 -789
- package/src/router/segment-resolution/streamed-handler-boundary.ts +3 -0
- package/src/router/segment-resolution.ts +4 -13
- package/src/router/segment-wrappers.ts +51 -269
- package/src/router/telemetry.ts +5 -0
- package/src/router/types.ts +11 -1
- package/src/router.ts +19 -17
- package/src/rsc/full-payload.ts +6 -5
- package/src/rsc/handler-context.ts +8 -14
- package/src/rsc/handler.ts +126 -507
- package/src/rsc/json-route-result.ts +5 -9
- package/src/rsc/loader-fetch.ts +6 -5
- package/src/rsc/progressive-enhancement.ts +5 -0
- package/src/rsc/request-stages.ts +759 -0
- package/src/rsc/response-cache-serve.ts +10 -14
- package/src/rsc/response-route-handler.ts +13 -5
- package/src/rsc/rewrite-passes.ts +2 -1
- package/src/rsc/routine-plan.ts +1 -1
- package/src/rsc/rsc-rendering.ts +164 -349
- package/src/rsc/server-action.ts +87 -113
- package/src/rsc/shell-capture-constants.ts +1 -1
- package/src/rsc/shell-capture.ts +275 -227
- package/src/rsc/shell-serve.ts +121 -18
- package/src/rsc/ssr-setup.ts +5 -4
- package/src/segment-system.tsx +3 -3
- package/src/server/context.ts +22 -25
- package/src/server/handle-store.ts +55 -0
- package/src/server/render-pass.ts +291 -0
- package/src/server/request-context.ts +75 -115
- package/src/server/rewrite-trail.ts +6 -4
- package/src/ssr/index.tsx +1 -1
- package/src/testing/dispatch.ts +226 -710
- package/src/testing/e2e/page-helpers.ts +2 -2
- package/src/testing/render-route.tsx +199 -13
- package/src/testing/serve-shell-request.ts +36 -40
- package/src/types/cache-types.ts +6 -3
- package/src/types/error-types.ts +30 -3
- package/src/types/handler-context.ts +12 -1
- package/src/types/segments.ts +1 -1
- package/src/vite/discovery/build-discovery-phase.ts +204 -0
- package/src/vite/discovery/build-env.ts +148 -0
- package/src/vite/discovery/bundle-scan-phase.ts +128 -0
- package/src/vite/discovery/dev-prerender-cache.ts +8 -3
- package/src/vite/discovery/dev-server-phase.ts +1776 -0
- package/src/vite/discovery/discover-routers.ts +1 -1
- package/src/vite/discovery/discovery-errors.ts +1 -1
- package/src/vite/discovery/prerender-collection.ts +24 -39
- package/src/vite/discovery/state.ts +15 -0
- package/src/vite/plugins/version-plugin.ts +1 -1
- package/src/vite/plugins/virtual-entries.ts +1 -1
- package/src/vite/router-discovery.ts +29 -2428
- package/src/vite/temp-rsc-server.ts +223 -0
- package/src/vite/utils/prerender-utils.ts +47 -0
- package/src/wire-params.ts +40 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +0 -72
- package/src/router/segment-resolution/fresh.ts +0 -945
|
@@ -44,6 +44,8 @@ export interface StreamedHandlerOptions<TEnv> {
|
|
|
44
44
|
context: HandlerContext<any, TEnv>;
|
|
45
45
|
routeKey?: string;
|
|
46
46
|
params: Record<string, string>;
|
|
47
|
+
/** onError's `isPartial`, as the walk reports a sync handler's error. */
|
|
48
|
+
isPartial: true | undefined;
|
|
47
49
|
/** False where the rejection must reach the caller (prerender, intercept background re-render). */
|
|
48
50
|
recover: boolean;
|
|
49
51
|
}
|
|
@@ -64,6 +66,7 @@ export function trackStreamedHandler<TEnv>(
|
|
|
64
66
|
const tracked = deps.trackHandler(result as Promise<ReactNode>, {
|
|
65
67
|
segmentId,
|
|
66
68
|
segmentType,
|
|
69
|
+
isPartial: options.isPartial,
|
|
67
70
|
});
|
|
68
71
|
observeStreamedHandler(
|
|
69
72
|
tracked,
|
|
@@ -5,20 +5,11 @@ export {
|
|
|
5
5
|
buildLoaderErrorContext,
|
|
6
6
|
} from "./segment-resolution/helpers.js";
|
|
7
7
|
export {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
resolveLoadersOnly,
|
|
9
|
+
buildEntryRevalidateMap,
|
|
10
|
+
resolveParallelSegments,
|
|
11
|
+
resolveEntryHandler,
|
|
10
12
|
resolveSegment,
|
|
11
13
|
resolveOrphanLayout,
|
|
12
|
-
resolveParallelEntry,
|
|
13
14
|
resolveAllSegments,
|
|
14
|
-
resolveLoadersOnly,
|
|
15
|
-
} from "./segment-resolution/fresh.js";
|
|
16
|
-
export {
|
|
17
|
-
resolveLoadersOnlyWithRevalidation,
|
|
18
|
-
buildEntryRevalidateMap,
|
|
19
|
-
resolveParallelSegmentsWithRevalidation,
|
|
20
|
-
resolveEntryHandlerWithRevalidation,
|
|
21
|
-
resolveSegmentWithRevalidation,
|
|
22
|
-
resolveOrphanLayoutWithRevalidation,
|
|
23
|
-
resolveAllSegmentsWithRevalidation,
|
|
24
15
|
} from "./segment-resolution/revalidation.js";
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
import type { EntryData, InterceptEntry } from "../server/context";
|
|
2
|
-
import type {
|
|
3
|
-
HandlerContext,
|
|
4
|
-
ResolvedSegment,
|
|
5
|
-
ShouldRevalidateFn,
|
|
6
|
-
} from "../types";
|
|
7
1
|
import type { SegmentResolutionDeps } from "./types.js";
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
2
|
+
import type { RouterContext } from "./router-context.js";
|
|
3
|
+
import type {
|
|
4
|
+
ResolutionPass,
|
|
5
|
+
ResolutionPassInput,
|
|
6
|
+
} from "./segment-resolution/resolution-pass.js";
|
|
10
7
|
|
|
11
8
|
import {
|
|
12
|
-
resolveAllSegments as _resolveAllSegments,
|
|
13
9
|
resolveLoadersOnly as _resolveLoadersOnly,
|
|
14
|
-
resolveLoadersOnlyWithRevalidation as _resolveLoadersOnlyWithRevalidation,
|
|
15
10
|
buildEntryRevalidateMap as _buildEntryRevalidateMap,
|
|
16
|
-
|
|
11
|
+
resolveAllSegments as _resolveAllSegments,
|
|
17
12
|
} from "./segment-resolution.js";
|
|
18
13
|
|
|
19
14
|
import {
|
|
@@ -22,270 +17,57 @@ import {
|
|
|
22
17
|
resolveInterceptLoadersOnly as _resolveInterceptLoadersOnly,
|
|
23
18
|
} from "./intercept-resolution.js";
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
resolveAllSegments
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
entries: EntryData[],
|
|
42
|
-
context: HandlerContext<any, TEnv>,
|
|
43
|
-
clientSegmentIds: Set<string>,
|
|
44
|
-
prevParams: Record<string, string>,
|
|
45
|
-
request: Request,
|
|
46
|
-
prevUrl: URL,
|
|
47
|
-
nextUrl: URL,
|
|
48
|
-
routeKey: string,
|
|
49
|
-
actionContext?: {
|
|
50
|
-
actionId?: string;
|
|
51
|
-
actionUrl?: URL;
|
|
52
|
-
actionResult?: any;
|
|
53
|
-
formData?: FormData;
|
|
54
|
-
},
|
|
55
|
-
stale?: boolean,
|
|
56
|
-
) => Promise<{ segments: ResolvedSegment[]; matchedIds: string[] }>;
|
|
57
|
-
buildEntryRevalidateMap: (
|
|
58
|
-
entries: EntryData[],
|
|
59
|
-
) => Map<
|
|
60
|
-
string,
|
|
61
|
-
{ entry: EntryData; revalidate: ShouldRevalidateFn<any, any>[] }
|
|
62
|
-
>;
|
|
63
|
-
resolveAllSegmentsWithRevalidation: (
|
|
64
|
-
entries: EntryData[],
|
|
65
|
-
routeKey: string,
|
|
66
|
-
params: Record<string, string>,
|
|
67
|
-
context: HandlerContext<any, TEnv>,
|
|
68
|
-
clientSegmentSet: Set<string>,
|
|
69
|
-
prevParams: Record<string, string>,
|
|
70
|
-
request: Request,
|
|
71
|
-
prevUrl: URL,
|
|
72
|
-
nextUrl: URL,
|
|
73
|
-
actionContext:
|
|
74
|
-
| {
|
|
75
|
-
actionId?: string;
|
|
76
|
-
actionUrl?: URL;
|
|
77
|
-
actionResult?: any;
|
|
78
|
-
formData?: FormData;
|
|
79
|
-
}
|
|
80
|
-
| undefined,
|
|
81
|
-
interceptResult: { intercept: InterceptEntry; entry: EntryData } | null,
|
|
82
|
-
localRouteName: string,
|
|
83
|
-
pathname: string,
|
|
84
|
-
stale?: boolean,
|
|
85
|
-
chain?: readonly EntryData[],
|
|
86
|
-
) => Promise<{ segments: ResolvedSegment[]; matchedIds: string[] }>;
|
|
87
|
-
findInterceptForRoute: (
|
|
88
|
-
targetRouteKey: string,
|
|
89
|
-
fromEntry: EntryData | null,
|
|
90
|
-
selectorContext?: InterceptSelectorContext | null,
|
|
91
|
-
isAction?: boolean,
|
|
92
|
-
) => { intercept: InterceptEntry; entry: EntryData } | null;
|
|
93
|
-
resolveInterceptEntry: (
|
|
94
|
-
interceptEntry: InterceptEntry,
|
|
95
|
-
parentEntry: EntryData,
|
|
96
|
-
params: Record<string, string>,
|
|
97
|
-
context: HandlerContext<any, TEnv>,
|
|
98
|
-
belongsToRoute?: boolean,
|
|
99
|
-
revalidationContext?: any,
|
|
100
|
-
options?: { background?: boolean },
|
|
101
|
-
) => Promise<ResolvedSegment[]>;
|
|
102
|
-
resolveInterceptLoadersOnly: (
|
|
103
|
-
interceptEntry: InterceptEntry,
|
|
104
|
-
parentEntry: EntryData,
|
|
105
|
-
context: HandlerContext<any, TEnv>,
|
|
106
|
-
belongsToRoute: boolean,
|
|
107
|
-
revalidationContext: RevalidationContext,
|
|
108
|
-
) => Promise<ResolvedSegment[]>;
|
|
109
|
-
}
|
|
20
|
+
/** The resolvers RouterContext exposes, with the router's deps bound. */
|
|
21
|
+
export type SegmentWrappers<TEnv = any> = Pick<
|
|
22
|
+
RouterContext<TEnv>,
|
|
23
|
+
"resolveAllSegments" | "resolveInterceptEntry"
|
|
24
|
+
> &
|
|
25
|
+
Required<
|
|
26
|
+
Pick<
|
|
27
|
+
RouterContext<TEnv>,
|
|
28
|
+
| "resolveLoadersOnly"
|
|
29
|
+
| "buildEntryRevalidateMap"
|
|
30
|
+
| "resolveInterceptLoadersOnly"
|
|
31
|
+
>
|
|
32
|
+
> & {
|
|
33
|
+
/** Its own signature: a null selector context, isAction defaulting to false. */
|
|
34
|
+
findInterceptForRoute: typeof _findInterceptForRoute;
|
|
35
|
+
};
|
|
110
36
|
|
|
111
37
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* These maintain the same signatures as the original inline functions
|
|
116
|
-
* so that RouterContext and call sites don't need to change.
|
|
38
|
+
* Bind the router's segment deps into the extracted segment and intercept
|
|
39
|
+
* resolvers. Each gets a ResolutionPass: the caller's request-side input with
|
|
40
|
+
* the deps added here, once per call.
|
|
117
41
|
*/
|
|
118
42
|
export function createSegmentWrappers<TEnv = any>(
|
|
119
|
-
|
|
43
|
+
deps: SegmentResolutionDeps<TEnv>,
|
|
120
44
|
): SegmentWrappers<TEnv> {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
context: HandlerContext<any, TEnv>,
|
|
126
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
127
|
-
options?: ResolveSegmentOptions,
|
|
128
|
-
): ReturnType<typeof _resolveAllSegments> {
|
|
129
|
-
return _resolveAllSegments(
|
|
130
|
-
entries,
|
|
131
|
-
routeKey,
|
|
132
|
-
params,
|
|
133
|
-
context,
|
|
134
|
-
loaderPromises,
|
|
135
|
-
segmentDeps,
|
|
136
|
-
options,
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function resolveLoadersOnly(
|
|
141
|
-
entries: EntryData[],
|
|
142
|
-
context: HandlerContext<any, TEnv>,
|
|
143
|
-
): ReturnType<typeof _resolveLoadersOnly> {
|
|
144
|
-
return _resolveLoadersOnly(entries, context, segmentDeps);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function resolveLoadersOnlyWithRevalidation(
|
|
148
|
-
entries: EntryData[],
|
|
149
|
-
context: HandlerContext<any, TEnv>,
|
|
150
|
-
clientSegmentIds: Set<string>,
|
|
151
|
-
prevParams: Record<string, string>,
|
|
152
|
-
request: Request,
|
|
153
|
-
prevUrl: URL,
|
|
154
|
-
nextUrl: URL,
|
|
155
|
-
routeKey: string,
|
|
156
|
-
actionContext?: {
|
|
157
|
-
actionId?: string;
|
|
158
|
-
actionUrl?: URL;
|
|
159
|
-
actionResult?: any;
|
|
160
|
-
formData?: FormData;
|
|
161
|
-
},
|
|
162
|
-
stale?: boolean,
|
|
163
|
-
): ReturnType<typeof _resolveLoadersOnlyWithRevalidation> {
|
|
164
|
-
return _resolveLoadersOnlyWithRevalidation(
|
|
165
|
-
entries,
|
|
166
|
-
context,
|
|
167
|
-
clientSegmentIds,
|
|
168
|
-
prevParams,
|
|
169
|
-
request,
|
|
170
|
-
prevUrl,
|
|
171
|
-
nextUrl,
|
|
172
|
-
routeKey,
|
|
173
|
-
segmentDeps,
|
|
174
|
-
actionContext,
|
|
175
|
-
stale,
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function buildEntryRevalidateMap(
|
|
180
|
-
entries: EntryData[],
|
|
181
|
-
): ReturnType<typeof _buildEntryRevalidateMap> {
|
|
182
|
-
return _buildEntryRevalidateMap(entries);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function resolveAllSegmentsWithRevalidation(
|
|
186
|
-
entries: EntryData[],
|
|
187
|
-
routeKey: string,
|
|
188
|
-
params: Record<string, string>,
|
|
189
|
-
context: HandlerContext<any, TEnv>,
|
|
190
|
-
clientSegmentSet: Set<string>,
|
|
191
|
-
prevParams: Record<string, string>,
|
|
192
|
-
request: Request,
|
|
193
|
-
prevUrl: URL,
|
|
194
|
-
nextUrl: URL,
|
|
195
|
-
actionContext:
|
|
196
|
-
| {
|
|
197
|
-
actionId?: string;
|
|
198
|
-
actionUrl?: URL;
|
|
199
|
-
actionResult?: any;
|
|
200
|
-
formData?: FormData;
|
|
201
|
-
}
|
|
202
|
-
| undefined,
|
|
203
|
-
interceptResult: { intercept: InterceptEntry; entry: EntryData } | null,
|
|
204
|
-
localRouteName: string,
|
|
205
|
-
pathname: string,
|
|
206
|
-
stale?: boolean,
|
|
207
|
-
chain?: readonly EntryData[],
|
|
208
|
-
): ReturnType<typeof _resolveAllSegmentsWithRevalidation> {
|
|
209
|
-
return _resolveAllSegmentsWithRevalidation(
|
|
210
|
-
entries,
|
|
211
|
-
routeKey,
|
|
212
|
-
params,
|
|
213
|
-
context,
|
|
214
|
-
clientSegmentSet,
|
|
215
|
-
prevParams,
|
|
216
|
-
request,
|
|
217
|
-
prevUrl,
|
|
218
|
-
nextUrl,
|
|
219
|
-
actionContext,
|
|
220
|
-
interceptResult,
|
|
221
|
-
localRouteName,
|
|
222
|
-
pathname,
|
|
223
|
-
segmentDeps,
|
|
224
|
-
stale,
|
|
225
|
-
chain,
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function findInterceptForRoute(
|
|
230
|
-
targetRouteKey: string,
|
|
231
|
-
fromEntry: EntryData | null,
|
|
232
|
-
selectorContext: InterceptSelectorContext | null = null,
|
|
233
|
-
isAction: boolean = false,
|
|
234
|
-
): ReturnType<typeof _findInterceptForRoute> {
|
|
235
|
-
return _findInterceptForRoute(
|
|
236
|
-
targetRouteKey,
|
|
237
|
-
fromEntry,
|
|
238
|
-
selectorContext,
|
|
239
|
-
isAction,
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function resolveInterceptEntry(
|
|
244
|
-
interceptEntry: InterceptEntry,
|
|
245
|
-
parentEntry: EntryData,
|
|
246
|
-
params: Record<string, string>,
|
|
247
|
-
context: HandlerContext<any, TEnv>,
|
|
248
|
-
belongsToRoute: boolean = true,
|
|
249
|
-
revalidationContext?: any,
|
|
250
|
-
options?: { background?: boolean },
|
|
251
|
-
): ReturnType<typeof _resolveInterceptEntry> {
|
|
252
|
-
return _resolveInterceptEntry(
|
|
253
|
-
interceptEntry,
|
|
254
|
-
parentEntry,
|
|
255
|
-
params,
|
|
256
|
-
context,
|
|
257
|
-
belongsToRoute,
|
|
258
|
-
segmentDeps,
|
|
259
|
-
revalidationContext,
|
|
260
|
-
options,
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function resolveInterceptLoadersOnly(
|
|
265
|
-
interceptEntry: InterceptEntry,
|
|
266
|
-
parentEntry: EntryData,
|
|
267
|
-
context: HandlerContext<any, TEnv>,
|
|
268
|
-
belongsToRoute: boolean,
|
|
269
|
-
revalidationContext: RevalidationContext,
|
|
270
|
-
): ReturnType<typeof _resolveInterceptLoadersOnly> {
|
|
271
|
-
return _resolveInterceptLoadersOnly(
|
|
272
|
-
interceptEntry,
|
|
273
|
-
parentEntry,
|
|
274
|
-
context,
|
|
275
|
-
belongsToRoute,
|
|
276
|
-
segmentDeps,
|
|
277
|
-
revalidationContext,
|
|
278
|
-
);
|
|
279
|
-
}
|
|
45
|
+
const pass = (input: ResolutionPassInput<TEnv>): ResolutionPass<TEnv> => ({
|
|
46
|
+
...input,
|
|
47
|
+
deps,
|
|
48
|
+
});
|
|
280
49
|
|
|
281
50
|
return {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
findInterceptForRoute:
|
|
288
|
-
resolveInterceptEntry:
|
|
289
|
-
|
|
51
|
+
resolveLoadersOnly: (input, entries, walk) =>
|
|
52
|
+
_resolveLoadersOnly(pass(input), entries, walk),
|
|
53
|
+
buildEntryRevalidateMap: _buildEntryRevalidateMap,
|
|
54
|
+
resolveAllSegments: (input, entries, walk) =>
|
|
55
|
+
_resolveAllSegments(pass(input), entries, walk),
|
|
56
|
+
findInterceptForRoute: _findInterceptForRoute,
|
|
57
|
+
resolveInterceptEntry: (input, intercept, entry, belongsToRoute, options) =>
|
|
58
|
+
_resolveInterceptEntry(
|
|
59
|
+
pass(input),
|
|
60
|
+
intercept,
|
|
61
|
+
entry,
|
|
62
|
+
belongsToRoute,
|
|
63
|
+
options,
|
|
64
|
+
),
|
|
65
|
+
resolveInterceptLoadersOnly: (input, intercept, entry, belongsToRoute) =>
|
|
66
|
+
_resolveInterceptLoadersOnly(
|
|
67
|
+
pass(input),
|
|
68
|
+
intercept,
|
|
69
|
+
entry,
|
|
70
|
+
belongsToRoute,
|
|
71
|
+
),
|
|
290
72
|
};
|
|
291
73
|
}
|
package/src/router/telemetry.ts
CHANGED
|
@@ -317,6 +317,11 @@ export function getRequestId(request: Request): string {
|
|
|
317
317
|
return id;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
+
/** Make `id` the id getRequestId returns for `request`. */
|
|
321
|
+
export function setRequestId(request: Request, id: string): void {
|
|
322
|
+
requestIds.set(request, id);
|
|
323
|
+
}
|
|
324
|
+
|
|
320
325
|
/**
|
|
321
326
|
* Built-in console sink that logs events in a structured format.
|
|
322
327
|
* Designed as the default sink for development / debugging.
|
package/src/router/types.ts
CHANGED
|
@@ -32,6 +32,16 @@ export type ActionContext = {
|
|
|
32
32
|
actionUrl?: URL;
|
|
33
33
|
actionResult?: any;
|
|
34
34
|
formData?: FormData;
|
|
35
|
+
/**
|
|
36
|
+
* A thrown action's error segment (matchError), set on the action's
|
|
37
|
+
* revalidation (rsc/server-action.ts matchBoundaryRevalidation). The walk
|
|
38
|
+
* (resolveAllSegments) resolves every entry above the segment's outlet as on
|
|
39
|
+
* a success, emits the segment in the outlet's place and stops, so nothing
|
|
40
|
+
* at or below the outlet runs. The pass skips the prerender store
|
|
41
|
+
* (cache-lookup.ts): the evicted handler is under the cut. No revalidate()
|
|
42
|
+
* predicate sees it.
|
|
43
|
+
*/
|
|
44
|
+
boundary?: ResolvedSegment;
|
|
35
45
|
};
|
|
36
46
|
|
|
37
47
|
export interface SegmentResolutionDeps<TEnv = any> {
|
|
@@ -47,7 +57,6 @@ export interface SegmentResolutionDeps<TEnv = any> {
|
|
|
47
57
|
params?: Record<string, string>;
|
|
48
58
|
env?: TEnv;
|
|
49
59
|
isPartial?: boolean;
|
|
50
|
-
requestStartTime?: number;
|
|
51
60
|
},
|
|
52
61
|
/** An `ssr: false` loader on a document or capture render. */
|
|
53
62
|
useDefaultErrorBoundary?: boolean,
|
|
@@ -57,6 +66,7 @@ export interface SegmentResolutionDeps<TEnv = any> {
|
|
|
57
66
|
errorContext?: {
|
|
58
67
|
segmentId?: string;
|
|
59
68
|
segmentType?: string;
|
|
69
|
+
isPartial?: boolean;
|
|
60
70
|
},
|
|
61
71
|
) => Promise<T>;
|
|
62
72
|
findNearestErrorBoundary: (
|
package/src/router.ts
CHANGED
|
@@ -44,6 +44,7 @@ import { createHandleStore, type HandleStore } from "./server/handle-store.js";
|
|
|
44
44
|
import {
|
|
45
45
|
getRequestContext,
|
|
46
46
|
_getRequestContext,
|
|
47
|
+
reportedErrorsOf,
|
|
47
48
|
} from "./server/request-context.js";
|
|
48
49
|
import type {
|
|
49
50
|
ErrorPhase,
|
|
@@ -315,7 +316,8 @@ export function createRouter<TEnv = any>(
|
|
|
315
316
|
* Wrapper for invokeOnError that binds the router's onError callback.
|
|
316
317
|
* Uses the shared utility from router/error-handling.ts for consistent behavior.
|
|
317
318
|
*
|
|
318
|
-
* Deduplicates via per-request WeakSet stored on the ALS request context
|
|
319
|
+
* Deduplicates via per-request WeakSet stored on the ALS request context
|
|
320
|
+
* (background work keeps its own, reportedErrorsOf).
|
|
319
321
|
* A closure-level WeakSet would silently swallow errors if the same object
|
|
320
322
|
* instance is thrown across separate requests (e.g. a singleton error).
|
|
321
323
|
*/
|
|
@@ -325,7 +327,8 @@ export function createRouter<TEnv = any>(
|
|
|
325
327
|
context: Parameters<typeof invokeOnError<TEnv>>[3],
|
|
326
328
|
): void {
|
|
327
329
|
if (error != null && typeof error === "object") {
|
|
328
|
-
const
|
|
330
|
+
const reqCtx = _getRequestContext();
|
|
331
|
+
const reportedErrors = reqCtx && reportedErrorsOf(reqCtx);
|
|
329
332
|
if (reportedErrors) {
|
|
330
333
|
if (reportedErrors.has(error)) return;
|
|
331
334
|
reportedErrors.add(error);
|
|
@@ -488,6 +491,7 @@ export function createRouter<TEnv = any>(
|
|
|
488
491
|
errorContext?: {
|
|
489
492
|
segmentId?: string;
|
|
490
493
|
segmentType?: string;
|
|
494
|
+
isPartial?: boolean;
|
|
491
495
|
},
|
|
492
496
|
): Promise<T> => {
|
|
493
497
|
// One ALS read serves both the store lookup and the onError closure.
|
|
@@ -520,6 +524,7 @@ export function createRouter<TEnv = any>(
|
|
|
520
524
|
env: reqCtx.env as TEnv,
|
|
521
525
|
segmentId: errorContext?.segmentId,
|
|
522
526
|
segmentType: errorContext?.segmentType as any,
|
|
527
|
+
isPartial: errorContext?.isPartial,
|
|
523
528
|
handledByBoundary: true,
|
|
524
529
|
});
|
|
525
530
|
});
|
|
@@ -542,22 +547,24 @@ export function createRouter<TEnv = any>(
|
|
|
542
547
|
params?: Record<string, string>;
|
|
543
548
|
env?: TEnv;
|
|
544
549
|
isPartial?: boolean;
|
|
545
|
-
requestStartTime?: number;
|
|
546
550
|
},
|
|
547
551
|
useDefaultErrorBoundary?: boolean,
|
|
548
552
|
): Promise<LoaderDataResult<T>> {
|
|
549
|
-
|
|
550
|
-
const
|
|
553
|
+
// A PPR shell capture sends nothing to the sink: the same switch as match().
|
|
554
|
+
const emitTelemetry =
|
|
555
|
+
!!telemetrySink && !_getRequestContext()?._shellCaptureState?.run;
|
|
556
|
+
const loaderStart = emitTelemetry ? performance.now() : 0;
|
|
557
|
+
const loaderRequestId = emitTelemetry
|
|
551
558
|
? errorContext?.request
|
|
552
559
|
? getRequestId(errorContext.request)
|
|
553
560
|
: undefined
|
|
554
561
|
: undefined;
|
|
555
562
|
// Derived once here for both the loader.start and loader.end emits (the
|
|
556
563
|
// loader.error emit uses ctx.loaderName from wrapLoaderWithErrorHandling).
|
|
557
|
-
const loaderName =
|
|
564
|
+
const loaderName = emitTelemetry
|
|
558
565
|
? segmentId.split(".").pop() || "unknown"
|
|
559
566
|
: "";
|
|
560
|
-
if (
|
|
567
|
+
if (emitTelemetry) {
|
|
561
568
|
safeEmit(telemetry, {
|
|
562
569
|
type: "loader.start",
|
|
563
570
|
timestamp: loaderStart,
|
|
@@ -589,9 +596,8 @@ export function createRouter<TEnv = any>(
|
|
|
589
596
|
env: errorContext.env,
|
|
590
597
|
isPartial: errorContext.isPartial,
|
|
591
598
|
handledByBoundary: ctx.handledByBoundary,
|
|
592
|
-
requestStartTime: errorContext.requestStartTime,
|
|
593
599
|
});
|
|
594
|
-
if (
|
|
600
|
+
if (emitTelemetry) {
|
|
595
601
|
const errorObj =
|
|
596
602
|
error instanceof Error ? error : new Error(String(error));
|
|
597
603
|
safeEmit(telemetry, {
|
|
@@ -618,7 +624,7 @@ export function createRouter<TEnv = any>(
|
|
|
618
624
|
);
|
|
619
625
|
|
|
620
626
|
// Emit loader.end after the promise settles (fire-and-forget)
|
|
621
|
-
if (
|
|
627
|
+
if (emitTelemetry) {
|
|
622
628
|
result.then((r) => {
|
|
623
629
|
safeEmit(telemetry, {
|
|
624
630
|
type: "loader.end",
|
|
@@ -663,11 +669,9 @@ export function createRouter<TEnv = any>(
|
|
|
663
669
|
|
|
664
670
|
// Create segment resolution wrappers bound to segmentDeps
|
|
665
671
|
const {
|
|
666
|
-
resolveAllSegments,
|
|
667
672
|
resolveLoadersOnly,
|
|
668
|
-
resolveLoadersOnlyWithRevalidation,
|
|
669
673
|
buildEntryRevalidateMap,
|
|
670
|
-
|
|
674
|
+
resolveAllSegments,
|
|
671
675
|
findInterceptForRoute,
|
|
672
676
|
resolveInterceptEntry,
|
|
673
677
|
resolveInterceptLoadersOnly,
|
|
@@ -713,16 +717,14 @@ export function createRouter<TEnv = any>(
|
|
|
713
717
|
getMetricsStore,
|
|
714
718
|
createCacheScope,
|
|
715
719
|
findInterceptForRoute,
|
|
716
|
-
|
|
720
|
+
resolveAllSegments,
|
|
717
721
|
resolveInterceptEntry,
|
|
718
722
|
evaluateRevalidation,
|
|
719
723
|
getRequestContext,
|
|
720
|
-
resolveAllSegments,
|
|
721
724
|
createHandleStore,
|
|
722
725
|
buildEntryRevalidateMap,
|
|
723
|
-
resolveLoadersOnlyWithRevalidation,
|
|
724
|
-
resolveInterceptLoadersOnly,
|
|
725
726
|
resolveLoadersOnly,
|
|
727
|
+
resolveInterceptLoadersOnly,
|
|
726
728
|
telemetry: telemetrySink,
|
|
727
729
|
};
|
|
728
730
|
}
|
package/src/rsc/full-payload.ts
CHANGED
|
@@ -61,7 +61,7 @@ export function buildFullPayload(
|
|
|
61
61
|
// capture renders from what its record keeps (resolvedHandleStream).
|
|
62
62
|
handles: resolvedHandleStream(
|
|
63
63
|
handleStore,
|
|
64
|
-
reqCtx.
|
|
64
|
+
reqCtx._shellCaptureState?.run === true,
|
|
65
65
|
),
|
|
66
66
|
// Post-handler-barrier pushes (streaming loader ctx.handle() writes)
|
|
67
67
|
// stream here; the client applies them after hydration. Instantly
|
|
@@ -105,8 +105,7 @@ export function renderedLocation(
|
|
|
105
105
|
| Pick<
|
|
106
106
|
RequestContext<any>,
|
|
107
107
|
| "_variables"
|
|
108
|
-
| "
|
|
109
|
-
| "_shellCaptureForVisitor"
|
|
108
|
+
| "_shellCaptureState"
|
|
110
109
|
| "_documentCacheRender"
|
|
111
110
|
| "_payloadVisitorLocation"
|
|
112
111
|
| "res"
|
|
@@ -116,7 +115,9 @@ export function renderedLocation(
|
|
|
116
115
|
): URL {
|
|
117
116
|
if (!reqCtx || !rewriteTrail(reqCtx)) return url;
|
|
118
117
|
if (rendersForSharedAudience(reqCtx)) {
|
|
119
|
-
return reqCtx.
|
|
118
|
+
return reqCtx._shellCaptureState?.forVisitor
|
|
119
|
+
? visitorUrl(reqCtx, url)
|
|
120
|
+
: url;
|
|
120
121
|
}
|
|
121
122
|
reqCtx._payloadVisitorLocation = true;
|
|
122
123
|
return visitorUrl(reqCtx, url);
|
|
@@ -163,7 +164,7 @@ export function payloadInitialTheme(
|
|
|
163
164
|
reqCtx: Pick<
|
|
164
165
|
RequestContext<any>,
|
|
165
166
|
| "_themeConfig"
|
|
166
|
-
| "
|
|
167
|
+
| "_shellCaptureState"
|
|
167
168
|
| "_readTheme"
|
|
168
169
|
| "_documentCacheRender"
|
|
169
170
|
| "_payloadVisitorTheme"
|
|
@@ -7,12 +7,17 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { RangoInternal } from "../router/router-interfaces.js";
|
|
10
|
-
import type { ErrorPhase } from "../types.js";
|
|
11
|
-
import type { InvokeOnErrorContext } from "../router/error-handling.js";
|
|
12
10
|
import type { RSCDependencies, LoadSSRModule } from "./types.js";
|
|
13
11
|
import type { SSRStreamMode } from "../router/router-options.js";
|
|
12
|
+
import type { RequestStageContext } from "./request-stages.js";
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Extends what the request stages (rsc/request-stages.ts) call back into, so
|
|
16
|
+
* the handler hands this one bundle to them as well.
|
|
17
|
+
*/
|
|
18
|
+
export interface HandlerContext<
|
|
19
|
+
TEnv = unknown,
|
|
20
|
+
> extends RequestStageContext<TEnv> {
|
|
16
21
|
router: RangoInternal<TEnv, any>;
|
|
17
22
|
/**
|
|
18
23
|
* The router's DOCUMENT version (router-versions.ts): payload metadata, the
|
|
@@ -28,17 +33,6 @@ export interface HandlerContext<TEnv = unknown> {
|
|
|
28
33
|
decodeAction: RSCDependencies["decodeAction"];
|
|
29
34
|
decodeFormState: RSCDependencies["decodeFormState"];
|
|
30
35
|
loadSSRModule: LoadSSRModule;
|
|
31
|
-
callOnError: (
|
|
32
|
-
error: unknown,
|
|
33
|
-
phase: ErrorPhase,
|
|
34
|
-
context: InvokeOnErrorContext<TEnv>,
|
|
35
|
-
) => void;
|
|
36
|
-
getRequiredRouteMap: () => Record<string, string>;
|
|
37
|
-
createRedirectFlightResponse: (
|
|
38
|
-
redirectUrl: string,
|
|
39
|
-
locationState?: Record<string, unknown>,
|
|
40
|
-
external?: boolean,
|
|
41
|
-
) => Response;
|
|
42
36
|
|
|
43
37
|
/**
|
|
44
38
|
* Resolve the SSR stream mode for a given request.
|