@rangojs/router 0.20.0 → 0.22.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 (331) hide show
  1. package/dist/bin/rango.js +39 -15
  2. package/dist/types/browser/event-controller.d.ts +49 -0
  3. package/dist/types/browser/history-state.d.ts +16 -4
  4. package/dist/types/browser/navigation-store.d.ts +9 -0
  5. package/dist/types/browser/navigation-transaction.d.ts +7 -0
  6. package/dist/types/browser/partial-update.d.ts +2 -1
  7. package/dist/types/browser/prefetch/default-strategy.d.ts +16 -20
  8. package/dist/types/browser/rango-state.d.ts +3 -1
  9. package/dist/types/browser/react/NavigationProvider.d.ts +14 -1
  10. package/dist/types/browser/react/context.d.ts +25 -0
  11. package/dist/types/browser/react/location-state-shared.d.ts +84 -10
  12. package/dist/types/browser/react/location-state.d.ts +7 -2
  13. package/dist/types/browser/rsc-router.d.ts +13 -2
  14. package/dist/types/browser/types.d.ts +10 -0
  15. package/dist/types/build/generate-manifest.d.ts +2 -0
  16. package/dist/types/cache/background-task.d.ts +22 -0
  17. package/dist/types/cache/cache-key-utils.d.ts +50 -5
  18. package/dist/types/cache/cache-policy.d.ts +17 -0
  19. package/dist/types/cache/cache-scope.d.ts +5 -6
  20. package/dist/types/cache/cf/cf-cache-store.d.ts +34 -7
  21. package/dist/types/cache/cf/cf-cache-types.d.ts +12 -4
  22. package/dist/types/cache/document-cache.d.ts +8 -5
  23. package/dist/types/cache/handle-snapshot.d.ts +59 -50
  24. package/dist/types/cache/index.d.ts +3 -1
  25. package/dist/types/cache/invalidation-order.d.ts +14 -0
  26. package/dist/types/cache/memory-segment-store.d.ts +33 -1
  27. package/dist/types/cache/shell-snapshot.d.ts +29 -4
  28. package/dist/types/cache/store-scope.d.ts +22 -0
  29. package/dist/types/cache/tag-invalidation.d.ts +7 -6
  30. package/dist/types/cache/types.d.ts +84 -24
  31. package/dist/types/cache/vercel/vercel-cache-store.d.ts +35 -17
  32. package/dist/types/client-urls/navigation.d.ts +7 -1
  33. package/dist/types/client-urls/optimistic-location.d.ts +10 -4
  34. package/dist/types/errors.d.ts +6 -0
  35. package/dist/types/handles/deferred-resolution.d.ts +18 -1
  36. package/dist/types/internal-suspense-audit.d.ts +1 -0
  37. package/dist/types/loader-store.d.ts +4 -8
  38. package/dist/types/outlet-provider.d.ts +2 -1
  39. package/dist/types/prerender/build-shell-capture.d.ts +8 -6
  40. package/dist/types/prerender/cloudflare.d.ts +49 -0
  41. package/dist/types/prerender/create-prerender-trigger.d.ts +121 -0
  42. package/dist/types/prerender/index.d.ts +12 -0
  43. package/dist/types/prerender/memory-prerender-store.d.ts +29 -0
  44. package/dist/types/prerender/on-demand.d.ts +272 -0
  45. package/dist/types/prerender/producer-guard.d.ts +33 -0
  46. package/dist/types/prerender/shell-manifest-key.d.ts +1 -18
  47. package/dist/types/prerender/warm-request.d.ts +65 -0
  48. package/dist/types/prerender/warm.d.ts +65 -0
  49. package/dist/types/prerender/writable-store.d.ts +170 -0
  50. package/dist/types/prerender.d.ts +27 -0
  51. package/dist/types/reverse.d.ts +1 -1
  52. package/dist/types/route-content-wrapper.d.ts +3 -1
  53. package/dist/types/router/error-handling.d.ts +2 -0
  54. package/dist/types/router/handler-context.d.ts +1 -1
  55. package/dist/types/router/match-middleware/cache-lookup.d.ts +15 -1
  56. package/dist/types/router/navigation-snapshot.d.ts +8 -1
  57. package/dist/types/router/pattern-matching.d.ts +2 -0
  58. package/dist/types/router/prefetch-default.d.ts +4 -4
  59. package/dist/types/router/prerender-match.d.ts +23 -1
  60. package/dist/types/router/route-trie-builder.d.ts +8 -1
  61. package/dist/types/router/router-context.d.ts +1 -0
  62. package/dist/types/router/router-interfaces.d.ts +32 -1
  63. package/dist/types/router/router-options.d.ts +39 -5
  64. package/dist/types/router/segment-resolution/fresh.d.ts +7 -0
  65. package/dist/types/router/segment-resolution/loader-cache.d.ts +23 -10
  66. package/dist/types/router/segment-resolution/revalidation.d.ts +5 -1
  67. package/dist/types/router/segment-resolution/streamed-handler-boundary.d.ts +43 -0
  68. package/dist/types/router/trie-matching.d.ts +2 -0
  69. package/dist/types/router-versions.d.ts +39 -0
  70. package/dist/types/rsc/handler-context.d.ts +5 -0
  71. package/dist/types/rsc/shell-build-manifest.d.ts +9 -6
  72. package/dist/types/rsc/shell-capture-constants.d.ts +20 -5
  73. package/dist/types/rsc/shell-capture.d.ts +14 -1
  74. package/dist/types/rsc/shell-serve.d.ts +2 -2
  75. package/dist/types/rsc/ssr-module-loader.d.ts +15 -0
  76. package/dist/types/rsc/types.d.ts +12 -6
  77. package/dist/types/segment-boundary-content.d.ts +17 -0
  78. package/dist/types/segment-loader-promise.d.ts +2 -6
  79. package/dist/types/server/build-version-table.d.ts +53 -0
  80. package/dist/types/server/context.d.ts +12 -4
  81. package/dist/types/server/handle-store.d.ts +89 -46
  82. package/dist/types/server/request-context.d.ts +84 -9
  83. package/dist/types/suspense-audit-react.d.ts +26 -0
  84. package/dist/types/suspense-audit.d.ts +157 -0
  85. package/dist/types/testing/action-form.d.ts +34 -0
  86. package/dist/types/testing/build-versions.d.ts +32 -0
  87. package/dist/types/testing/dom.entry.d.ts +1 -1
  88. package/dist/types/testing/flight.entry.d.ts +3 -1
  89. package/dist/types/testing/index.d.ts +6 -0
  90. package/dist/types/testing/internal/seed-vars.d.ts +7 -2
  91. package/dist/types/testing/internal/server-modules.d.ts +8 -0
  92. package/dist/types/testing/location-state-key.d.ts +5 -1
  93. package/dist/types/testing/render-route.d.ts +77 -6
  94. package/dist/types/testing/serve-shell-request.d.ts +55 -4
  95. package/dist/types/testing/shell-status.d.ts +14 -6
  96. package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +9 -6
  97. package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
  98. package/dist/types/thenable-status.d.ts +6 -0
  99. package/dist/types/types/handler-context.d.ts +15 -5
  100. package/dist/types/types/route-entry.d.ts +5 -0
  101. package/dist/types/urls/path-helper.d.ts +18 -0
  102. package/dist/types/vite/discovery/build-versions.d.ts +393 -0
  103. package/dist/types/vite/discovery/installed-packages.d.ts +26 -0
  104. package/dist/types/vite/discovery/router-versions-phase.d.ts +52 -0
  105. package/dist/types/vite/discovery/shell-prerender-phase.d.ts +7 -17
  106. package/dist/types/vite/discovery/state.d.ts +25 -0
  107. package/dist/types/vite/encryption-key.d.ts +18 -0
  108. package/dist/types/vite/inject-client-debug.d.ts +6 -25
  109. package/dist/types/vite/plugin-types.d.ts +27 -0
  110. package/dist/types/vite/plugins/{version-injector.d.ts → entry-bootstrap-injector.d.ts} +4 -6
  111. package/dist/types/vite/plugins/expose-ids/export-analysis.d.ts +1 -0
  112. package/dist/types/vite/plugins/expose-ids/router-transform.d.ts +14 -0
  113. package/dist/types/vite/plugins/stable-rsc-output.d.ts +51 -0
  114. package/dist/types/vite/plugins/version-plugin.d.ts +9 -11
  115. package/dist/types/vite/plugins/virtual-entries.d.ts +18 -1
  116. package/dist/types/vite/router-discovery.d.ts +6 -0
  117. package/dist/types/vite/utils/bundle-analysis.d.ts +6 -2
  118. package/dist/types/vite/utils/client-chunks.d.ts +2 -0
  119. package/dist/types/vite/utils/compare-strings.d.ts +7 -0
  120. package/dist/types/vite/utils/package-resolution.d.ts +8 -0
  121. package/dist/types/vite/utils/prerender-utils.d.ts +2 -0
  122. package/dist/vite/index.js +1707 -931
  123. package/package.json +12 -3
  124. package/skills/cache-guide/SKILL.md +102 -37
  125. package/skills/caching/SKILL.md +56 -9
  126. package/skills/catalog.json +1 -1
  127. package/skills/client-urls/SKILL.md +16 -0
  128. package/skills/cloudflare/SKILL.md +133 -1
  129. package/skills/comparison/references/framework-comparison.md +17 -13
  130. package/skills/deployment-caching/SKILL.md +33 -12
  131. package/skills/document-cache/SKILL.md +16 -14
  132. package/skills/hooks/SKILL.md +25 -0
  133. package/skills/hooks/handle-and-actions.md +5 -0
  134. package/skills/hooks/navigation.md +38 -0
  135. package/skills/hooks/state.md +213 -11
  136. package/skills/hooks/urls.md +40 -1
  137. package/skills/host-router/SKILL.md +31 -0
  138. package/skills/intercept/SKILL.md +6 -0
  139. package/skills/loader/SKILL.md +25 -5
  140. package/skills/middleware/SKILL.md +2 -0
  141. package/skills/migrate-nextjs/SKILL.md +82 -9
  142. package/skills/ppr/SKILL.md +150 -48
  143. package/skills/prerender/SKILL.md +651 -10
  144. package/skills/rango/SKILL.md +9 -7
  145. package/skills/response-routes/SKILL.md +5 -5
  146. package/skills/route/SKILL.md +29 -0
  147. package/skills/router-setup/SKILL.md +15 -1
  148. package/skills/testing/SKILL.md +32 -27
  149. package/skills/testing/cache-prerender.md +18 -17
  150. package/skills/testing/client-components.md +193 -8
  151. package/skills/testing/handles.md +2 -0
  152. package/skills/testing/loader.md +1 -1
  153. package/skills/testing/middleware.md +1 -1
  154. package/skills/testing/render-handler.md +18 -18
  155. package/skills/testing/serve-shell-request.md +167 -22
  156. package/skills/testing/server-actions.md +17 -17
  157. package/skills/testing/server-tree.md +1 -1
  158. package/skills/typesafety/generated-files-and-cli.md +1 -1
  159. package/skills/use-cache/SKILL.md +25 -10
  160. package/skills/vercel/SKILL.md +5 -3
  161. package/skills/view-transitions/SKILL.md +9 -4
  162. package/src/bin/rango.ts +1 -1
  163. package/src/browser/event-controller.ts +119 -2
  164. package/src/browser/history-state.ts +39 -17
  165. package/src/browser/link-interceptor.ts +2 -2
  166. package/src/browser/navigation-bridge.ts +104 -41
  167. package/src/browser/navigation-store.ts +26 -0
  168. package/src/browser/navigation-transaction.ts +24 -12
  169. package/src/browser/network-error-handler.ts +2 -0
  170. package/src/browser/partial-update.ts +58 -14
  171. package/src/browser/prefetch/default-strategy.ts +22 -42
  172. package/src/browser/rango-state.ts +3 -1
  173. package/src/browser/react/Link.tsx +37 -43
  174. package/src/browser/react/NavigationProvider.tsx +85 -1
  175. package/src/browser/react/context.ts +30 -0
  176. package/src/browser/react/location-state-shared.ts +200 -34
  177. package/src/browser/react/location-state.ts +28 -77
  178. package/src/browser/react/use-action.ts +4 -1
  179. package/src/browser/react/use-handle.ts +3 -0
  180. package/src/browser/react/use-link-status.ts +4 -3
  181. package/src/browser/react/use-navigation.ts +4 -1
  182. package/src/browser/react/use-params.ts +4 -1
  183. package/src/browser/react/use-pathname.ts +4 -1
  184. package/src/browser/react/use-search-params.ts +5 -3
  185. package/src/browser/react/use-segments.ts +36 -54
  186. package/src/browser/rsc-router.tsx +93 -31
  187. package/src/browser/segment-reconciler.ts +3 -3
  188. package/src/browser/server-action-bridge.ts +43 -7
  189. package/src/browser/types.ts +11 -0
  190. package/src/build/generate-manifest.ts +17 -0
  191. package/src/build/merge-full-manifests.ts +5 -0
  192. package/src/build/route-trie.ts +1 -0
  193. package/src/cache/background-task.ts +61 -0
  194. package/src/cache/cache-key-utils.ts +91 -12
  195. package/src/cache/cache-policy.ts +11 -2
  196. package/src/cache/cache-runtime.ts +23 -23
  197. package/src/cache/cache-scope.ts +48 -36
  198. package/src/cache/cf/cf-cache-store.ts +91 -66
  199. package/src/cache/cf/cf-cache-types.ts +12 -4
  200. package/src/cache/document-cache.ts +35 -14
  201. package/src/cache/handle-snapshot.ts +118 -86
  202. package/src/cache/index.ts +5 -0
  203. package/src/cache/invalidation-order.ts +53 -0
  204. package/src/cache/memory-segment-store.ts +52 -1
  205. package/src/cache/shell-snapshot.ts +52 -5
  206. package/src/cache/store-scope.ts +36 -0
  207. package/src/cache/tag-invalidation.ts +7 -5
  208. package/src/cache/types.ts +90 -24
  209. package/src/cache/vercel/vercel-cache-store.ts +68 -26
  210. package/src/client-urls/client-root.tsx +1 -0
  211. package/src/client-urls/navigation.ts +10 -0
  212. package/src/client-urls/optimistic-location.ts +10 -4
  213. package/src/client.tsx +40 -3
  214. package/src/errors.ts +13 -6
  215. package/src/handles/deferred-resolution.ts +36 -0
  216. package/src/internal-suspense-audit.ts +12 -0
  217. package/src/loader-store.ts +4 -9
  218. package/src/outlet-provider.tsx +25 -1
  219. package/src/prerender/build-shell-capture.ts +11 -9
  220. package/src/prerender/cloudflare.ts +130 -0
  221. package/src/prerender/create-prerender-trigger.ts +780 -0
  222. package/src/prerender/index.ts +39 -0
  223. package/src/prerender/memory-prerender-store.ts +115 -0
  224. package/src/prerender/on-demand.ts +339 -0
  225. package/src/prerender/producer-guard.ts +66 -0
  226. package/src/prerender/shell-manifest-key.ts +12 -17
  227. package/src/prerender/warm-request.ts +154 -0
  228. package/src/prerender/warm.ts +193 -0
  229. package/src/prerender/writable-store.ts +278 -0
  230. package/src/prerender.ts +29 -0
  231. package/src/reverse.ts +1 -1
  232. package/src/route-content-wrapper.tsx +107 -13
  233. package/src/router/error-handling.ts +12 -12
  234. package/src/router/find-match.ts +1 -0
  235. package/src/router/handler-context.ts +2 -0
  236. package/src/router/intercept-resolution.ts +15 -8
  237. package/src/router/loader-resolution.ts +2 -10
  238. package/src/router/manifest.ts +2 -0
  239. package/src/router/match-middleware/background-revalidation.ts +2 -0
  240. package/src/router/match-middleware/cache-lookup.ts +239 -54
  241. package/src/router/navigation-snapshot.ts +25 -6
  242. package/src/router/pattern-matching.ts +14 -0
  243. package/src/router/prefetch-default.ts +4 -4
  244. package/src/router/prerender-match.ts +460 -352
  245. package/src/router/request-classification.ts +15 -12
  246. package/src/router/route-trie-builder.ts +9 -0
  247. package/src/router/router-context.ts +1 -0
  248. package/src/router/router-interfaces.ts +35 -1
  249. package/src/router/router-options.ts +45 -5
  250. package/src/router/segment-resolution/fresh.ts +20 -19
  251. package/src/router/segment-resolution/loader-cache.ts +110 -77
  252. package/src/router/segment-resolution/revalidation.ts +34 -24
  253. package/src/router/segment-resolution/streamed-handler-boundary.ts +133 -0
  254. package/src/router/trie-matching.ts +3 -0
  255. package/src/router-versions.ts +60 -0
  256. package/src/router.ts +107 -1
  257. package/src/rsc/full-payload.ts +6 -2
  258. package/src/rsc/handler-context.ts +5 -0
  259. package/src/rsc/handler.ts +64 -7
  260. package/src/rsc/progressive-enhancement.ts +5 -1
  261. package/src/rsc/response-cache-serve.ts +10 -4
  262. package/src/rsc/rsc-rendering.ts +65 -12
  263. package/src/rsc/shell-build-manifest.ts +17 -12
  264. package/src/rsc/shell-capture-constants.ts +39 -7
  265. package/src/rsc/shell-capture.ts +144 -45
  266. package/src/rsc/shell-serve.ts +12 -6
  267. package/src/rsc/ssr-module-loader.ts +26 -0
  268. package/src/rsc/types.ts +12 -6
  269. package/src/segment-boundary-content.ts +25 -0
  270. package/src/segment-loader-promise.ts +28 -38
  271. package/src/segment-system.tsx +117 -57
  272. package/src/server/build-version-table.ts +130 -0
  273. package/src/server/context.ts +40 -17
  274. package/src/server/cookie-store.ts +5 -0
  275. package/src/server/handle-store.ts +357 -127
  276. package/src/server/request-context.ts +149 -12
  277. package/src/ssr/ssr-root.tsx +32 -13
  278. package/src/suspense-audit-react.tsx +98 -0
  279. package/src/suspense-audit.ts +1030 -0
  280. package/src/testing/action-form.ts +66 -0
  281. package/src/testing/build-versions.ts +64 -0
  282. package/src/testing/dispatch.ts +6 -0
  283. package/src/testing/dom.entry.ts +1 -0
  284. package/src/testing/flight-runtime.d.ts +27 -0
  285. package/src/testing/flight.entry.ts +4 -0
  286. package/src/testing/index.ts +22 -0
  287. package/src/testing/internal/context.ts +2 -1
  288. package/src/testing/internal/seed-vars.ts +14 -2
  289. package/src/testing/internal/server-modules.ts +32 -0
  290. package/src/testing/location-state-key.ts +18 -8
  291. package/src/testing/render-handler.ts +2 -1
  292. package/src/testing/render-route.tsx +293 -46
  293. package/src/testing/serve-shell-request.ts +262 -37
  294. package/src/testing/shell-status.ts +17 -6
  295. package/src/testing/vitest-stubs/plugin-rsc.ts +37 -11
  296. package/src/testing/vitest-stubs/version.ts +4 -1
  297. package/src/thenable-status.ts +10 -0
  298. package/src/types/handler-context.ts +15 -5
  299. package/src/types/route-entry.ts +6 -0
  300. package/src/urls/path-helper.ts +69 -9
  301. package/src/use-loader.tsx +57 -30
  302. package/src/vite/discovery/build-versions.ts +1281 -0
  303. package/src/vite/discovery/bundle-postprocess.ts +4 -0
  304. package/src/vite/discovery/discover-routers.ts +15 -0
  305. package/src/vite/discovery/installed-packages.ts +159 -0
  306. package/src/vite/discovery/prerender-collection.ts +38 -1
  307. package/src/vite/discovery/router-versions-phase.ts +336 -0
  308. package/src/vite/discovery/shell-prerender-phase.ts +33 -43
  309. package/src/vite/discovery/state.ts +36 -1
  310. package/src/vite/discovery/virtual-module-codegen.ts +7 -2
  311. package/src/vite/encryption-key.ts +101 -9
  312. package/src/vite/inject-client-debug.ts +42 -20
  313. package/src/vite/plugin-types.ts +28 -0
  314. package/src/vite/plugins/{version-injector.ts → entry-bootstrap-injector.ts} +7 -22
  315. package/src/vite/plugins/expose-ids/export-analysis.ts +1 -1
  316. package/src/vite/plugins/expose-ids/router-transform.ts +36 -15
  317. package/src/vite/plugins/expose-internal-ids.ts +12 -3
  318. package/src/vite/plugins/stable-rsc-output.ts +147 -0
  319. package/src/vite/plugins/version-plugin.ts +19 -24
  320. package/src/vite/plugins/version.d.ts +17 -2
  321. package/src/vite/plugins/virtual-entries.ts +39 -6
  322. package/src/vite/rango.ts +28 -3
  323. package/src/vite/router-discovery.ts +96 -13
  324. package/src/vite/utils/bundle-analysis.ts +39 -7
  325. package/src/vite/utils/client-chunks.ts +5 -1
  326. package/src/vite/utils/compare-strings.ts +9 -0
  327. package/src/vite/utils/package-resolution.ts +9 -0
  328. package/src/vite/utils/prerender-utils.ts +4 -1
  329. package/src/vite/utils/shared-utils.ts +1 -1
  330. package/dist/types/segment-content-promise.d.ts +0 -13
  331. package/src/segment-content-promise.ts +0 -67
