@rangojs/router 0.21.0 → 0.22.1

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 (244) hide show
  1. package/dist/bin/rango.js +13 -1
  2. package/dist/types/browser/event-controller.d.ts +30 -13
  3. package/dist/types/browser/navigation-store.d.ts +9 -0
  4. package/dist/types/browser/partial-update.d.ts +2 -1
  5. package/dist/types/browser/prefetch/default-strategy.d.ts +16 -20
  6. package/dist/types/browser/react/NavigationProvider.d.ts +14 -1
  7. package/dist/types/browser/react/context.d.ts +14 -0
  8. package/dist/types/browser/rsc-router.d.ts +13 -2
  9. package/dist/types/browser/types.d.ts +10 -0
  10. package/dist/types/build/generate-manifest.d.ts +2 -0
  11. package/dist/types/cache/background-task.d.ts +22 -0
  12. package/dist/types/cache/cache-key-utils.d.ts +50 -5
  13. package/dist/types/cache/cache-policy.d.ts +17 -0
  14. package/dist/types/cache/cache-scope.d.ts +1 -1
  15. package/dist/types/cache/cf/cf-cache-store.d.ts +7 -1
  16. package/dist/types/cache/document-cache.d.ts +8 -5
  17. package/dist/types/cache/handle-snapshot.d.ts +23 -0
  18. package/dist/types/cache/index.d.ts +1 -1
  19. package/dist/types/cache/invalidation-order.d.ts +14 -0
  20. package/dist/types/cache/memory-segment-store.d.ts +33 -1
  21. package/dist/types/cache/shell-snapshot.d.ts +10 -1
  22. package/dist/types/cache/store-scope.d.ts +22 -0
  23. package/dist/types/cache/tag-invalidation.d.ts +7 -6
  24. package/dist/types/cache/types.d.ts +63 -14
  25. package/dist/types/cache/vercel/vercel-cache-store.d.ts +7 -1
  26. package/dist/types/errors.d.ts +6 -0
  27. package/dist/types/handles/deferred-resolution.d.ts +7 -0
  28. package/dist/types/internal-suspense-audit.d.ts +1 -0
  29. package/dist/types/loader-store.d.ts +4 -8
  30. package/dist/types/outlet-provider.d.ts +2 -1
  31. package/dist/types/prerender/cloudflare.d.ts +49 -0
  32. package/dist/types/prerender/create-prerender-trigger.d.ts +121 -0
  33. package/dist/types/prerender/index.d.ts +12 -0
  34. package/dist/types/prerender/memory-prerender-store.d.ts +29 -0
  35. package/dist/types/prerender/on-demand.d.ts +272 -0
  36. package/dist/types/prerender/producer-guard.d.ts +33 -0
  37. package/dist/types/prerender/shell-manifest-key.d.ts +1 -18
  38. package/dist/types/prerender/warm-request.d.ts +65 -0
  39. package/dist/types/prerender/warm.d.ts +65 -0
  40. package/dist/types/prerender/writable-store.d.ts +170 -0
  41. package/dist/types/prerender.d.ts +27 -0
  42. package/dist/types/reverse.d.ts +1 -1
  43. package/dist/types/route-content-wrapper.d.ts +3 -1
  44. package/dist/types/router/error-handling.d.ts +2 -0
  45. package/dist/types/router/handler-context.d.ts +1 -1
  46. package/dist/types/router/match-middleware/cache-lookup.d.ts +14 -0
  47. package/dist/types/router/pattern-matching.d.ts +2 -0
  48. package/dist/types/router/prefetch-default.d.ts +4 -4
  49. package/dist/types/router/prerender-match.d.ts +23 -1
  50. package/dist/types/router/route-trie-builder.d.ts +8 -1
  51. package/dist/types/router/router-context.d.ts +1 -0
  52. package/dist/types/router/router-interfaces.d.ts +30 -0
  53. package/dist/types/router/router-options.d.ts +24 -0
  54. package/dist/types/router/segment-resolution/fresh.d.ts +7 -0
  55. package/dist/types/router/segment-resolution/loader-cache.d.ts +2 -1
  56. package/dist/types/router/segment-resolution/revalidation.d.ts +5 -1
  57. package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +43 -0
  58. package/dist/types/router/trie-matching.d.ts +2 -0
  59. package/dist/types/rsc/shell-build-manifest.d.ts +6 -4
  60. package/dist/types/rsc/shell-capture-constants.d.ts +20 -5
  61. package/dist/types/rsc/shell-capture.d.ts +14 -1
  62. package/dist/types/rsc/shell-serve.d.ts +2 -2
  63. package/dist/types/rsc/ssr-module-loader.d.ts +15 -0
  64. package/dist/types/rsc/types.d.ts +8 -0
  65. package/dist/types/segment-boundary-content.d.ts +17 -0
  66. package/dist/types/segment-loader-promise.d.ts +2 -6
  67. package/dist/types/server/build-version-table.d.ts +9 -0
  68. package/dist/types/server/context.d.ts +12 -4
  69. package/dist/types/server/handle-store.d.ts +2 -0
  70. package/dist/types/server/request-context.d.ts +63 -2
  71. package/dist/types/suspense-audit-react.d.ts +26 -0
  72. package/dist/types/suspense-audit.d.ts +157 -0
  73. package/dist/types/testing/action-form.d.ts +34 -0
  74. package/dist/types/testing/flight.entry.d.ts +2 -0
  75. package/dist/types/testing/index.d.ts +4 -0
  76. package/dist/types/testing/internal/server-modules.d.ts +8 -0
  77. package/dist/types/testing/serve-shell-request.d.ts +34 -4
  78. package/dist/types/testing/shell-status.d.ts +14 -6
  79. package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +9 -6
  80. package/dist/types/thenable-status.d.ts +6 -0
  81. package/dist/types/types/handler-context.d.ts +7 -0
  82. package/dist/types/types/route-entry.d.ts +5 -0
  83. package/dist/types/urls/path-helper.d.ts +18 -0
  84. package/dist/types/vite/discovery/state.d.ts +11 -0
  85. package/dist/types/vite/inject-client-debug.d.ts +6 -25
  86. package/dist/types/vite/utils/bundle-analysis.d.ts +6 -2
  87. package/dist/vite/index.js +180 -497
  88. package/package.json +13 -3
  89. package/skills/cache-guide/SKILL.md +18 -17
  90. package/skills/caching/SKILL.md +40 -4
  91. package/skills/catalog.json +1 -1
  92. package/skills/cloudflare/SKILL.md +131 -0
  93. package/skills/comparison/references/framework-comparison.md +1 -1
  94. package/skills/deployment-caching/SKILL.md +33 -12
  95. package/skills/document-cache/SKILL.md +16 -14
  96. package/skills/hooks/SKILL.md +22 -0
  97. package/skills/hooks/handle-and-actions.md +3 -4
  98. package/skills/hooks/navigation.md +10 -0
  99. package/skills/hooks/state.md +5 -4
  100. package/skills/host-router/SKILL.md +18 -0
  101. package/skills/loader/SKILL.md +6 -4
  102. package/skills/middleware/SKILL.md +1 -1
  103. package/skills/migrate-nextjs/SKILL.md +82 -9
  104. package/skills/ppr/SKILL.md +31 -8
  105. package/skills/prerender/SKILL.md +645 -8
  106. package/skills/rango/SKILL.md +1 -0
  107. package/skills/response-routes/SKILL.md +5 -5
  108. package/skills/route/SKILL.md +29 -0
  109. package/skills/testing/SKILL.md +2 -1
  110. package/skills/testing/cache-prerender.md +18 -17
  111. package/skills/testing/serve-shell-request.md +104 -8
  112. package/skills/use-cache/SKILL.md +9 -5
  113. package/skills/vercel/SKILL.md +2 -0
  114. package/skills/view-transitions/SKILL.md +9 -4
  115. package/src/browser/event-controller.ts +69 -25
  116. package/src/browser/link-interceptor.ts +2 -2
  117. package/src/browser/navigation-bridge.ts +75 -35
  118. package/src/browser/navigation-store.ts +26 -0
  119. package/src/browser/navigation-transaction.ts +9 -2
  120. package/src/browser/network-error-handler.ts +2 -0
  121. package/src/browser/partial-update.ts +48 -12
  122. package/src/browser/prefetch/default-strategy.ts +22 -42
  123. package/src/browser/react/Link.tsx +37 -42
  124. package/src/browser/react/NavigationProvider.tsx +63 -3
  125. package/src/browser/react/context.ts +17 -0
  126. package/src/browser/react/location-state.ts +5 -19
  127. package/src/browser/react/use-action.ts +4 -1
  128. package/src/browser/react/use-handle.ts +4 -20
  129. package/src/browser/react/use-link-status.ts +4 -3
  130. package/src/browser/react/use-navigation.ts +4 -1
  131. package/src/browser/react/use-params.ts +4 -1
  132. package/src/browser/react/use-pathname.ts +4 -1
  133. package/src/browser/react/use-search-params.ts +5 -3
  134. package/src/browser/react/use-segments.ts +36 -54
  135. package/src/browser/rsc-router.tsx +79 -39
  136. package/src/browser/segment-reconciler.ts +3 -3
  137. package/src/browser/server-action-bridge.ts +26 -6
  138. package/src/browser/types.ts +11 -0
  139. package/src/build/generate-manifest.ts +17 -0
  140. package/src/build/merge-full-manifests.ts +5 -0
  141. package/src/build/route-trie.ts +1 -0
  142. package/src/cache/background-task.ts +61 -0
  143. package/src/cache/cache-key-utils.ts +91 -12
  144. package/src/cache/cache-policy.ts +11 -2
  145. package/src/cache/cache-runtime.ts +23 -23
  146. package/src/cache/cache-scope.ts +38 -36
  147. package/src/cache/cf/cf-cache-store.ts +16 -11
  148. package/src/cache/document-cache.ts +35 -14
  149. package/src/cache/handle-snapshot.ts +50 -0
  150. package/src/cache/index.ts +1 -0
  151. package/src/cache/invalidation-order.ts +53 -0
  152. package/src/cache/memory-segment-store.ts +52 -1
  153. package/src/cache/shell-snapshot.ts +17 -0
  154. package/src/cache/store-scope.ts +36 -0
  155. package/src/cache/tag-invalidation.ts +7 -5
  156. package/src/cache/types.ts +69 -14
  157. package/src/cache/vercel/vercel-cache-store.ts +20 -6
  158. package/src/client.tsx +40 -3
  159. package/src/errors.ts +13 -6
  160. package/src/handles/deferred-resolution.ts +7 -2
  161. package/src/internal-suspense-audit.ts +12 -0
  162. package/src/loader-store.ts +4 -9
  163. package/src/outlet-provider.tsx +25 -1
  164. package/src/prerender/cloudflare.ts +130 -0
  165. package/src/prerender/create-prerender-trigger.ts +780 -0
  166. package/src/prerender/index.ts +39 -0
  167. package/src/prerender/memory-prerender-store.ts +115 -0
  168. package/src/prerender/on-demand.ts +339 -0
  169. package/src/prerender/producer-guard.ts +66 -0
  170. package/src/prerender/shell-manifest-key.ts +12 -17
  171. package/src/prerender/warm-request.ts +154 -0
  172. package/src/prerender/warm.ts +193 -0
  173. package/src/prerender/writable-store.ts +278 -0
  174. package/src/prerender.ts +29 -0
  175. package/src/reverse.ts +1 -1
  176. package/src/route-content-wrapper.tsx +107 -13
  177. package/src/router/error-handling.ts +12 -12
  178. package/src/router/find-match.ts +1 -0
  179. package/src/router/handler-context.ts +2 -0
  180. package/src/router/intercept-resolution.ts +15 -8
  181. package/src/router/loader-resolution.ts +2 -10
  182. package/src/router/match-middleware/background-revalidation.ts +2 -0
  183. package/src/router/match-middleware/cache-lookup.ts +230 -38
  184. package/src/router/pattern-matching.ts +14 -0
  185. package/src/router/prefetch-default.ts +4 -4
  186. package/src/router/prerender-match.ts +460 -352
  187. package/src/router/route-trie-builder.ts +9 -0
  188. package/src/router/router-context.ts +1 -0
  189. package/src/router/router-interfaces.ts +33 -0
  190. package/src/router/router-options.ts +30 -0
  191. package/src/router/segment-resolution/fresh.ts +20 -19
  192. package/src/router/segment-resolution/loader-cache.ts +15 -17
  193. package/src/router/segment-resolution/revalidation.ts +34 -24
  194. package/src/router/segment-resolution/streamed-handler-boundary.ts +133 -0
  195. package/src/router/trie-matching.ts +3 -0
  196. package/src/router.ts +107 -1
  197. package/src/rsc/handler.ts +51 -4
  198. package/src/rsc/progressive-enhancement.ts +5 -1
  199. package/src/rsc/response-cache-serve.ts +10 -4
  200. package/src/rsc/rsc-rendering.ts +53 -11
  201. package/src/rsc/shell-build-manifest.ts +10 -8
  202. package/src/rsc/shell-capture-constants.ts +39 -7
  203. package/src/rsc/shell-capture.ts +108 -19
  204. package/src/rsc/shell-serve.ts +12 -6
  205. package/src/rsc/ssr-module-loader.ts +26 -0
  206. package/src/rsc/types.ts +8 -0
  207. package/src/segment-boundary-content.ts +25 -0
  208. package/src/segment-loader-promise.ts +28 -38
  209. package/src/segment-system.tsx +117 -57
  210. package/src/server/build-version-table.ts +15 -0
  211. package/src/server/context.ts +40 -17
  212. package/src/server/cookie-store.ts +5 -0
  213. package/src/server/handle-store.ts +13 -0
  214. package/src/server/loader-registry.ts +6 -1
  215. package/src/server/request-context.ts +87 -1
  216. package/src/ssr/ssr-root.tsx +20 -13
  217. package/src/suspense-audit-react.tsx +98 -0
  218. package/src/suspense-audit.ts +1030 -0
  219. package/src/testing/action-form.ts +66 -0
  220. package/src/testing/flight-runtime.d.ts +27 -0
  221. package/src/testing/flight.entry.ts +3 -0
  222. package/src/testing/index.ts +19 -0
  223. package/src/testing/internal/server-modules.ts +32 -0
  224. package/src/testing/render-route.tsx +25 -12
  225. package/src/testing/serve-shell-request.ts +190 -34
  226. package/src/testing/shell-status.ts +17 -6
  227. package/src/testing/vitest-stubs/plugin-rsc.ts +37 -11
  228. package/src/thenable-status.ts +10 -0
  229. package/src/types/handler-context.ts +7 -0
  230. package/src/types/route-entry.ts +6 -0
  231. package/src/urls/path-helper.ts +69 -9
  232. package/src/use-loader.tsx +57 -30
  233. package/src/vite/discovery/bundle-postprocess.ts +4 -0
  234. package/src/vite/discovery/discover-routers.ts +15 -0
  235. package/src/vite/discovery/shell-prerender-phase.ts +5 -5
  236. package/src/vite/discovery/state.ts +17 -1
  237. package/src/vite/inject-client-debug.ts +42 -20
  238. package/src/vite/plugins/virtual-entries.ts +8 -1
  239. package/src/vite/router-discovery.ts +14 -0
  240. package/src/vite/utils/bundle-analysis.ts +39 -7
  241. package/dist/types/browser/react/subscribe-to-nothing.d.ts +0 -7
  242. package/dist/types/segment-content-promise.d.ts +0 -13
  243. package/src/browser/react/subscribe-to-nothing.ts +0 -7
  244. package/src/segment-content-promise.ts +0 -67
