@rangojs/router 0.27.0 → 0.28.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.
Files changed (212) hide show
  1. package/dist/bin/rango.js +1 -1
  2. package/dist/types/__internal.d.ts +7 -1
  3. package/dist/types/browser/event-controller.d.ts +2 -1
  4. package/dist/types/browser/history-state.d.ts +3 -9
  5. package/dist/types/browser/navigation-store.d.ts +8 -6
  6. package/dist/types/browser/react/filter-segment-order.d.ts +2 -2
  7. package/dist/types/browser/segment-reconciler.d.ts +6 -4
  8. package/dist/types/browser/types.d.ts +2 -1
  9. package/dist/types/browser/wire-protocol.d.ts +25 -0
  10. package/dist/types/cache/cache-key-utils.d.ts +11 -5
  11. package/dist/types/cache/cache-scope.d.ts +34 -22
  12. package/dist/types/cache/cf/cf-cache-constants.d.ts +2 -2
  13. package/dist/types/cache/cf/cf-cache-store.d.ts +47 -65
  14. package/dist/types/cache/cf/cf-kv-utils.d.ts +1 -1
  15. package/dist/types/cache/handle-snapshot.d.ts +9 -4
  16. package/dist/types/cache/segment-codec.d.ts +14 -0
  17. package/dist/types/cache/shell-snapshot.d.ts +1 -1
  18. package/dist/types/cache/tag-invalidation.d.ts +10 -0
  19. package/dist/types/cache/taint.d.ts +5 -3
  20. package/dist/types/cache/types.d.ts +7 -3
  21. package/dist/types/cache/vercel/vercel-cache-store.d.ts +8 -6
  22. package/dist/types/prefetch-markers.d.ts +5 -14
  23. package/dist/types/prerender/store.d.ts +31 -0
  24. package/dist/types/prerender/warm-request.d.ts +3 -3
  25. package/dist/types/prerender.d.ts +2 -2
  26. package/dist/types/route-name.d.ts +5 -0
  27. package/dist/types/router/error-handling.d.ts +4 -4
  28. package/dist/types/router/instrument.d.ts +4 -3
  29. package/dist/types/router/intercept-resolution.d.ts +25 -9
  30. package/dist/types/router/match-context.d.ts +4 -11
  31. package/dist/types/router/match-handlers.d.ts +2 -6
  32. package/dist/types/router/match-middleware/background-revalidation.d.ts +10 -20
  33. package/dist/types/router/match-middleware/cache-lookup.d.ts +34 -86
  34. package/dist/types/router/match-middleware/segment-resolution.d.ts +8 -6
  35. package/dist/types/router/prerender-match.d.ts +21 -6
  36. package/dist/types/router/preview-match.d.ts +2 -7
  37. package/dist/types/router/request-classification.d.ts +5 -0
  38. package/dist/types/router/router-context.d.ts +7 -46
  39. package/dist/types/router/router-interfaces.d.ts +8 -14
  40. package/dist/types/router/segment-resolution/loader-cache.d.ts +3 -3
  41. package/dist/types/router/segment-resolution/loader-mask.d.ts +4 -4
  42. package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +20 -18
  43. package/dist/types/router/segment-resolution/resolution-pass.d.ts +93 -0
  44. package/dist/types/router/segment-resolution/revalidation.d.ts +82 -31
  45. package/dist/types/router/segment-resolution.d.ts +1 -2
  46. package/dist/types/router/segment-wrappers.d.ts +11 -48
  47. package/dist/types/router/telemetry.d.ts +2 -0
  48. package/dist/types/router/types.d.ts +10 -0
  49. package/dist/types/rsc/full-payload.d.ts +2 -2
  50. package/dist/types/rsc/handler-context.d.ts +6 -6
  51. package/dist/types/rsc/json-route-result.d.ts +5 -9
  52. package/dist/types/rsc/request-stages.d.ts +203 -0
  53. package/dist/types/rsc/response-cache-serve.d.ts +7 -12
  54. package/dist/types/rsc/response-route-handler.d.ts +2 -2
  55. package/dist/types/rsc/routine-plan.d.ts +1 -1
  56. package/dist/types/rsc/server-action.d.ts +2 -2
  57. package/dist/types/rsc/shell-capture-constants.d.ts +1 -1
  58. package/dist/types/rsc/shell-capture.d.ts +132 -15
  59. package/dist/types/rsc/shell-serve.d.ts +37 -12
  60. package/dist/types/server/context.d.ts +9 -8
  61. package/dist/types/server/handle-store.d.ts +16 -0
  62. package/dist/types/server/render-pass.d.ts +72 -0
  63. package/dist/types/server/request-context.d.ts +24 -104
  64. package/dist/types/server/rewrite-trail.d.ts +2 -2
  65. package/dist/types/testing/dispatch.d.ts +35 -18
  66. package/dist/types/types/cache-types.d.ts +6 -3
  67. package/dist/types/types/error-types.d.ts +9 -1
  68. package/dist/types/types/handler-context.d.ts +9 -1
  69. package/dist/types/types/segments.d.ts +1 -1
  70. package/dist/types/vite/discovery/build-discovery-phase.d.ts +40 -0
  71. package/dist/types/vite/discovery/build-env.d.ts +22 -0
  72. package/dist/types/vite/discovery/bundle-scan-phase.d.ts +12 -0
  73. package/dist/types/vite/discovery/dev-prerender-cache.d.ts +3 -2
  74. package/dist/types/vite/discovery/dev-server-phase.d.ts +26 -0
  75. package/dist/types/vite/discovery/discovery-errors.d.ts +1 -1
  76. package/dist/types/vite/discovery/state.d.ts +12 -0
  77. package/dist/types/vite/plugins/version-plugin.d.ts +1 -1
  78. package/dist/types/vite/plugins/virtual-entries.d.ts +1 -1
  79. package/dist/types/vite/router-discovery.d.ts +8 -47
  80. package/dist/types/vite/temp-rsc-server.d.ts +39 -0
  81. package/dist/types/vite/utils/prerender-utils.d.ts +9 -0
  82. package/dist/types/wire-params.d.ts +34 -0
  83. package/dist/vite/index.js +3809 -3710
  84. package/package.json +1 -1
  85. package/skills/cache-guide/SKILL.md +8 -5
  86. package/skills/caching/SKILL.md +37 -18
  87. package/skills/document-cache/SKILL.md +13 -1
  88. package/skills/handler-use/SKILL.md +1 -1
  89. package/skills/intercept/SKILL.md +17 -7
  90. package/skills/middleware/SKILL.md +18 -0
  91. package/skills/ppr/SKILL.md +18 -3
  92. package/skills/prerender/SKILL.md +39 -15
  93. package/skills/rango/SKILL.md +5 -1
  94. package/skills/server-actions/SKILL.md +8 -1
  95. package/skills/testing/response-routes.md +6 -4
  96. package/skills/use-cache/SKILL.md +46 -8
  97. package/src/__internal.ts +7 -1
  98. package/src/browser/connection-warmup.ts +3 -1
  99. package/src/browser/event-controller.ts +5 -3
  100. package/src/browser/history-state.ts +6 -12
  101. package/src/browser/navigation-bridge.ts +14 -13
  102. package/src/browser/navigation-client.ts +18 -25
  103. package/src/browser/navigation-store.ts +25 -27
  104. package/src/browser/navigation-transaction.ts +4 -1
  105. package/src/browser/prefetch/cache.ts +2 -1
  106. package/src/browser/prefetch/fetch.ts +8 -16
  107. package/src/browser/prefetch/queue.ts +4 -4
  108. package/src/browser/react/NavigationProvider.tsx +2 -1
  109. package/src/browser/react/filter-segment-order.ts +2 -2
  110. package/src/browser/rsc-router.tsx +1 -0
  111. package/src/browser/segment-reconciler.ts +66 -53
  112. package/src/browser/server-action-bridge.ts +50 -57
  113. package/src/browser/types.ts +2 -1
  114. package/src/browser/wire-protocol.ts +41 -0
  115. package/src/cache/cache-key-utils.ts +11 -5
  116. package/src/cache/cache-runtime.ts +110 -50
  117. package/src/cache/cache-scope.ts +110 -64
  118. package/src/cache/cf/cf-cache-constants.ts +2 -2
  119. package/src/cache/cf/cf-cache-store.ts +486 -874
  120. package/src/cache/cf/cf-kv-utils.ts +1 -1
  121. package/src/cache/document-cache.ts +34 -13
  122. package/src/cache/handle-snapshot.ts +19 -7
  123. package/src/cache/segment-codec.ts +55 -0
  124. package/src/cache/shell-snapshot.ts +2 -2
  125. package/src/cache/tag-invalidation.ts +21 -2
  126. package/src/cache/taint.ts +5 -3
  127. package/src/cache/types.ts +7 -3
  128. package/src/cache/vercel/vercel-cache-store.ts +243 -310
  129. package/src/handles/pushed-by.ts +1 -1
  130. package/src/prefetch-markers.ts +5 -16
  131. package/src/prerender/store.ts +76 -0
  132. package/src/prerender/warm-request.ts +8 -4
  133. package/src/prerender.ts +2 -2
  134. package/src/route-name.ts +8 -0
  135. package/src/router/error-handling.ts +4 -4
  136. package/src/router/instrument.ts +4 -3
  137. package/src/router/intercept-resolution.ts +77 -75
  138. package/src/router/loader-resolution.ts +5 -4
  139. package/src/router/match-api.ts +4 -5
  140. package/src/router/match-context.ts +20 -12
  141. package/src/router/match-handlers.ts +8 -20
  142. package/src/router/match-middleware/background-revalidation.ts +41 -53
  143. package/src/router/match-middleware/cache-lookup.ts +675 -726
  144. package/src/router/match-middleware/cache-store.ts +4 -8
  145. package/src/router/match-middleware/intercept-resolution.ts +3 -23
  146. package/src/router/match-middleware/segment-resolution.ts +34 -61
  147. package/src/router/middleware.ts +69 -11
  148. package/src/router/navigation-snapshot.ts +4 -4
  149. package/src/router/prerender-match.ts +100 -44
  150. package/src/router/preview-match.ts +6 -41
  151. package/src/router/request-classification.ts +13 -7
  152. package/src/router/route-snapshot.ts +2 -5
  153. package/src/router/router-context.ts +10 -95
  154. package/src/router/router-interfaces.ts +8 -14
  155. package/src/router/segment-resolution/loader-cache.ts +14 -9
  156. package/src/router/segment-resolution/loader-mask.ts +5 -5
  157. package/src/router/segment-resolution/prefetch-deferral.ts +30 -27
  158. package/src/router/segment-resolution/resolution-pass.ts +137 -0
  159. package/src/router/segment-resolution/revalidation.ts +897 -776
  160. package/src/router/segment-resolution.ts +4 -13
  161. package/src/router/segment-wrappers.ts +51 -269
  162. package/src/router/telemetry.ts +5 -0
  163. package/src/router/types.ts +10 -0
  164. package/src/router.ts +12 -13
  165. package/src/rsc/full-payload.ts +6 -5
  166. package/src/rsc/handler-context.ts +8 -14
  167. package/src/rsc/handler.ts +126 -507
  168. package/src/rsc/json-route-result.ts +5 -9
  169. package/src/rsc/loader-fetch.ts +6 -5
  170. package/src/rsc/progressive-enhancement.ts +5 -0
  171. package/src/rsc/request-stages.ts +757 -0
  172. package/src/rsc/response-cache-serve.ts +10 -14
  173. package/src/rsc/response-route-handler.ts +13 -5
  174. package/src/rsc/rewrite-passes.ts +2 -1
  175. package/src/rsc/routine-plan.ts +1 -1
  176. package/src/rsc/rsc-rendering.ts +164 -349
  177. package/src/rsc/server-action.ts +87 -113
  178. package/src/rsc/shell-capture-constants.ts +1 -1
  179. package/src/rsc/shell-capture.ts +212 -169
  180. package/src/rsc/shell-serve.ts +121 -18
  181. package/src/rsc/ssr-setup.ts +5 -4
  182. package/src/segment-system.tsx +3 -3
  183. package/src/server/context.ts +22 -25
  184. package/src/server/handle-store.ts +55 -0
  185. package/src/server/render-pass.ts +291 -0
  186. package/src/server/request-context.ts +26 -115
  187. package/src/server/rewrite-trail.ts +6 -4
  188. package/src/ssr/index.tsx +1 -1
  189. package/src/testing/dispatch.ts +223 -710
  190. package/src/testing/e2e/page-helpers.ts +2 -2
  191. package/src/testing/serve-shell-request.ts +23 -36
  192. package/src/types/cache-types.ts +6 -3
  193. package/src/types/error-types.ts +9 -1
  194. package/src/types/handler-context.ts +12 -1
  195. package/src/types/segments.ts +1 -1
  196. package/src/vite/discovery/build-discovery-phase.ts +204 -0
  197. package/src/vite/discovery/build-env.ts +148 -0
  198. package/src/vite/discovery/bundle-scan-phase.ts +128 -0
  199. package/src/vite/discovery/dev-prerender-cache.ts +8 -3
  200. package/src/vite/discovery/dev-server-phase.ts +1776 -0
  201. package/src/vite/discovery/discover-routers.ts +1 -1
  202. package/src/vite/discovery/discovery-errors.ts +1 -1
  203. package/src/vite/discovery/prerender-collection.ts +24 -39
  204. package/src/vite/discovery/state.ts +15 -0
  205. package/src/vite/plugins/version-plugin.ts +1 -1
  206. package/src/vite/plugins/virtual-entries.ts +1 -1
  207. package/src/vite/router-discovery.ts +29 -2428
  208. package/src/vite/temp-rsc-server.ts +223 -0
  209. package/src/vite/utils/prerender-utils.ts +47 -0
  210. package/src/wire-params.ts +35 -0
  211. package/dist/types/router/segment-resolution/fresh.d.ts +0 -72
  212. package/src/router/segment-resolution/fresh.ts +0 -945