@@ -30,5 +30,7 @@ export { renderServerTree, findClientBoundaries, findElements, textContent, asse
30
30
  export type { RenderServerTreeOptions, RenderServerTreeResult, ClientBoundary, BoundarySelector, FoundElement, ElementSelector, } from "./flight-tree.js";
31
31
  export { renderHandler } from "./render-handler.js";
32
32
  export type { TestableHandler, RenderHandlerOptions, RenderHandlerResult, StateCookieSeed, } from "./render-handler.js";
33
+ export { createActionForm } from "./action-form.js";
34
+ export type { CreateActionFormOptions } from "./action-form.js";
33
35
  export { serveShellRequest, resetShellTestState, } from "./serve-shell-request.js";
34
- export type { ServeShellRequestOptions, ServeShellRequestResult, } from "./serve-shell-request.js";
36
+ export type { ServeShellRequestOptions, ServeShellRequestResult, ShellRequestHandles, } from "./serve-shell-request.js";
@@ -43,11 +43,17 @@ export { runClientRevalidate } from "./run-client-revalidate.js";
43
43
  export type { RunClientRevalidateOptions } from "./run-client-revalidate.js";
44
44
  export { dispatch } from "./dispatch.js";
45
45
  export type { DispatchOptions } from "./dispatch.js";
46
+ export { createMemoryPrerenderStore } from "../prerender/memory-prerender-store.js";
47
+ export type { MemoryPrerenderStore, MemoryPrerenderStoreOptions, } from "../prerender/memory-prerender-store.js";
48
+ export type { WritablePrerenderStore, PrerenderStoredEntry, PrerenderKey, } from "../prerender/writable-store.js";
49
+ export type { PrerenderConfig, PrerenderResult, PrerenderWarmCaches, } from "../prerender/on-demand.js";
46
50
  export { assertCacheStatus, assertCacheDecision, parseCacheHeader, createCacheSink, filterCacheDecisions, } from "./cache-status.js";
47
51
  export type { ExpectedCacheStatus, CacheStatusTarget, CacheSink, } from "./cache-status.js";
48
52
  export type { TelemetryEvent, TelemetrySink, CacheDecisionEvent, CacheSegmentSignal, CacheSegmentStatus, } from "../router/telemetry.js";
49
53
  export { assertPprReplayStatus, assertShellStatus, parsePprReplayStatus, parseShellStatus, PPR_REPLAY_STATUS_HEADER, shellCacheKey, SHELL_STATUS_HEADER, } from "./shell-status.js";
50
54
  export type { PprReplayBypassReason, PprReplayStatus, ShellCachePartition, ShellStatus, ShellStatusTarget, } from "./shell-status.js";
55
+ export { setBuildVersions } from "./build-versions.js";
56
+ export type { BuildVersions, RouterVersions } from "./build-versions.js";
51
57
  export { collectHandle } from "./collect-handle.js";
52
58
  export { withLocationStateKey } from "./location-state-key.js";
53
59
  export { diffGeneratedRoutes, assertGeneratedRoutesMatch, } from "./generated-routes.js";
@@ -7,6 +7,7 @@
7
7
  * client/browser modules).