@@ -31,7 +31,7 @@ export type ParamsFor<TRoutes, TName extends keyof TRoutes> = ExtractParams<Rout
31
31
  /**
32
32
  * Check if an object type has any keys
33
33
  */
34
- type IsEmptyObject<T> = keyof T extends never ? true : false;
34
+ export type IsEmptyObject<T> = keyof T extends never ? true : false;
35
35
  /**
36
36
  * Extract search schema from a route entry.
37
37
  * Returns {} if no search schema is defined.
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from "react";
1
+ import type { ComponentProps, ReactNode } from "react";
2
2
  import { Component } from "react";
3
3
  import type { ResolvedSegment } from "./types.js";
4
4
  /**
@@ -70,6 +70,7 @@ export declare function RouteContentWrapper({ content, fallback, segmentId, }: {
70
70
  fallback?: ReactNode;
71
71
  segmentId?: string;
72
72
  }): ReactNode;
73
+ export declare function AuditedRouteContent({ content, fallback, segmentId, }: ComponentProps<typeof RouteContentWrapper>): ReactNode;
73
74
  /**
74
75
  * LoaderBoundary - Client component that resolves loader promises and renders OutletProvider
75
76
  *
@@ -102,3 +103,4 @@ export interface LoaderBoundaryProps {
102
103
  children: ReactNode;
103
104
  }
104
105
  export declare function LoaderBoundary({ loaderDataPromise, loaderIds, loaderStreams, awaitedLoaderIds, fallback, outletKey, outletContent, segment, parallel, children, }: LoaderBoundaryProps): ReactNode;
106
+ export declare function AuditedLoaderBoundary({ fallback, children, ...resolver }: LoaderBoundaryProps): ReactNode;
@@ -78,6 +78,8 @@ export declare function findNearestNotFoundBoundary(entry: EntryData | null, def
78
78
  * Sanitizes error details in production
79
79
  */