@@ -1,51 +1,14 @@
1
- import type { EntryData, InterceptEntry } from "../server/context";
2
- import type { HandlerContext, ResolvedSegment, ShouldRevalidateFn } from "../types";
3
1
  import type { SegmentResolutionDeps } from "./types.js";
4
- import type { ResolveSegmentOptions } from "./segment-resolution.js";
5
- import type { RevalidationContext } from "./router-context.js";
6
- import type { InterceptSelectorContext } from "../server/context";
7
- export interface SegmentWrappers<TEnv = any> {
8
- resolveAllSegments: (entries: EntryData[], routeKey: string, params: Record<string, string>, context: HandlerContext<any, TEnv>, loaderPromises: Map<string, Promise<any>>, options?: ResolveSegmentOptions) => Promise<ResolvedSegment[]>;
9
- resolveLoadersOnly: (entries: EntryData[], context: HandlerContext<any, TEnv>) => Promise<ResolvedSegment[]>;
10
- resolveLoadersOnlyWithRevalidation: (entries: EntryData[], context: HandlerContext<any, TEnv>, clientSegmentIds: Set<string>, prevParams: Record<string, string>, request: Request, prevUrl: URL, nextUrl: URL, routeKey: string, actionContext?: {
11
- actionId?: string;
12
- actionUrl?: URL;
13
- actionResult?: any;
14
- formData?: FormData;
15
- }, stale?: boolean) => Promise<{
16
- segments: ResolvedSegment[];
17
- matchedIds: string[];
18
- }>;
19
- buildEntryRevalidateMap: (entries: EntryData[]) => Map<string, {
20
- entry: EntryData;
21
- revalidate: ShouldRevalidateFn<any, any>[];
22
- }>;
23
- resolveAllSegmentsWithRevalidation: (entries: EntryData[], routeKey: string, params: Record<string, string>, context: HandlerContext<any, TEnv>, clientSegmentSet: Set<string>, prevParams: Record<string, string>, request: Request, prevUrl: URL, nextUrl: URL, actionContext: {
24
- actionId?: string;
25
- actionUrl?: URL;
26
- actionResult?: any;
27
- formData?: FormData;
28
- } | undefined, interceptResult: {
29
- intercept: InterceptEntry;
30
- entry: EntryData;
31
- } | null, localRouteName: string, pathname: string, stale?: boolean, chain?: readonly EntryData[]) => Promise<{
32
- segments: ResolvedSegment[];
33
- matchedIds: string[];
34
- }>;
35
- findInterceptForRoute: (targetRouteKey: string, fromEntry: EntryData | null, selectorContext?: InterceptSelectorContext | null, isAction?: boolean) => {
36
- intercept: InterceptEntry;
37
- entry: EntryData;
38
- } | null;
39
- resolveInterceptEntry: (interceptEntry: InterceptEntry, parentEntry: EntryData, params: Record<string, string>, context: HandlerContext<any, TEnv>, belongsToRoute?: boolean, revalidationContext?: any, options?: {
40
- background?: boolean;
41
- }) => Promise<ResolvedSegment[]>;
42
- resolveInterceptLoadersOnly: (interceptEntry: InterceptEntry, parentEntry: EntryData, context: HandlerContext<any, TEnv>, belongsToRoute: boolean, revalidationContext: RevalidationContext) => Promise<ResolvedSegment[]>;
43
- }
2
+ import type { RouterContext } from "./router-context.js";
3
+ import { findInterceptForRoute as _findInterceptForRoute } from "./intercept-resolution.js";
4
+ /** The resolvers RouterContext exposes, with the router's deps bound. */
5
+ export type SegmentWrappers<TEnv = any> = Pick<RouterContext<TEnv>, "resolveAllSegments" | "resolveInterceptEntry"> & Required<Pick<RouterContext<TEnv>, "resolveLoadersOnly" | "buildEntryRevalidateMap" | "resolveInterceptLoadersOnly">> & {
6
+ /** Its own signature: a null selector context, isAction defaulting to false. */
7
+ findInterceptForRoute: typeof _findInterceptForRoute;
8
+ };
44
9
  /**
45
- * Create thin wrapper functions that bind segmentDeps to extracted
46
- * segment resolution and intercept resolution functions.
47
- *
48
- * These maintain the same signatures as the original inline functions
49
- * so that RouterContext and call sites don't need to change.
10
+ * Bind the router's segment deps into the extracted segment and intercept
11
+ * resolvers. Each gets a ResolutionPass: the caller's request-side input with
12
+ * the deps added here, once per call.
50
13
  */