8
8
  */
9
9
  import { type ContextVar } from "../../context-var.js";
10
+ import { type RouterVersions } from "../../router-versions.js";
10
11
  export interface StateCookieSeed {
11
12
  /**
12
13
  * Cookie-name prefix, sanitized then composed with `routerId` exactly like
@@ -20,11 +21,15 @@ export interface StateCookieSeed {
20
21
  */
21
22
  routerId?: string;
22
23
  /**
23
- * Build version used as the rotated value's prefix (`{version}:{timestamp}`).
24
- * Defaults to `"0"` (resolved inside createRequestContext).
24
+ * The app's version, as `createRouter({ version })` would set it: the
25
+ * rotated value's prefix (`{version}:{timestamp}`) and the version a cache
26
+ * store keys with. Defaults to `"0"` for the prefix (resolved inside
27
+ * createRequestContext) and to the build versions for the store.
25
28
  */
26
29
  version?: string;
27
30
  }
28
31
  export declare function resolveSeededStateCookieName(seed?: StateCookieSeed): string;
32
+ /** The request context's `versions` for a seeded `stateCookie.version`. */
33
+ export declare function seededVersions(seed?: StateCookieSeed): RouterVersions | undefined;
29
34
  export type VarsInit = Record<string, unknown> | ReadonlyArray<readonly [ContextVar<unknown> | string, unknown]>;