80
80
  export declare function createErrorInfo(error: unknown, segmentId: string, segmentType: ErrorInfo["segmentType"]): ErrorInfo;
81
+ /** Invoke an errorBoundary() fallback that may be a handler or a plain node. */
82
+ export declare function renderErrorFallback(fallback: ReactNode | ErrorBoundaryHandler, errorInfo: ErrorInfo): ReactNode;
81
83
  /**
82
84
  * Create an error segment with the fallback component
83
85
  * Renders the fallback with error info and reset function
@@ -37,7 +37,7 @@ export declare function createHandlerContext<TEnv>(params: Record<string, string
37
37
  * search, reverse, and use(handle) work. Request-time properties
38
38
  * (request, env, headers, cookies, get, set, res) throw with a clear error.
39
39
  */
40
- export declare function createPrerenderContext<TEnv>(params: Record<string, string>, pathname: string, routeMap: Record<string, string>, routeName?: string, buildVars?: Record<string, any>, isPassthroughRoute?: boolean, buildEnv?: TEnv, devMode?: boolean): InternalHandlerContext<any, TEnv>;
40
+ export declare function createPrerenderContext<TEnv>(params: Record<string, string>, pathname: string, routeMap: Record<string, string>, routeName?: string, buildVars?: Record<string, any>, isPassthroughRoute?: boolean, buildEnv?: TEnv, devMode?: boolean, onDemand?: boolean): InternalHandlerContext<any, TEnv>;
41
41
  /**
42
42
  * Create a StaticContext for Static() handlers at build time.
43
43
  *
@@ -94,6 +94,16 @@
94
94
  import type { ResolvedSegment } from "../../types.js";
95
95
  import { type EntryData } from "../../server/context.js";
96
96
  import type { MatchContext, MatchPipelineState } from "../match-context.js";
97
+ import type { PrerenderStore } from "../../prerender/store.js";
98
+ import type { PrerenderTargetObject, ResolvedPrerender } from "../../prerender/on-demand.js";
99
+ import { type RequestContext } from "../../server/request-context.js";
100
+ /**
101
+ * @internal Replace the prerender store this module serves from, and return
102
+ * the one it replaced. For serveShellRequest (testing/serve-shell-request.ts),
103
+ * which installs the production store over the artifacts it bakes for a call
104
+ * and puts the previous one back after it.
105
+ */
106
+ export declare function setPrerenderStoreForTests(store: PrerenderStore | null | undefined): PrerenderStore | null | undefined;
97
107
  /**
98
108
  * Whether the prerender store holds a baked entry for this route + params.
99
109
  * Consulted by the PPR replay gate (matchPartialWithPprReplay), which must
@@ -106,6 +116,10 @@ import type { MatchContext, MatchPipelineState } from "../match-context.js";
106
116
  * subsequent get() share one underlying load.
107
117
  */