51
- export declare function createSegmentWrappers<TEnv = any>(segmentDeps: SegmentResolutionDeps<TEnv>): SegmentWrappers<TEnv>;
14
+ export declare function createSegmentWrappers<TEnv = any>(deps: SegmentResolutionDeps<TEnv>): SegmentWrappers<TEnv>;
@@ -208,6 +208,8 @@ export declare function safeEmit(sink: TelemetrySink, event: TelemetryEvent): vo
208
208
  * Generated IDs use format "t-{base36}" to distinguish from header values.
209
209
  */
210
210
  export declare function getRequestId(request: Request): string;
211
+ /** Make `id` the id getRequestId returns for `request`. */
212
+ export declare function setRequestId(request: Request, id: string): void;
211
213
  /**
212
214
  * Built-in console sink that logs events in a structured format.
213
215
  * Designed as the default sink for development / debugging.
@@ -15,6 +15,16 @@ export type ActionContext = {
15
15
  actionUrl?: URL;
16
16
  actionResult?: any;
17
17
  formData?: FormData;
18
+ /**
19
+ * A thrown action's error segment (matchError), set on the action's
20
+ * revalidation (rsc/server-action.ts matchBoundaryRevalidation). The walk
21
+ * (resolveAllSegments) resolves every entry above the segment's outlet as on
22
+ * a success, emits the segment in the outlet's place and stops, so nothing
23
+ * at or below the outlet runs. The pass skips the prerender store
24
+ * (cache-lookup.ts): the evicted handler is under the cut. No revalidate()
25
+ * predicate sees it.
26
+ */
27
+ boundary?: ResolvedSegment;
18
28
  };