30
35
  export declare function seedVariables(variables: Record<string, unknown>, vars?: VarsInit): Record<string, unknown>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Register `exports` as the server module `id`, merging into an earlier call.
3
+ * The module object is kept and mutated: the stub's require is memoized per
4
+ * id, so a later export must appear on the object it first returned.
5
+ */
6
+ export declare function registerServerModule(id: string, exports: Record<string, unknown>): void;
7
+ /** The module a decoded server reference resolves to. */
8
+ export declare function loadServerModule(id: string): Record<string, unknown>;
@@ -6,11 +6,15 @@ import { type LocationStateDefinition } from "../browser/react/location-state-sh
6
6
  * use (`MyState(value)`, `useLocationState(MyState)`, `.read()`).
7
7
  *
8
8
  * - `withLocationStateKey(GridState, "GridState")` sets `__rsc_ls_GridState`
9
- * (a name that already starts with `__rsc_ls_` is used as-is).
9
+ * (a name that already starts with `__rsc_ls_` is used as-is). A definition
10
+ * with `clearOnReload` appends its suffix, so read the stored key back from
11
+ * `GridState.__rsc_ls_key` (`__rsc_ls_GridState~r`).
10
12
  * - Without a name, a key already set (by the plugin or an earlier call) is
11
13
  * kept; otherwise the definition gets a synthetic `__rsc_ls_test_<n>` key,