108
118
  export declare function prerenderEntryExists(routeKey: string | undefined, params: Record<string, string>, pathname: string, entries: EntryData[]): Promise<boolean>;
119
+ /** @internal Tests only (testing/serve-shell-request.ts resetShellTestState). */
120
+ export declare function resetOverlayRevalidationsForTests(): void;
121
+ /** @internal Exported for the eviction unit test. */
122
+ export declare function scheduleOverlayRevalidation<TEnv>(serializedKey: string, onRevalidate: NonNullable<ResolvedPrerender["config"]["onRevalidate"]>, target: PrerenderTargetObject, reqCtx: RequestContext<TEnv>, now?: number): void;
109
123
  /**
110
124
  * Async generator middleware type
111
125
  */
@@ -134,6 +134,8 @@ export interface RouteMatchResult<TEnv = any> {
134
134
  pr?: true;
135
135
  /** Passthrough: handler kept for live fallback on unknown params (from trie) */
136
136
  pt?: true;
137
+ /** On-demand prerender eligible (router.prerender() refreshable) */
138
+ od?: true;
137
139
  /** Response type for non-RSC routes (json, text, image, any) */
138
140
  responseType?: string;
139
141
  /** Negotiate variants: response-type routes sharing this path */
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Resolve the router-wide default Link prefetch strategy once, at router init.
3
- * The resolved value ships to the client in payload metadata; the browser
4
- * entry applies it via `setDefaultPrefetchStrategy` (browser/prefetch/
5
- * default-strategy.ts) and every `<Link>` without an explicit `prefetch` prop
6
- * falls back to it.
3
+ * The resolved value ships to the client in payload metadata; the router
4
+ * store carries it (`NavigationStoreContext.defaultPrefetch`, see
5
+ * browser/prefetch/default-strategy.ts) and every `<Link>` without an explicit
6
+ * `prefetch` prop falls back to it.
7
7
  *
8
8
  * The type lives HERE (not in browser/react/Link.tsx) because both seats need
9
9
  * it: this server-side resolver and the client Link/default-strategy modules.
@@ -5,10 +5,19 @@ import type { PartialPrerenderProps } from "../urls/pattern-types.js";
5
5
  import type { HandlerContext, ResolvedSegment } from "../types";
6
6
  import type { SerializedSegmentData } from "../cache/types.js";
7
7
  import type { RouteMatchResult } from "./pattern-matching.js";
8
+ import type { RouterVersions } from "../router-versions.js";
9
+ import type { OnDemandRouteConfig } from "../prerender/on-demand.js";
8
10
  export interface PrerenderMatchDeps<TEnv = any> {
9
11
  /** Owning router id; scopes bake-time root-scope/search-schema lookups the
10
12
  * same way reqCtx._routerId does at runtime (issue #762). */
11
13
  routerId?: string;
14
+ /**
15
+ * The owning router's cache versions. Set on the requestless on-demand
16
+ * producer's context as `_versions`, so cache stores built inside the render
17
+ * key under the router's pair like a live request does instead of the
18
+ * whole-build fallback (server/build-version-table.ts getCacheVersions).
19
+ */
20
+ versions?: RouterVersions;
12
21
  findMatch: (pathname: string) => RouteMatchResult<TEnv> | null | Promise<RouteMatchResult<TEnv> | null>;
13
22
  buildRouterContext: () => RouterContext<TEnv>;
14
23
  mergedRouteMap: Record<string, string>;
@@ -20,7 +29,15 @@ export interface PrerenderMatchDeps<TEnv = any> {
20
29
  */
21
30
  export declare function matchForPrerender<TEnv = any>(pathname: string, params: Record<string, string>, deps: PrerenderMatchDeps<TEnv>, buildVars?: Record<string, any>, isPassthroughRoute?: boolean, buildEnv?: TEnv,
22
31
  /** Dev-only: check getParams() for passthrough routes to skip unknown params. */
23
- devMode?: boolean): Promise<{
32
+ devMode?: boolean,
33
+ /**
34
+ * Requestless on-demand refresh (router.prerender()). Arms the personalization
35
+ * guard: cookies()/headers()/response mutations throw a
36
+ * PrerenderPersonalizationError so the caller maps a personalized render to
37
+ * skipped-personalized instead of baking a shared payload. `buildEnv` here is
38
+ * the live trigger env, not the shared build env.
39
+ */
40
+ onDemand?: boolean): Promise<{
24
41
  segments: SerializedSegmentData[];
25
42
  /** RSC-encoded handle map ("" when none) — see handle-snapshot.ts. Encoded in
26
43
  * the producer (where the Flight codec resolves) so the node-side build/dev
@@ -33,6 +50,11 @@ devMode?: boolean): Promise<{
33
50
  * the sinks store it as-is (no longer merge raw records). */
34
51
  interceptHandles?: string;
35
52
  passthrough?: true;
53
+ /** On-demand only: the render hit `notFound()` and nothing else failed. */
54
+ notFound?: true;
55
+ /** Route-level onDemand config (ttl/tags) read off the route entry; only set
56
+ * when `onDemand` and the route declared an onDemand object literal. */
57
+ onDemandConfig?: OnDemandRouteConfig;
36
58
  /**
37
59
  * The matched route entry's `ppr` path option, surfaced so the build
38
60
  * collection can flag Prerender+ppr routes as build-time shell candidates
@@ -31,6 +31,12 @@ export interface TrieLeaf {
31
31
  pr?: true;
32
32
  /** Passthrough: handler kept in bundle for live fallback on unknown params */
33
33
  pt?: true;
34
+ /**
35
+ * On-demand prerender eligible: the route opted into router.prerender()
36
+ * refresh. Distinct from `pr` — an od route may have no build-baked entry yet
37
+ * still needs a writable-overlay lookup at serve time.
38
+ */
39
+ od?: true;
34
40
  /** Response type for non-RSC routes (json, text, image, any) */
35
41
  rt?: string;
36
42
  /** Negotiate variants: response-type routes sharing this path */
@@ -73,5 +79,6 @@ export interface TrieNode {
73
79
  * @param prerenderRouteNames - Optional set of prerendered route names (sets leaf.pr)
74
80
  * @param passthroughRouteNames - Optional set of passthrough route names (sets leaf.pt)
75
81
  * @param responseTypeRoutes - Optional map of route name to response type (sets leaf.rt)
82
+ * @param onDemandRouteNames - Optional set of on-demand-eligible route names (sets leaf.od)
76
83
  */
77
- export declare function buildRouteTrie(routeManifest: Record<string, string>, routeToStaticPrefix: Record<string, string>, routeTrailingSlash?: Record<string, string>, prerenderRouteNames?: Set<string>, passthroughRouteNames?: Set<string>, responseTypeRoutes?: Record<string, string>): TrieNode;
84
+ export declare function buildRouteTrie(routeManifest: Record<string, string>, routeToStaticPrefix: Record<string, string>, routeTrailingSlash?: Record<string, string>, prerenderRouteNames?: Set<string>, passthroughRouteNames?: Set<string>, responseTypeRoutes?: Record<string, string>, onDemandRouteNames?: Set<string>): TrieNode;
@@ -45,6 +45,7 @@ export interface RouterContext<TEnv = any> {
45
45
  getContext: () => {
46
46
  getOrCreateStore: (key: string) => any;
47
47
  runWithStore: <T>(store: any, namespace: string, parent: any, fn: () => T) => T;
48
+ runIsolated: <T>(forRoute: string, fn: () => T) => T;
48
49
  };
49
50
  getMetricsStore: () => MetricsStore | undefined;
50
51
  createCacheScope: (cacheConfig: any, parent: CacheScope | null) => CacheScope | null;
@@ -184,6 +184,28 @@ export interface Rango<TEnv = any, TRoutes extends Record<string, unknown> = Rec
184
184
  * ```
185
185
  */
186
186
  fetch(request: Request, input?: RouterRequestInput<TEnv>): Promise<Response>;
187
+ /**
188
+ * Bind `{ env, ctx }` and get the on-demand (ISR-style) prerender runner, to refresh from a running app —
189
+ * fetch handler, cron, queue, workflow, webhook, or server action.
190
+ *
191
+ * Requestless: the producer renders with route params and env only, never the
192
+ * caller's cookies/headers/session. Only routes that opted in via
193
+ * `Prerender(..., { onDemand })` are persistable; others return a skipped
194
+ * result. Configure the store via the `prerender` router option.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * const prerender = router.prerender({ env, ctx });
199
+ * await prerender("/products/42");
200
+ * await prerender(
201
+ * { route: "products.detail", params: { id: "42" } },
202
+ * { throwOnError: true },
203
+ * );
204
+ * await prerender.many(targets, { concurrency: 4 });
205
+ * await prerender.markStale(["product:42"]);
206
+ * ```
207
+ */
208
+ prerender: import("../prerender/on-demand.js").PrerenderFn<TEnv, TRoutes>;
187
209
  }
188
210
  /**
189
211
  * Internal Rango router interface — the full framework-facing API.
@@ -254,6 +276,12 @@ export interface RangoInternal<TEnv = any, TRoutes extends Record<string, unknow
254
276
  * Cache configuration
255
277
  */
256
278
  readonly cache?: RangoOptions<TEnv>["cache"];
279
+ /**
280
+ * Prerender store configuration (the writable durable overlay for on-demand
281
+ * prerender). Stored separately from the `prerender` trigger method so the RSC
282
+ * handler can resolve it per request. @internal
283
+ */
284
+ readonly _prerenderConfig?: RangoOptions<TEnv>["prerender"];
257
285
  /**
258
286
  * Not found component to render when no route matches
259
287
  */
@@ -471,6 +499,8 @@ export interface RangoInternal<TEnv = any, TRoutes extends Record<string, unknow
471
499
  * Handle an RSC request.
472
500
  */
473
501
  fetch(request: Request, input?: RouterRequestInput<TEnv>): Promise<Response>;
502
+ /** On-demand prerender binder: router.prerender({ env, ctx }) returns the runner. */
503
+ prerender: import("../prerender/on-demand.js").PrerenderFn<TEnv, TRoutes>;
474
504
  }
475
505
  /**
476
506
  * Assert a public Rango into the internal type.
@@ -314,6 +314,30 @@ export interface RangoOptions<TEnv = any> {
314
314
  enabled?: boolean;
315
315
  searchParams?: CacheSearchParams;
316
316
  });
317
+ /**
318
+ * Writable prerender store for on-demand (ISR-style) prerender refresh.
319
+ *
320
+ * A durable overlay in front of the bundled build manifest. When provided,
321
+ * `router.prerender(target, { env, ctx })` renders a route requestlessly and
322
+ * writes a versioned payload here; the serve path reads the overlay before the
323
+ * bundled manifest. Same union shape as `cache`: a plain config object or a
324
+ * factory resolved per request/per call (never at `createRouter()` time), so
325
+ * multi-tenant apps never memoize one request's binding for another.
326
+ *
327
+ * @example Cloudflare KV overlay with SWR revalidation
328
+ * ```typescript
329
+ * import { createKVPrerenderStore } from "@rangojs/router/prerender/cloudflare";
330
+ *
331
+ * const router = createRouter<AppEnv>({
332
+ * prerender: (env) => ({
333
+ * store: createKVPrerenderStore(env.PRERENDER_KV),
334
+ * ttl: 3600,
335
+ * onRevalidate: (target, e) => e.PRERENDER_QUEUE.send({ target }),
336
+ * }),
337
+ * });
338
+ * ```
339
+ */
340
+ prerender?: import("../prerender/on-demand.js").PrerenderConfig<TEnv> | ((env: TEnv, ctx?: ExecutionContext) => import("../prerender/on-demand.js").PrerenderConfig<TEnv>);
317
341
  /**
318
342
  * Named cache profiles for "use cache" directive.
319
343
  * Profile names map to TTL/SWR configuration.
@@ -37,6 +37,13 @@ export interface ResolveSegmentOptions {
37
37
  * #918: resolved twice on a MISS, once and discarded on a HIT).
38
38
  */
39
39
  chain?: readonly EntryData[];
40
+ /**
41
+ * The matched chain entry being resolved: where the sync path catches a
42
+ * handler error, so a streamed handler (or slot owned by a routeless layout)
43
+ * recovers into the same boundary. resolveSegment sets it for the entry it
44
+ * resolves; nested resolutions keep the outer value.
45
+ */
46
+ boundaryEntry?: EntryData;
40
47
  }
41
48
  /**
42
49
  * Resolve segments from EntryData.
@@ -9,7 +9,8 @@
9
9
  * 1. options.key(requestCtx) — full override, stored namespaced as
10
10
  * loader:{loaderId}:key:{encodeURIComponent(result)} (#1009)
11
11
  * 2. store.keyGenerator(requestCtx, defaultKey) — store-level modification
12
- * 3. loader:{loaderId}:{host}{pathname}:{sortedParams} — default
12
+ * 3. loader:{loaderId}:{routerId}@{host}{pathname}:{sortedParams} — default
13
+ * (a loader's ctx is one router's: cache-key-utils.ts, the router rule)
13
14
  *
14
15
  * Values are serialized via RSC Flight (serializeResult/deserializeResult),
15
16
  * supporting ReactNode, Promises, null, and all RSC-serializable types.
@@ -51,6 +51,8 @@ export declare function resolveParallelSegmentsWithRevalidation<TEnv>(entry: Ent
51
51
  * to it: loader sub-ids are filtered out and slots are re-grouped by parent).
52
52
  */
53
53
  loaderOrder?: "after" | "before";
54
+ /** Matched chain entry being resolved; see ResolveSegmentOptions.boundaryEntry. */
55
+ boundaryEntry?: EntryData;
54
56
  }): Promise<SegmentRevalidationResult>;
55
57
  /**
56
58
  * Resolve entry handler (layout, cache, or route) with revalidation.
@@ -74,7 +76,9 @@ chain?: readonly EntryData[]): Promise<SegmentRevalidationResult>;
74
76
  */
75
77
  export declare function resolveOrphanLayoutWithRevalidation<TEnv>(orphan: EntryData, params: Record<string, string>, context: HandlerContext<any, TEnv>, clientSegmentIds: Set<string>, prevParams: Record<string, string>, request: Request, prevUrl: URL, nextUrl: URL, routeKey: string, belongsToRoute: boolean, deps: SegmentResolutionDeps<TEnv>, actionContext?: ActionContext, stale?: boolean,
76
78
  /** Parent route entry — its loaders are inherited so parallel slots can access them. */
77
- parentRouteEntry?: EntryData): Promise<SegmentRevalidationResult>;
79
+ parentRouteEntry?: EntryData,
80
+ /** Matched chain entry being resolved (see ResolveSegmentOptions.boundaryEntry); defaults to parentRouteEntry. */
81
+ boundaryEntry?: EntryData | undefined): Promise<SegmentRevalidationResult>;
78
82
  /**
79
83
  * Resolve all segments for a route with revalidation logic (for matchPartial).
80
84
  */
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Streamed handlers (loading()): track, observe, and recover a rejection into
3
+ * the declared errorBoundary() / notFoundBoundary() fallback.
4
+ *
5
+ * Invariants:
6
+ * - No status write and no onError call: the status is committed at first
7
+ * flush, and trackHandler already reports each rejection once.
8
+ * - The recovered promise resolves, so Flight reports no error. The writers
9
+ * that refuse a failed render through Flight errors need the failure
10
+ * recorded here: `_renderErrors` for the document cache and a prerender
11
+ * warm, `_recoveredHandlerErrors` for cacheRoute (cache(), and the doc record
12
+ * a PPR capture needs). The shell capture and the SWR re-render own both,
13
+ * so a derived render never writes into (or reads) the foreground's.
14
+ * - Nothing to render to rethrows the original rejection: no boundary found, a
15
+ * thrown Response (redirect), a Skip, a throwing fallback.
16
+ * - No recovery when `recover` is false (prerender throwOnError, the intercept
17
+ * background re-render): those lanes must reject so nothing is baked/cached.
18
+ */
19
+ import type { ReactNode } from "react";
20
+ import type { EntryData } from "../../server/context.js";
21
+ import type { ErrorInfo, HandlerContext } from "../../types/index.js";
22
+ import type { SegmentResolutionDeps } from "../types.js";
23
+ export interface StreamedHandlerOptions<TEnv> {
24
+ /**
25
+ * Entry to look boundaries up from: the matched chain entry being resolved
26
+ * (where the sync path catches, whatever routeless layout owns a slot), or
27
+ * the intercept's declaring entry.
28
+ */
29
+ boundaryEntry: EntryData;
30
+ segmentId: string;
31
+ segmentType: ErrorInfo["segmentType"];
32
+ context: HandlerContext<any, TEnv>;
33
+ routeKey?: string;
34
+ params: Record<string, string>;
35
+ /** False where the rejection must reach the caller (prerender, intercept background re-render). */
36
+ recover: boolean;
37
+ }
38
+ /**
39
+ * Track a streamed handler promise and return the segment component: the
40
+ * tracked promise itself when there is nothing to recover to, else a promise
41
+ * that resolves to the declared fallback on rejection.
42
+ */
43
+ export declare function trackStreamedHandler<TEnv>(deps: SegmentResolutionDeps<TEnv>, result: Promise<unknown>, options: StreamedHandlerOptions<TEnv>): ReactNode;
@@ -18,6 +18,8 @@ export interface TrieMatchResult {
18
18
  pr?: true;
19
19
  /** Passthrough: handler kept for live fallback on unknown params */
20
20
  pt?: true;
21
+ /** On-demand prerender eligible (router.prerender() refreshable) */
22
+ od?: true;
21
23
  /** Response type for non-RSC routes (json, text, image, any) */
22
24
  responseType?: string;
23
25
  /** Negotiate variants: response-type routes sharing this path */
@@ -36,7 +36,7 @@ export interface BuildShellEntry {
36
36
  tags?: string[];
37
37
  }
38
38
  interface ShellManifestModule {
39
- /** Manifest key (pathname — see shell-manifest-key.ts) -> asset specifier. */
39
+ /** Manifest key (router id + pathname, shell-manifest-key.ts) -> asset specifier. */
40
40
  default: Record<string, string>;
41
41
  loadShellAsset: (spec: string) => Promise<{
42
42
  default: BuildShellEntry;
@@ -80,11 +80,13 @@ export interface DevShellLookup {
80
80
  * request is search-less, like the entries lookupBuildShell serves): a
81
81
  * manifest entry for the path in production, a Prerender route in dev. No
82
82
  * asset load and no dev capture: it only decides whether a request that
83
- * cannot read the build shell deserves a warning.
83
+ * cannot read the build shell deserves a warning. The manifest entry is the
84
+ * one staged for the router `routerId` (shell-manifest-key.ts).
84
85
  */
85
- export declare function hasBuildShell(pathname: string, dev?: DevShellLookup): Promise<boolean>;
86
+ export declare function hasBuildShell(routerId: string, pathname: string, dev?: DevShellLookup): Promise<boolean>;
86
87
  /**
87
88
  * Look up the baked shell entry for a request, applying every serve gate:
89
+ * the serving router's own entry only (`routerId`, shell-manifest-key.ts),
88
90
  * search-less requests only (the build captured the bare pathname; a
89
91
  * search-bearing URL has its own shell identity owned by runtime capture),
90
92
  * version validity, payload integrity, and tag-invalidation markers. Returns
@@ -96,5 +98,5 @@ export declare function hasBuildShell(pathname: string, dev?: DevShellLookup): P
96
98
  * exclusion) matches the baked shell — ad-click traffic is exactly the
97
99
  * traffic the shell was prerendered for.
98
100
  */
99
- export declare function lookupBuildShell(url: URL, buildVersion: string, store: SegmentCacheStore, dev?: DevShellLookup, filter?: SearchParamsFilter): Promise<BuildShellHit | null>;
101
+ export declare function lookupBuildShell(routerId: string, url: URL, buildVersion: string, store: SegmentCacheStore, dev?: DevShellLookup, filter?: SearchParamsFilter): Promise<BuildShellHit | null>;
100
102
  export {};
@@ -56,13 +56,14 @@ export type PprReplayBypassReason = (typeof PPR_REPLAY_BYPASS_REASONS)[number];
56
56
  */
57
57
  export declare function shellSearchSeed(url: URL, filter?: SearchParamsFilter): string;
58
58
  /**
59
- * Shell cache key: host + pathname + sorted search + a `:shell` namespace suffix
60
- * (so it can never collide with a document-cache key; the store further isolates
61
- * the shell family internally).
59
+ * Shell cache key: router id + host + pathname + sorted search + a `:shell`
60
+ * namespace suffix (so it can never collide with a document-cache key; the
61
+ * store further isolates the shell family internally).
62
62
  *
63
63
  * The key includes the request HOST: in a multi-tenant host-router deployment
64
64
  * (one worker, one shared KV/runtime-cache store) a host-less key would serve
65
- * tenant A's captured shell to tenant B's users.
65
+ * tenant A's captured shell to tenant B's users. It starts with the serving
66
+ * ROUTER for the same reason (cache-key-utils.ts, the router rule).
66
67
  *
67
68
  * `filter` is the request's compiled `cache.searchParams` config
68
69
  * (ctx._searchParamsFilter): excluded params collapse onto one shell slot.
@@ -70,7 +71,7 @@ export declare function shellSearchSeed(url: URL, filter?: SearchParamsFilter):
70
71
  * and lookup makes every shell request a permanent miss. The testing helper
71
72
  * `shellCacheKey` (testing/shell-status.ts) builds its key with it too.
72
73
  */
73
- export declare function buildShellKey(url: URL, filter?: SearchParamsFilter): string;
74
+ export declare function buildShellKey(routerId: string, url: URL, filter?: SearchParamsFilter): string;
74
75
  /**
75
76
  * The shell key for one request partition (cache-scope.ts
76
77
  * resolveShellPartition): the route cache() `key()` or store keyGenerator
@@ -133,6 +134,20 @@ export declare const POST_QUIESCE_TASK_HOPS = 16;
133
134
  * check on the stampede guard, keyed off the same constant.
134
135
  */
135
136
  export declare const SHELL_CAPTURE_TASK_HARD_CAP_MS = 25000;
137
+ /**
138
+ * Why a capture attempt refused to store its shell
139
+ * (ShellCaptureDebugEvent.refusal, `caches.refusal` on a `router.prerender()`
140
+ * result): `identity` (a request-scoped read: cookies(), headers(), the
141
+ * theme, a `{ cache: false }` variable), `dynamic` (`ctx.dynamic()`),
142
+ * `loader` (a `{ ssr: false }` loader rejected, or settled with
143
+ * redirect()/notFound()), `no-record` (no doc record: the route's cache()
144
+ * refused the write, or the handler output failed), `handles` (a pushed
145
+ * handle value did not finish encoding), `size` (over the store's value
146
+ * limit), `record-expired` (the route cache() record the capture wrote ran
147
+ * out first), `invalidated` (a tag of the shell was invalidated after the
148
+ * capture started), `uncacheable` (the store cannot hold the entry).
149
+ */
150
+ export type ShellCaptureRefusal = "identity" | "dynamic" | "loader" | "no-record" | "handles" | "size" | "record-expired" | "invalidated" | "uncacheable";
136
151
  /**
137
152
  * Shared PPR loader-lane hint, appended to every capture warning or error
138
153
  * whose fix depends on the lane (shell-capture.ts warnings, the cookie-store.ts
@@ -19,6 +19,7 @@
19
19
  * (variables, cache store). Guarding is serve-time.
20
20
  */
21
21
  import { type MatchResult } from "../types.js";
22
+ import { type ShellCaptureRefusal } from "./shell-capture-constants.js";
22
23
  import { type RequestContext, type RouteRecordWindow } from "../server/request-context.js";
23
24
  import { type HandleStore } from "../server/handle-store.js";
24
25
  import type { SegmentCacheStore } from "../cache/types.js";
@@ -170,6 +171,8 @@ export interface ShellCaptureDebugEvent {
170
171
  untaggedBake?: true;
171
172
  /** Outcome reported by a store that supports shell-write acknowledgements. */
172
173
  storeWrite?: "stored" | "invalidated" | "uncacheable";
174
+ /** Why a `refused` attempt refused. */
175
+ refusal?: ShellCaptureRefusal;
173
176
  /** Consecutive failure count in the key's backoff entry, when one exists. */
174
177
  backoffFailures?: number;
175
178
  /** Ms remaining in the key's backoff window, when one exists. */
@@ -335,6 +338,15 @@ export interface ShellCaptureDescriptor {
335
338
  * re-render the page and drop the isolate's memo of the shell just stored.
336
339
  */
337
340
  storedSeqAtRead?: number;
341
+ /**
342
+ * A `router.prerender()` warm's capture (rsc-rendering.ts shellServePlan):
343
+ * one explicit call that must store, so the guards that shed a herd of
344
+ * visitors do not apply to it. scheduleShellCapture skips the in-flight
345
+ * dedup and the refused-capture backoff, and attemptCapture waits longer on
346
+ * the write barrier. Every correctness guard, the inert-store skip and the
347
+ * queue limits still decide.
348
+ */
349
+ force?: true;
338
350
  }
339
351
  /** The latest stored capture's sequence number for `key` in this isolate, or 0. */
340
352
  export declare function lastStoredCaptureSeq(key: string): number;
@@ -400,7 +412,7 @@ type CaptureTaskOutcome = "stored" | "redirect" | "no-shell";
400
412
  * the warning. A plain mutable bag, not a return value: captureAndStoreShell's
401
413
  * outcome type stays a string union producer B consumes unchanged.
402
414
  */
403
- type CaptureAttemptStats = Pick<ShellCaptureDebugEvent, "barrierWaitMs" | "writeSettleMs" | "preludeBytes" | "snapshotBytes" | "snapshotSkipped" | "untaggedBake" | "storeWrite" | "recordSettleMs" | "entryBytes"> & {
415
+ type CaptureAttemptStats = Pick<ShellCaptureDebugEvent, "barrierWaitMs" | "writeSettleMs" | "preludeBytes" | "snapshotBytes" | "snapshotSkipped" | "untaggedBake" | "storeWrite" | "refusal" | "recordSettleMs" | "entryBytes"> & {
404
416
  /**
405
417
  * Why a no-shell attempt ran out of ppr.captureTimeout (the match, the
406
418
  * handler output, or the prerender after them). A set cause skips the
@@ -462,6 +474,7 @@ export type CaptureRecordOutcome = {
462
474
  reason: string;
463
475
  } | {
464
476
  kind: "refused";
477
+ refusal: ShellCaptureRefusal;
465
478
  };
466
479
  /**
467
480
  * Record-first capture: the doc record is both the settle signal and the
@@ -274,7 +274,7 @@ export declare function warnPprWindowCappedOnce(routeName: string, ppr: {
274
274
  * Whether a partitioned request needs no build-shell probe: its route was
275
275
  * already warned, or its path was already found without one.
276
276
  */
277
- export declare function partitionBuildShellCheckDone(pathname: string, routeName: string | undefined): boolean;
277
+ export declare function partitionBuildShellCheckDone(routerId: string, pathname: string, routeName: string | undefined): boolean;
278
278
  /**
279
279
  * Record a partitioned request's build-shell probe, and warn once per route
280
280
  * when it found one: the route has a build-time shell its requests cannot
@@ -285,7 +285,7 @@ export declare function partitionBuildShellCheckDone(pathname: string, routeName
285
285
  * declared-intent-cannot-be-honored doctrine as the warnings above; a path
286
286
  * with no build shell stays silent.
287
287
  */
288
- export declare function notePartitionBuildShellCheck(pathname: string, routeName: string | undefined, found: boolean): void;
288
+ export declare function notePartitionBuildShellCheck(routerId: string, pathname: string, routeName: string | undefined, found: boolean): void;
289
289
  /**
290
290
  * @internal Reset the serve path's once-per-key warnings (the shell path's
291
291
  * one registry), its build-shell probe memo and buffered tail timings. Tests
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The SSR module loader a handler created without `loadSSRModule` falls back
3
+ * to in tests (`router.fetch` creates its handler that way). A leaf with no
4
+ * runtime imports: testing/serve-shell-request.ts installs its stub here when
5
+ * it loads, without importing rsc/handler.ts (which binds build-only virtual
6
+ * modules a flight-only test config does not alias).
7
+ */
8
+ import type { LoadSSRModule } from "./types.js";
9
+ /**
10
+ * @internal Tests only: `router.prerender()` warms through `router.fetch`,
11
+ * and the rsc Vitest project cannot run `import.meta.viteRsc.loadModule`.
12
+ */
13
+ export declare function setDefaultSSRModuleLoaderForTests(loader: LoadSSRModule | undefined): void;
14
+ /** @internal Undefined everywhere but in tests. */
15
+ export declare function defaultSSRModuleLoaderForTests(): LoadSSRModule | undefined;
@@ -103,6 +103,14 @@ export interface RscPayload {
103
103
  ok: boolean;
104
104
  data: unknown;
105
105
  };
106
+ /**
107
+ * useActionState form state of a progressive-enhancement POST re-render
108
+ * (the value the SSR render received). Present only on that document; the
109
+ * browser entry passes it to hydrateRoot so the hydrated hook matches the
110
+ * server HTML instead of resetting to its initial state. A promise so a
111
+ * state Flight cannot serialize rejects this slot alone.
112
+ */
113
+ formState?: Promise<ReactFormState>;
106
114
  }
107
115
  /**
108
116
  * React form state type for useActionState progressive enhancement
@@ -0,0 +1,17 @@
1
+ import type { ReactNode } from "react";
2
+ /**
3
+ * What a RouteContentWrapper receives as `content`.
4
+ *
5
+ * Browser: hand over the settled value. React treats a promise as fulfilled
6
+ * only after it has read it, and a boundary on screen handed a promise it has
7
+ * not read, in a render that cannot wait, shows its fallback. A component that
8
+ * is already a promise (a Flight-streamed segment) is returned as is, since
9
+ * it can really be pending.
10
+ *
11
+ * Server: a fresh `Promise.resolve(component)` per call, so Suspense emits the
12
+ * fallback in the streamed HTML. A shared resolved promise would carry React's
13
+ * `.status` across requests and skip it.
14
+ *
15
+ * @internal
16
+ */
17
+ export declare function getBoundaryContent(component: ReactNode): ReactNode;
@@ -10,12 +10,8 @@ import type { ResolvedSegment } from "./types.js";
10
10
  */
11
11
  export declare function buildLoaderPromise(loaders: ResolvedSegment[]): Promise<any[]>;
12
12
  /**
13
- * Memoize an aggregate Promise.all for a set of loader segments. Reusing the
14
- * same aggregate across renders — invalidated only when any underlying
15
- * loader.loaderData ref changes — keeps React's `use()` in "known fulfilled"
16
- * state and prevents a fresh Promise.all from suspending (and briefly
17
- * committing the Suspense fallback) on every partial update that doesn't
18
- * actually change loader data.
13
+ * The aggregate for a set of loader segments, memoized on their `loaderData`
14
+ * refs: the settled array once it has fulfilled, the promise before that.
19
15
  *
20
16
  * @internal
21
17
  */
@@ -8,6 +8,15 @@ import { type RouterVersions, type RouterVersionsTable } from "../router-version
8
8
  * 3. `VERSION` for both: the dev stamp, bumped on every RSC module edit.
9
9
  */
10
10
  export declare function resolveRouterVersions(routerId: string | undefined, override?: string): RouterVersions;
11
+ /**
12
+ * The version an on-demand prerender overlay key carries: the router's data
13
+ * version, because the overlay stores segment data, as the segment cache does
14
+ * (a client-only deploy keeps both). The write side (`router.prerender`,
15
+ * router.ts) and the read side (rsc/handler.ts) both call this with
16
+ * `createRouter({ version })`, the only override the trigger can see, so they
17
+ * cannot disagree; a `createRSCHandler({ version })` does not move it.
18
+ */
19
+ export declare function resolvePrerenderVersion(routerId: string | undefined, routerVersion: string | undefined): string;
11
20
  /**
12
21
  * The versions of the router serving the current request, for a cache store
13
22
  * building a key. A store operation with no request context (a detached task