19
29
  export interface SegmentResolutionDeps<TEnv = any> {
20
30
  wrapLoaderPromise: <T>(promise: Promise<T>, entry: EntryData, segmentId: string, pathname: string, errorContext?: {
@@ -32,7 +32,7 @@ export declare function buildFullPayload(m: MatchResult, ctx: HandlerContext<any
32
32
  * visitor's URL. Any other render that shows the visitor's URL marks
33
33
  * `_payloadVisitorLocation`, and the document cache does not store it.
34
34
  */
35
- export declare function renderedLocation(reqCtx: Pick<RequestContext<any>, "_variables" | "_shellCaptureRun" | "_shellCaptureForVisitor" | "_documentCacheRender" | "_payloadVisitorLocation" | "res"> | undefined, url: URL): URL;
35
+ export declare function renderedLocation(reqCtx: Pick<RequestContext<any>, "_variables" | "_shellCaptureState" | "_documentCacheRender" | "_payloadVisitorLocation" | "res"> | undefined, url: URL): URL;
36
36
  /**
37
37
  * A payload's `pathname` (renderedLocation) and, when middleware rewrote the
38
38
  * request, `rewriteTarget`: the path and search the route rendered (the
@@ -63,4 +63,4 @@ export declare function payloadLocation(reqCtx: Parameters<typeof renderedLocati
63
63
  * default it marks `_payloadVisitorTheme`, and the document cache does not
64
64
  * store the response.
65
65
  */
66
- export declare function payloadInitialTheme(reqCtx: Pick<RequestContext<any>, "_themeConfig" | "_shellCaptureRun" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "res">): Theme | undefined;
66
+ export declare function payloadInitialTheme(reqCtx: Pick<RequestContext<any>, "_themeConfig" | "_shellCaptureState" | "_readTheme" | "_documentCacheRender" | "_payloadVisitorTheme" | "res">): Theme | undefined;
@@ -6,11 +6,14 @@
6
6
  * RSC rendering) so they can be standalone modules without closure coupling.
7
7
  */
8
8
  import type { RangoInternal } from "../router/router-interfaces.js";
9
- import type { ErrorPhase } from "../types.js";
10
- import type { InvokeOnErrorContext } from "../router/error-handling.js";
11
9
  import type { RSCDependencies, LoadSSRModule } from "./types.js";
12
10
  import type { SSRStreamMode } from "../router/router-options.js";
13
- export interface HandlerContext<TEnv = unknown> {
11
+ import type { RequestStageContext } from "./request-stages.js";
12
+ /**
13
+ * Extends what the request stages (rsc/request-stages.ts) call back into, so
14
+ * the handler hands this one bundle to them as well.
15
+ */
16
+ export interface HandlerContext<TEnv = unknown> extends RequestStageContext<TEnv> {
14
17
  router: RangoInternal<TEnv, any>;
15
18
  /**
16
19
  * The router's DOCUMENT version (router-versions.ts): payload metadata, the
@@ -26,9 +29,6 @@ export interface HandlerContext<TEnv = unknown> {
26
29
  decodeAction: RSCDependencies["decodeAction"];
27
30
  decodeFormState: RSCDependencies["decodeFormState"];
28
31
  loadSSRModule: LoadSSRModule;
29
- callOnError: (error: unknown, phase: ErrorPhase, context: InvokeOnErrorContext<TEnv>) => void;
30
- getRequiredRouteMap: () => Record<string, string>;
31
- createRedirectFlightResponse: (redirectUrl: string, locationState?: Record<string, unknown>, external?: boolean) => Response;
32
32
  /**
33
33
  * Resolve the SSR stream mode for a given request.
34
34
  * Returns "stream" when no resolveStreaming callback is configured.
@@ -1,10 +1,6 @@
1
1
  /**
2
- * Shared serialization for `json()` response-route results.
3
- *
4
- * Kept in its own lightweight module (depends only on `errors.js`) so the
5
- * `dispatch()` testing primitive can import it WITHOUT dragging in
6
- * `response-route-handler.ts`'s heavy runtime graph, which transitively reaches
7
- * a Vite virtual module and breaks a plain (non-Vite) vitest import.
2
+ * Serialization for `json()` response-route results (depends only on
3
+ * `errors.js`).
8
4
  */
9
5
  /**
10
6
  * Serialize a `json()` response-route result, rejecting a nested unresolved
@@ -13,8 +9,8 @@
13
9
  * the RSC pipeline awaits nested promises but this path does not. Throwing
14
10
  * `RESPONSE_NOT_SERIALIZABLE` makes the failure loud.
15
11
  *
16
- * Shared by the production response-route handler and the `dispatch()` testing
17
- * primitive so a `dispatch` json test of a forgotten await fails exactly where
18
- * production 500s, instead of going green.
12
+ * The `dispatch()` testing primitive runs the same response-route handler, so
13
+ * a `dispatch` json test of a forgotten await fails exactly where production
14
+ * 500s, instead of going green.
19
15
  */
20
16
  export declare function stringifyJsonRouteResult(result: unknown): string;
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Request stages
3
+ *
4
+ * The stages a request runs through before and after rendering: classify,
5
+ * guard, the global middleware passes, the response route, and the
6
+ * response's finalization. The RSC handler (rsc/handler.ts createRSCHandler)
7
+ * runs them all around its Flight executor. The dispatch testing primitive
8
+ * (testing/dispatch.ts) runs classify, the terminal plans, the passes, the
9
+ * response route and the finalization, and throws where a plan would render
10
+ * a component. Sharing them keeps dispatch's responses identical to
11
+ * production's; a hand-kept mirror drifted once (#1128).
12
+ *
13
+ * No import of @vitejs/plugin-rsc on this graph: dispatch loads it in a
14
+ * plain Vitest project, where plugin-rsc's entries cannot load (they import
15
+ * Vite virtuals). testing/__tests__/testing-module-graph.test.ts pins it.
16
+ */
17
+ import type { MiddlewareEntry } from "../router/middleware-types.js";
18
+ import { type RequestContext } from "../server/request-context.js";
19
+ import { type RewritePassesOptions, type RewritePassesResult } from "./rewrite-passes.js";
20
+ import { type ResponseRouteMatch } from "./response-route-handler.js";
21
+ import type { ErrorPhase } from "../types.js";
22
+ import type { OnErrorCallback } from "../types/error-types.js";
23
+ import { type InvokeOnErrorContext } from "../router/error-handling.js";
24
+ import type { OriginCheckPhase } from "./origin-guard.js";
25
+ import { type OnTimeoutCallback, type ResolvedTimeouts, type TimeoutPhase } from "../router/timeout.js";
26
+ import { type TelemetrySink } from "../router/telemetry.js";
27
+ import { type ClassifyRequestDeps, type ExecutableRequestPlan, type RequestPlan, type ResponseRoutePlan } from "../router/request-classification.js";
28
+ /**
29
+ * The router members the stages read. The handler's `RangoInternal` carries
30
+ * them; dispatch reads them off the router a test passes.
31
+ */
32
+ export interface StageRouter<TEnv = unknown> {
33
+ readonly basename: string | undefined;
34
+ readonly middleware: MiddlewareEntry<TEnv>[];
35
+ readonly onError?: OnErrorCallback<TEnv>;
36
+ readonly telemetry?: TelemetrySink;
37
+ readonly timeouts?: ResolvedTimeouts;
38
+ readonly onTimeout?: OnTimeoutCallback<TEnv>;
39
+ }
40
+ /** Report an error through the router's onError. */
41
+ export type ReportError<TEnv = unknown> = (error: unknown, phase: ErrorPhase, context: InvokeOnErrorContext<TEnv>) => void;
42
+ /**
43
+ * What the stages call back into. The handler's context bundle
44
+ * (rsc/handler-context.ts HandlerContext) extends it.
45
+ */
46
+ export interface RequestStageContext<TEnv = unknown> {
47
+ router: StageRouter<TEnv>;
48
+ callOnError: ReportError<TEnv>;
49
+ getRequiredRouteMap: () => Record<string, string>;
50
+ /**
51
+ * The redirect a partial or action request receives: a Flight payload in
52
+ * the handler (fetch() would follow a raw 3xx to HTML). dispatch has no
53
+ * Flight runtime and answers 204 + X-RSC-Redirect.
54
+ */
55
+ createRedirectFlightResponse: (redirectUrl: string, locationState?: Record<string, unknown>, external?: boolean) => Response;
56
+ /**
57
+ * Reports a response-route handler's own throw; absent, it goes to
58
+ * callOnError with phase "handler". dispatch passes a no-op: it does not
59
+ * report that throw (its documented boundary, testing/dispatch.ts).
60
+ */
61
+ reportResponseRouteError?: (error: unknown, context: InvokeOnErrorContext<TEnv>) => void;
62
+ }
63
+ /** What classify and the terminal plans read beyond the stage context. */
64
+ export interface ClassifyContext<TEnv = unknown> {
65
+ router: {
66
+ readonly id: string;
67
+ readonly findMatch: ClassifyRequestDeps<TEnv>["findMatch"];
68
+ };
69
+ /** The router's DOCUMENT version: the `_rsc_v` reload check. */
70
+ version: string;
71
+ }
72
+ /**
73
+ * Per-request error reporter that deduplicates via the ALS request context.
74
+ *
75
+ * Uses the same _reportedErrors WeakSet as the router layer so errors
76
+ * that propagate across layers are only reported once per request.
77
+ */
78
+ export declare function createErrorReporter<TEnv>(router: {
79
+ readonly onError?: OnErrorCallback<TEnv>;
80
+ }): ReportError<TEnv>;
81
+ /**
82
+ * Wire background error reporting so "use cache" and other subsystems can
83
+ * surface non-fatal errors through the router's onError callback.
84
+ */
85
+ export declare function reportBackgroundErrors<TEnv>(reqCtx: RequestContext<TEnv>, request: Request, url: URL, callOnError: ReportError<TEnv>): void;
86
+ /**
87
+ * Classify a request into its plan. classifyRequest throws
88
+ * RouteNotFoundError for an unknown route; that falls through to a
89
+ * full-render plan with no matched route, so the render path renders the
90
+ * 404 page (match()/matchPartial() re-throw and the render's catch renders
91
+ * it).
92
+ */
93
+ export declare function classify<TEnv>(request: Request, url: URL, ctx: ClassifyContext<TEnv>): Promise<RequestPlan<TEnv>>;
94
+ /** The plan classify answers an unknown route with (the render path's 404). */
95
+ export declare function isUnmatchedPlan(plan: RequestPlan<any>): boolean;
96
+ /**
97
+ * Record a plan's route on the request context: its params and name, and the
98
+ * classified snapshot match()/matchPartial() reuse instead of resolving the
99
+ * route again. Runs inside the global chain, so global middleware sees the
100
+ * route after next(). A redirect has none.
101
+ */
102
+ export declare function recordPlanRoute<TEnv>(plan: ExecutableRequestPlan<TEnv>): void;
103
+ /**
104
+ * The checks between classification and execution that need no await.
105
+ * Returns the response of a terminal plan (a partial request's redirect, a
106
+ * version or app-switch reload), null to go on. Throws for a rewritten
107
+ * action whose target is not a page route.
108
+ *
109
+ * Synchronous, and the origin guard is a separate step: the caller awaits
110
+ * checkRequestOrigin only for the modes ORIGIN_CHECK_PHASE_BY_MODE gates, so
111
+ * a full, partial or response plan reaches execution without an added
112
+ * microtask (rsc/__tests__/request-microtasks.rsc-test.tsx).
113
+ */
114
+ export declare function terminalPlanResponse<TEnv>(plan: RequestPlan<TEnv>, url: URL, ctx: RequestStageContext<TEnv> & ClassifyContext<TEnv>): Response | null;
115
+ /**
116
+ * The origin guard's rejection: reports it through onError and telemetry,
117
+ * and returns the response checkRequestOrigin rejected the request with. The
118
+ * caller awaits checkRequestOrigin itself, for the modes
119
+ * ORIGIN_CHECK_PHASE_BY_MODE gates (action, loader, PE form), so the guard
120
+ * adds no microtask over that await.
121
+ */
122
+ export declare function originRejectedResponse<TEnv>(rejection: Response, phase: OriginCheckPhase, request: Request, env: TEnv, url: URL, ctx: RequestStageContext<TEnv>): Response;
123
+ export interface RequestPassesOptions<TEnv> {
124
+ ctx: RequestStageContext<TEnv>;
125
+ reqCtx: RequestContext<TEnv>;
126
+ /** The visitor's request and raw URL: the first pass. */
127
+ request: Request;
128
+ url: URL;
129
+ env: TEnv;
130
+ variables: Record<string, any>;
131
+ /** The visitor's global middleware, when the caller matched it already. */
132
+ firstPassMiddleware?: Array<{
133
+ entry: MiddlewareEntry<TEnv>;
134
+ params: Record<string, string>;
135
+ }>;
136
+ /** Runs before a pass's global chain; dispatch matches the pass there. */
137
+ beforePass?: (request: Request, url: URL, index: number) => Promise<void>;
138
+ /** The core handler a pass's global chain wraps. */
139
+ core: (request: Request, url: URL) => Promise<Response>;
140
+ onHop?: RewritePassesOptions["onHop"];
141
+ refuse?: RewritePassesOptions["refuse"];
142
+ }
143
+ export interface RequestPassesResult extends RewritePassesResult {
144
+ /** Whether the last pass ran a global middleware chain. */
145
+ hasMiddleware: boolean;
146
+ }
147
+ /**
148
+ * One pass per URL: the global middleware chain matched on the pass's path,
149
+ * wrapping the core handler. A `throw rewrite()` from global or route
150
+ * middleware unwinds the pass, and the next one runs the same request as
151
+ * the target from the top, as a direct visit would (rsc/rewrite-passes.ts).
152
+ */
153
+ export declare function runRequestPasses<TEnv>(opts: RequestPassesOptions<TEnv>): Promise<RequestPassesResult>;
154
+ /**
155
+ * The flat match handleResponseRoute takes, with params at the top level,
156
+ * built from a response-route plan.
157
+ */
158
+ export declare function responseRouteMatch(plan: ResponseRoutePlan<any>): ResponseRouteMatch;
159
+ export interface ServeResponseRouteOptions<TEnv> {
160
+ match: ResponseRouteMatch;
161
+ /** The matched route's key, for the timeout report. */
162
+ routeKey: string | undefined;
163
+ /** The pass's request, raw URL and env. */
164
+ request: Request;
165
+ url: URL;
166
+ env: TEnv;
167
+ variables: Record<string, any>;
168
+ /**
169
+ * Receives the handler's work when the deadline wins. The handler leaves
170
+ * it running; dispatch cancels its body.
171
+ */
172
+ abandon?: (work: Promise<Response>) => void;
173
+ }
174
+ /**
175
+ * A response route: its handler (rsc/response-route-handler.ts) under the
176
+ * renderStartMs deadline, which starts here, inside the global chain, so
177
+ * global middleware time never counts toward it.
178
+ */
179
+ export declare function serveResponseRoute<TEnv>(ctx: RequestStageContext<TEnv>, opts: ServeResponseRouteOptions<TEnv>): Promise<Response>;
180
+ /**
181
+ * Handle a timeout by reporting the error, emitting telemetry,
182
+ * and returning either the custom onTimeout response or a default 504.
183
+ */
184
+ export declare function timeoutResponse<TEnv>(ctx: RequestStageContext<TEnv>, request: Request, env: TEnv, url: URL, phase: TimeoutPhase, durationMs: number, routeKey?: string, actionId?: string): Promise<Response>;
185
+ export interface FinalizeRequestOptions<TEnv> {
186
+ ctx: RequestStageContext<TEnv>;
187
+ reqCtx: RequestContext<TEnv>;
188
+ /** The visitor's request, raw URL and env. */
189
+ request: Request;
190
+ url: URL;
191
+ env: TEnv;
192
+ /** runRequestPasses' result. */
193
+ hasMiddleware: boolean;
194
+ rewrittenTo?: string;
195
+ /** Runs on the response before the open-redirect guard. */
196
+ beforeGuard?: (response: Response) => void;
197
+ }
198
+ /**
199
+ * The response the global chain returned, made ready to leave: a partial or
200
+ * action request's redirect converted, onResponse callbacks drained, the
201
+ * rewrite header, the open-redirect guard and the stream-idle watchdog.
202
+ */
203
+ export declare function finalizeRequestResponse<TEnv>(downstream: Response, opts: FinalizeRequestOptions<TEnv>): Response;
@@ -5,23 +5,18 @@
5
5
  * matched entry tree, condition eval, key resolution (route key() > store
6
6
  * keyGenerator > default, CacheScope.resolveKeyFrom), tag resolution,
7
7
  * pre-handler-callback timing, and the fresh-hit / SWR-revalidate /
8
- * miss-write branches — for BOTH the production
9
- * response-route handler (rsc/response-route-handler.ts) and the dispatch testing
10
- * primitive (testing/dispatch.ts), so the two can never drift.
8
+ * miss-write branches — for the response-route handler
9
+ * (rsc/response-route-handler.ts), which the production handler and the
10
+ * dispatch testing primitive both run (rsc/request-stages.ts
11
+ * serveResponseRoute), so the two can never drift.
11
12
  *
12
- * Plugin-rsc hazard: cache-scope.ts pulls @vitejs/plugin-rsc (via segment-codec),
13
- * which the non-Vite unit-test runner cannot resolve, and this module is on the
14
- * testing barrel's EAGER graph (dispatch imports it). So `createCacheScope` is
15
- * NOT imported here at runtime — it is INJECTED by the caller (production
16
- * imports it statically; dispatch lazy-imports it only once a response route
17
- * matches). The only runtime imports here are plugin-rsc-free
18
- * (helpers' isCacheableStatus/finalizeResponse, traverseBack); cache-scope is a
19
- * type-only import (erased at build).
13
+ * `createCacheScope` is injected by the caller: the response-route handler
14
+ * passes the real one, unit tests a stub.
20
15
  */
21
16
  import type { CacheScope } from "../cache/cache-scope.js";
22
17
  import { type RequestContext } from "../server/request-context.js";
23
18
  import type { EntryCacheConfig, EntryData } from "../server/context.js";
24
- /** Injected cache-scope builder (kept off this module's runtime import graph). */
19
+ /** Injected cache-scope builder. */
25
20
  export interface CacheScopeDeps {
26
21
  createCacheScope: (config: EntryCacheConfig | undefined, parent?: CacheScope | null) => CacheScope | null;
27
22
  }
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import type { MiddlewareFn } from "../router/middleware.js";
9
9
  import { type EntryData } from "../server/context.js";
10
- import type { HandlerContext } from "./handler-context.js";
10
+ import type { RequestStageContext } from "./request-stages.js";
11
11
  export interface ResponseRouteMatch {
12
12
  responseType: string;
13
13
  handler: Function;
@@ -26,4 +26,4 @@ export interface ResponseRouteMatch {
26
26
  * For partial (client-side navigation) requests, returns X-RSC-Reload
27
27
  * so the browser triggers a hard navigation to the response route URL.
28
28
  */
29
- export declare function handleResponseRoute<TEnv>(handlerCtx: HandlerContext<TEnv>, preview: ResponseRouteMatch, request: Request, env: TEnv, url: URL, variables: Record<string, any>): Promise<Response>;
29
+ export declare function handleResponseRoute<TEnv>(handlerCtx: Pick<RequestStageContext<TEnv>, "callOnError" | "getRequiredRouteMap" | "reportResponseRouteError">, preview: ResponseRouteMatch, request: Request, env: TEnv, url: URL, variables: Record<string, any>): Promise<Response>;
@@ -62,7 +62,7 @@ export declare function step<T>(name: string, execute: () => T | Promise<T>): Ro
62
62
  *
63
63
  * Settlement tracking follows the RETURNED value: a returned promise is
64
64
  * observed until it settles; a scheduler that fires-and-forgets internally
65
- * (e.g. scheduleShellCapture via runBackground) returns void, so its trace
65
+ * (e.g. planShellCapture via runBackground) returns void, so its trace
66
66
  * entry settles at the scheduling call, not at background completion. That is
67
67
  * deliberate — the plan's contract ends at the handoff.
68
68
  */
@@ -27,8 +27,8 @@ import type { MatchResult } from "../types.js";
27
27
  * the revalidation phase so it runs INSIDE the same route-middleware wrapper as
28
28
  * a successful revalidation — route middleware (context vars, headers, cookies)
29
29
  * must apply to the error render too, matching the module doc's "identical to a
30
- * normal render". When `errorBoundary` is set, `actionContext` is unused (the
31
- * boundary is already matched; no matchPartial is run).
30
+ * normal render". That render is the action's revalidation, cut at the
31
+ * boundary (ActionContext.boundary).
32
32
  */
33
33
  export interface ActionContinuation {
34
34
  returnValue: {
@@ -139,7 +139,7 @@ export declare const POST_QUIESCE_TASK_HOPS = 16;
139
139
  * short is an acceptable loss — every terminal path backs the key off anyway),
140
140
  * and below workerd's ~30s waitUntil grace so the cap timer still fires in a
141
141
  * live context. When workerd kills the context BEFORE the cap fires, the timer
142
- * dies with it — that stranding is healed by scheduleShellCapture's staleness
142
+ * dies with it — that stranding is healed by planShellCapture's staleness
143
143
  * check on the stampede guard, keyed off the same constant.
144
144
  */
145
145
  export declare const SHELL_CAPTURE_TASK_HARD_CAP_MS = 25000;