12
14
  * which then stays on it.
13
15
  *
16
+ * A name may not contain "~": that separator is reserved for the suffix.
17
+ *
14
18
  * Returns the definition.
15
19
  *
16
20
  * @example
@@ -35,11 +35,19 @@
35
35
  * useRouter().replace kind "replace", refresh() kind "revalidate".
36
36
  * Back/forward, action and optimistic clientUrls() swap decisions are
37
37
  * e2e territory.
38
+ * - Location state reaches readers the way it does in production:
39
+ * NavigationProvider holds the committed entry's state next to the
40
+ * payload, so a navigation whose loader the test holds keeps the entry
41
+ * being left on screen with its own state. A `popstate` event is a
42
+ * back/forward onto the entry history.state holds; the tree has one
43
+ * location, so no page is restored with it. A server action's state, a
44
+ * redirect's and an intercept's are e2e territory.
38
45
  * What it DOES cover: client hooks that read NavigationProvider /
39
46
  * OutletContext — useParams, useReverse, useHref, useMount, useNavigation,
40
47
  * useRouter, usePathname, useSearchParams, Outlet/useOutlet nesting and seeded
41
48
  * descendant pending state, useLoader/useFetchLoader (seeded data),
42
- * useLocationState (seeded), and useHandle (seeded).
49
+ * useLocationState (seeded, or written by a navigation), and useHandle
50
+ * (seeded).
43
51
  * Basename-mounted apps: pass the `basename` option so useRouter().basename,
44
52
  * <Link> prefixing, and useMount/useHref resolve against the mount prefix
45
53
  * (without it they resolve at the root "/"). For an include("/shop", ...)
@@ -48,10 +56,10 @@
48
56
  */
49
57
  import { type ComponentType } from "react";
50
58
  import type { RenderResult } from "@testing-library/react";
51
- import type { NavigationStore } from "../browser/types.js";
59
+ import type { NavigateOptions, NavigationStore } from "../browser/types.js";
52
60
  import type { EventController } from "../browser/event-controller.js";
53
61
  import type { LoaderDefinition, TransitionConfig } from "../types.js";
54
- import type { LocationStateDefinition } from "../browser/react/location-state-shared.js";
62
+ import { type LocationStateDefinition } from "../browser/react/location-state-shared.js";
55
63
  import type { Handle } from "../handle.js";
56
64
  import type { ThemeConfig } from "../theme/types.js";
57
65
  import type { PrefetchStrategy } from "../router/prefetch-default.js";
@@ -159,6 +167,8 @@ export interface RenderRouteOptions {
159
167
  * `useLocationState(StateDef)`. Like loaders, a real `createLocationState()`
160
168
  * handle has an empty injected key in a bare test, so pass `[def, value]`
161
169
  * pairs; renderRoute assigns a synthetic key and writes it to `history.state`.
170
+ * With `hydrate: true` a `clearOnReload` definition's seed is removed before
171
+ * hydration, as on a document load.
162
172
  *
163
173
  * @example
164
174
  * renderRoute([{ path: "/", Component: FlashBanner }], {
@@ -192,6 +202,24 @@ export interface RenderRouteOptions {
192
202
  * computes the segment id for you). Merged with `handles`.
193
203
  */
194
204
  handle?: HandleDataSeed;
205
+ /**
206
+ * Handle values a document delivers after hydration, as a loader's push
207
+ * that is not in the document's handle snapshot is (a push made after the
208
+ * handler output settled, or any loader push on a PPR shell HIT). Each
209
+ * entry is `[handle, values]`: the handle's values after the update, which
210
+ * replace its `handles` seed once the root has hydrated (or mounted). With
211
+ * `hydrate: true` the server HTML is rendered from `handles`, and a reader
212
+ * inside a `<Suspense>` boundary hydrates after the update was applied, as
213
+ * a boundary that hydrates after the root does in production.
214
+ *
215
+ * @example
216
+ * const { serverHtml, recoverableErrors } = await renderRoute(routes, {
217
+ * hydrate: true,
218
+ * handles: [[Notes, ["from-handler"]]],
219
+ * lateHandles: [[Notes, ["from-handler", "from-loader"]]],
220
+ * });
221
+ */
222
+ lateHandles?: ReadonlyArray<readonly [Handle<any, any>, unknown[]]>;
195
223
  /**
196
224
  * Route name -> pattern map. Informational for parity with the server test
197
225
  * context; client useReverse takes its map directly as an argument, so this
@@ -253,6 +281,25 @@ export interface RenderRouteOptions {
253
281
  * not override a `"none"` default.
254
282
  */
255
283
  defaultPrefetch?: PrefetchStrategy;
284
+ /**
285
+ * Hydrate instead of mounting fresh: the same element is rendered to HTML
286
+ * (react-dom/server `renderToString`), placed in the container and hydrated.
287
+ * The result gains `serverHtml` and `recoverableErrors`
288
+ * (RenderRouteHydrateResult). `data-hydrated` is set on `<html>` after
289
+ * hydration, as production's root does, and removed on unmount.
290
+ *
291
+ * Limits:
292
+ * - The server pass runs without `window` and `document`, and only those. A
293
+ * hook that reads a global that stays defined there (`history`,
294
+ * `localStorage`, `navigator`) outside a server snapshot renders the same
295
+ * in both passes here and can still mismatch in real SSR.
296
+ * - Content that suspends in the server pass (`lazy`, a pending or untracked
297
+ * `use()` promise) is emitted as its fallback and client-rendered, not
298
+ * hydrated; React reports the boundary in `recoverableErrors`. Outside any
299
+ * `<Suspense>` it rejects.
300
+ * - Needs @testing-library/react >= 16.2.0; throws on older versions.
301
+ */
302
+ hydrate?: boolean;
256
303
  }
257
304
  /**
258
305
  * Imperative handle returned alongside the RTL result.
@@ -282,10 +329,17 @@ export interface TestRouterHandle {
282
329
  * `options.transition: false` is the per-navigation opt-out
283
330
  * (`router.push(url, { transition: false })`, `<Link transition={false}>`):
284
331
  * the commit is urgent and no transition({ when }) predicate is called.
332
+ *
333
+ * `options.state` and `options.replace: true` write the history entry the
334
+ * way `useRouter().push(url, { state })` and `.replace(url, { state })` do,
335
+ * so a test can carry location state on a navigation whose loader it
336
+ * holds: `state` pushes an entry with it, `replace: true` replaces the
337
+ * current entry (with `state`, or with none, which drops the entry's
338
+ * location state as a production replace does). With neither, history is
339
+ * left alone and readers keep the state they have: `navigate(url)` and
340
+ * `navigate(url, { replace: false })` are the same call.
285
341
  */
286
- navigate(url: string, options?: Pick<RenderRouteOptions, "loaders"> & {
287
- transition?: boolean;
288
- }): Promise<void>;
342
+ navigate(url: string, options?: Pick<RenderRouteOptions, "loaders"> & Pick<NavigateOptions, "state" | "replace" | "transition">): Promise<void>;
289
343
  /**
290
344
  * Re-render the current location, as router.refresh() does: a spec's
291
345
  * transition({ when }) decides it with kind "revalidate" (`to` is `from`).
@@ -304,4 +358,21 @@ export interface TestRouterHandle {
304
358
  export type RenderRouteResult = RenderResult & {
305
359
  router: TestRouterHandle;
306
360
  };
361
+ /** Result of renderRoute with `hydrate: true`. */
362
+ export type RenderRouteHydrateResult = RenderRouteResult & {
363
+ /** The HTML the server pass produced, as placed in the container. */
364
+ serverHtml: string;
365
+ /**
366
+ * Messages of the errors React recovered from (`onRecoverableError`): a
367
+ * hydration mismatch that made it re-render on the client, or a boundary the
368
+ * server pass could not finish. Empty means the tree hydrated as rendered.
369
+ * Live: React appends for as long as the root is mounted. An attribute-only
370
+ * mismatch is NOT here — React keeps the server attribute and only logs it
371
+ * with `console.error` in development.
372
+ */
373
+ recoverableErrors: string[];
374
+ };
375
+ export declare function renderRoute(routes: RenderRouteSpec[], options: RenderRouteOptions & {
376
+ hydrate: true;
377
+ }): Promise<RenderRouteHydrateResult>;
307
378
  export declare function renderRoute(routes: RenderRouteSpec[], options?: RenderRouteOptions): Promise<RenderRouteResult>;
@@ -27,12 +27,21 @@
27
27
  * capture refuses for a root postpone (a live loader read with no boundary
28
28
  * above it) or an SSR render error is captured here.
29
29
  *
30
+ * A `Prerender` route serves its handler layer from the artifact
31
+ * `router.matchForPrerender` bakes for the URL (on its first request, kept
32
+ * until resetShellTestState), through the production prerender store. Its
33
+ * first `ppr` request is a MISS with a runtime capture, as a URL without a
34
+ * build-time shell is in production; build-time shells are e2e-only. An
35
+ * on-demand route (`Prerender(..., { onDemand })`) bakes nothing here: it
36
+ * serves from its prerender store, as a refresh-only page does in production.
37
+ *
30
38
  * Must run under the `react-server` condition (the rsc Vitest project), with
31
39
  * `rangoTestAliases()` resolving `@vitejs/plugin-rsc/rsc/server` to the stub
32
40
  * that carries the Flight runtime.
33
41
  */
34
42
  import { type Rango } from "../router/router-interfaces.js";
35
43
  import type { SegmentCacheStore, ShellCacheEntry } from "../cache/types.js";
44
+ import type { HandleData } from "../server/handle-store.js";
36
45
  import { type PprReplayStatus, type ShellStatus } from "./shell-status.js";
37
46
  /** Options for {@link serveShellRequest}. */
38
47
  export interface ServeShellRequestOptions<TEnv = any> {
@@ -59,6 +68,29 @@ export interface ServeShellRequestOptions<TEnv = any> {
59
68
  from?: string;
60
69
  segments?: readonly string[];
61
70
  };
71
+ /**
72
+ * POST this form as a submit before hydration: the no-JS request the
73
+ * progressive-enhancement path runs the action for and re-renders the page
74
+ * after. Build it with `createActionForm`. The response is the document
75
+ * (`flight` is its payload, `formState` what the SSR render received).
76
+ * Not with `partial`.
77
+ */
78
+ form?: FormData;
79
+ }
80
+ /** A response's handle data, as the browser consumes it. */
81
+ export interface ShellRequestHandles {
82
+ /**
83
+ * What the document hydrates with: `metadata.handles`, read to its end
84
+ * before hydration starts. For a `partial` request, the last state the
85
+ * navigation streamed.
86
+ */
87
+ hydration: HandleData;
88
+ /**
89
+ * The states `metadata.handlesLate` delivered, in order. Each one replaces
90
+ * the client's handle data after hydration. Empty when nothing arrived
91
+ * late, and for a `partial` request.
92
+ */
93
+ late: HandleData[];
62
94
  }
63
95
  /** Result of {@link serveShellRequest}. */
64
96
  export interface ServeShellRequestResult {
@@ -96,17 +128,36 @@ export interface ServeShellRequestResult {
96
128
  * (CFCacheStore, VercelCacheStore) it warms the memo like any other read.
97
129
  */
98
130
  readEntry(): Promise<ShellCacheEntry | null>;
131
+ /**
132
+ * Decode the handle data of `flight` as the browser reads it, deferred
133
+ * values resolved. Undefined when no Flight was rendered.
134
+ */
135
+ readHandles(): Promise<ShellRequestHandles | undefined>;
136
+ /**
137
+ * The form state the SSR render received (the `formState` render option),
138
+ * or undefined when it received none.
139
+ */
140
+ formState: unknown;
141
+ /**
142
+ * The payload's `formState` as the browser reads it, the value the entry
143
+ * hands `hydrateRoot`. Undefined when the payload carries none (or no
144
+ * Flight was rendered). Rejects when the action's state is not
145
+ * Flight-serializable: the document still renders, and the entry
146
+ * hydrates without it.
147
+ */
148
+ readPayloadFormState(): Promise<unknown>;
99
149
  }
100
150
  /**
101
151
  * Reset the per-isolate PPR state requests leave behind, so the next test
102
152
  * starts as a fresh worker would: the capture's stampede guard, its backoff
103
153
  * (a refused capture backs its URL off for later tests too), the shell path's
104
154
  * once-per-key warnings, the build-shell manifest memo, the "use cache"
105
- * in-flight leaders and warnings, and CFCacheStore's isolate memos (shells,
155
+ * in-flight leaders and warnings, CFCacheStore's isolate memos (shells,
106
156
  * tag markers, tag hints) and warnings, which every CFCacheStore in the
107
- * process shares by namespace and URL. Call it in `beforeEach`, never while
108
- * a request is in flight. VercelCacheStore's memos live on the `cache`
109
- * handle it is given: a new handle starts empty.
157
+ * process shares by namespace and URL, and the Prerender artifacts baked so
158
+ * far. Call it in `beforeEach`, never while a request is in flight.
159
+ * VercelCacheStore's memos live on the `cache` handle it is given: a new
160
+ * handle starts empty.
110
161
  */
111
162
  export declare function resetShellTestState(): Promise<void>;
112
163
  /**
@@ -15,7 +15,7 @@
15
15
  * 2. **Smallest status signals:** `x-rango-shell` (`HIT` | `MISS`) on document
16
16
  * GETs, and `x-rango-ppr-replay` on partial requests to ppr routes. A replay
17
17
  * HIT is reported only when matching consumes the captured segment record.
18
- * Secondary unit signal: `store.getShell(shellCacheKey(url))` after a real
18
+ * Secondary unit signal: `store.getShell(shellCacheKey(router, url))` after a real
19
19
  * capture flush (background `putShell`). There is no Flight flag for shell HIT.
20
20
  *
21
21
  * 3. **A real MISS → capture → HIT in unit tests:** `serveShellRequest`
@@ -68,10 +68,16 @@ export interface ShellCachePartition {
68
68
  generated?: readonly string[];
69
69
  }
70
70
  /**
71
- * Shell store key for a document URL: the production `buildShellKey` (host +
72
- * pathname + sorted search + `:shell`) and `partitionShellKey`, both from the
73
- * React-free leaf `rsc/shell-capture-constants.ts`, so the testing barrel never
74
- * imports the shell-serve module (it pulls React).
71
+ * Shell store key of `router` for a document URL: the production
72
+ * `buildShellKey` (router id + host + pathname + sorted search + `:shell`)
73
+ * and `partitionShellKey`, both from the React-free leaf
74
+ * `rsc/shell-capture-constants.ts`, so the testing barrel never imports the
75
+ * shell-serve module (it pulls React).
76
+ *
77
+ * `router` is the router that serves the URL, or anything carrying its `id`
78
+ * (`{ id }` where the router cannot be imported, as in a Playwright test). A
79
+ * shell belongs to one router: two routers serving one host and path keep
80
+ * two entries.
75
81
  *
76
82
  * Accepts a `URL` or an absolute/relative request URL string (relative strings
77
83
  * resolve against `http://localhost`). Pass the router's `cache.searchParams`
@@ -86,7 +92,9 @@ export interface ShellCachePartition {
86
92
  * - store `keyGenerator` results, with or without `key()` results, as
87
93
  * `{ keys, generated }` (see {@link ShellCachePartition}).
88
94
  */
89
- export declare function shellCacheKey(url: URL | string, searchParams?: CacheSearchParams, partition?: string | readonly string[] | ShellCachePartition): string;
95
+ export declare function shellCacheKey(router: {
96
+ readonly id: string;
97
+ }, url: URL | string, searchParams?: CacheSearchParams, partition?: string | readonly string[] | ShellCachePartition): string;
90
98
  /**
91
99
  * Read `x-rango-shell` from a response. Returns `null` when the header is
92
100
  * absent (axis-1 / non-ppr / ineligible request).
@@ -16,8 +16,11 @@
16
16
  *
17
17
  * Without the condition React's server build refuses to load, so the codec
18
18
  * functions throw and a "use cache" call runs uncached. Any other load failure
19
- * (a moved vendored path, a missing peer) throws. The action entries stay
20
- * inert either way: no primitive decodes an action request.
19
+ * (a moved vendored path, a missing peer) throws. decodeAction and
20
+ * decodeFormState decode a no-JS form POST under the condition, resolving its
21
+ * action from the modules createActionForm() registered, as do
22
+ * `loadServerAction` and `decodeReply` for a plain form action. Without the
23
+ * condition they stay inert.
21
24
  */
22
25
  export declare const renderToReadableStream: (value: unknown, options?: object) => ReadableStream<Uint8Array>;
23
26
  export declare const createTemporaryReferenceSet: () => unknown;
@@ -26,7 +29,7 @@ export declare const createFromReadableStream: (stream: ReadableStream<Uint8Arra
26
29
  }) => Promise<unknown>;
27
30
  export declare const encodeReply: (value: unknown, options?: object) => Promise<string | FormData>;
28
31
  export declare const createClientTemporaryReferenceSet: () => unknown;
29
- export declare const loadServerAction: () => undefined;
30
- export declare const decodeReply: () => undefined;
31
- export declare const decodeAction: () => undefined;
32
- export declare const decodeFormState: () => undefined;
32
+ export declare const loadServerAction: (id: string) => Promise<unknown> | undefined;
33
+ export declare const decodeReply: (body: string | FormData, options?: object) => Promise<unknown> | undefined;
34
+ export declare const decodeAction: (body: FormData) => Promise<unknown> | null | undefined;
35
+ export declare const decodeFormState: (actionResult: unknown, body: FormData) => Promise<unknown> | undefined;
@@ -1 +1,2 @@
1
1
  export declare const VERSION = "";
2
+ export declare const ROUTER_VERSIONS: undefined;
@@ -7,3 +7,9 @@
7
7
  * isLoading registration (loader-store.ts), which must agree on "settled".
8
8
  */
9
9
  export declare function unwrapsSynchronously(stream: Promise<unknown>): boolean;
10
+ /**
11
+ * A resolved thenable for a use() whose result is ignored: React reads the
12
+ * "fulfilled" stamp and returns at once. `_debugInfo` keeps React DevTools from
13
+ * listing a 0 ms promise on every reader that calls it.
14
+ */
15
+ export declare const SETTLED_THENABLE: Promise<undefined>;
@@ -329,6 +329,13 @@ export type InternalHandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch exte
329
329
  _responseType?: string;
330
330
  /** Route name for cache key scoping (prevents cross-route collisions). */
331
331
  _routeName?: string;
332
+ /**
333
+ * @internal The on-demand overlay holds a "removed" marker for this request
334
+ * (tryPrerenderLookup, cache-lookup.ts); gateOnDemandProducer reads it. On
335
+ * this context, not the request's: withCacheLookup documents that the
336
+ * request ALS can be lost mid-pipeline on workerd.
337
+ */
338
+ _prerenderRemoved?: true;
332
339
  /**
333
340
  * @internal Loader-cache override table: loaderId -> memoized data promise.
334
341
  * A single stable ctx.use interceptor consults this instead of chaining one
@@ -342,11 +349,14 @@ export type InternalHandlerContext<TParams = {}, TEnv = DefaultEnv, TSearch exte
342
349
  */
343
350
  _loaderCacheOriginalUse?: (item: any) => any;
344
351
  /**
345
- * @internal A loader-cache HIT asks before replaying a loader's recorded
346
- * pushes: true when that loader has not run in this request and no other
347
- * replay delivered it; its later run then replaces the replayed values
348
- * (HandleStore.pushReplayed). One copy per loader per request. See
349
- * setupLoaderAccess.
352
+ * @internal A loader-cache or "use cache" HIT asks before replaying a
353
+ * loader's recorded pushes: true when that loader has not run in this
354
+ * request and no other replay delivered it; its later run then replaces
355
+ * the replayed values (HandleStore.pushReplayed). One copy per loader per
356
+ * request. A record's restore does not ask (restoreHandles): its copies
357
+ * are the pinned loader's own, or placeholders the claimed replay
358
+ * replaces. Absent on a stale refresh's ctx, whose pushes are diverted
359
+ * (handle-snapshot.ts appendHandles). See setupLoaderAccess.
350
360
  */
351
361
  _claimLoaderPushes?: (loaderId: string) => boolean;
352
362
  /**
@@ -72,6 +72,11 @@ export interface RouteEntry<TEnv = any> {
72
72
  * Used by the non-trie match path to set the `pt` flag.
73
73
  */
74
74
  passthroughRouteKeys?: Set<string>;
75
+ /**
76
+ * Route keys in this entry that opted into on-demand prerender.
77
+ * Used by the non-trie match path to set the `od` flag.
78
+ */
79
+ onDemandRouteKeys?: Set<string>;
75
80
  /**
76
81
  * Whether this entry is lazily evaluated.
77
82
  * When true, routes are populated on first matching request.
@@ -1,4 +1,22 @@
1
+ import type { Handler } from "../types.js";
1
2
  import type { PathFn, ResponsePathFn, JsonResponsePathFn, TextResponsePathFn } from "./path-helper-types.js";
3
+ /**
4
+ * A retained on-demand producer must never render on a live production
5
+ * request: bundle eviction is skipped for onDemand routes (the producer body
6
+ * stays available for router.prerender()), so without this gate an
7
+ * overlay+manifest miss on a plain Prerender(..., { onDemand }) route would
8
+ * execute the producer in-request — uncached per-request renders with the
9
+ * personalization guard unarmed. Keep the pre-retention miss contract instead
10
+ * (DataNotFoundError -> 404). Producer runs (build-time bake and
11
+ * router.prerender()) arrive with ctx.build true (createPrerenderContext);
12
+ * Vite dev keeps the documented live fall-through on a dev-store miss, except
13
+ * for a page the overlay marks removed (`_prerenderRemoved`): a live render
14
+ * would show in dev a page production answers with a 404.
15
+ * Pass-through when the route is not onDemand.
16
+ *
17
+ * @internal Exported for the unit test.
18
+ */
19
+ export declare function gateOnDemandProducer<TEnv>(producer: Handler<any, any, TEnv>, isOnDemand: boolean): Handler<any, any, TEnv>;
2
20
  export declare function createPathHelper<TEnv>(): PathFn<TEnv>;
3
21
  export declare function attachPathResponseTags<TEnv>(pathFn: PathFn<TEnv>): PathFn<TEnv> & {
4
22
  json: JsonResponsePathFn<TEnv>;