@rangojs/router 0.0.0-experimental.79 → 0.0.0-experimental.7c7e4327

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 (440) hide show
  1. package/AGENTS.md +8 -4
  2. package/README.md +301 -797
  3. package/dist/bin/rango.js +603 -145
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +3750 -1160
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +96 -24
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +85 -6
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +228 -33
  12. package/skills/caching/SKILL.md +336 -19
  13. package/skills/catalog.json +271 -0
  14. package/skills/comparison/SKILL.md +50 -0
  15. package/skills/comparison/agents/openai.yaml +4 -0
  16. package/skills/comparison/references/framework-comparison.md +837 -0
  17. package/skills/composability/SKILL.md +110 -4
  18. package/skills/css/SKILL.md +76 -0
  19. package/skills/debug-manifest/SKILL.md +5 -3
  20. package/skills/defer-hydration/SKILL.md +235 -0
  21. package/skills/document-cache/SKILL.md +87 -56
  22. package/skills/fonts/SKILL.md +1 -1
  23. package/skills/handler-use/SKILL.md +12 -10
  24. package/skills/hooks/SKILL.md +73 -691
  25. package/skills/hooks/data.md +273 -0
  26. package/skills/hooks/handle-and-actions.md +103 -0
  27. package/skills/hooks/navigation.md +110 -0
  28. package/skills/hooks/outlets.md +41 -0
  29. package/skills/hooks/state.md +228 -0
  30. package/skills/hooks/urls.md +135 -0
  31. package/skills/host-router/SKILL.md +129 -27
  32. package/skills/i18n/SKILL.md +276 -0
  33. package/skills/intercept/SKILL.md +75 -19
  34. package/skills/layout/SKILL.md +40 -19
  35. package/skills/links/SKILL.md +247 -17
  36. package/skills/loader/SKILL.md +248 -10
  37. package/skills/middleware/SKILL.md +25 -13
  38. package/skills/migrate-nextjs/SKILL.md +205 -20
  39. package/skills/migrate-react-router/SKILL.md +59 -670
  40. package/skills/migrate-react-router/cloudflare-workers.md +129 -0
  41. package/skills/migrate-react-router/component-migration.md +196 -0
  42. package/skills/migrate-react-router/data-and-actions.md +225 -0
  43. package/skills/migrate-react-router/route-mapping.md +271 -0
  44. package/skills/mime-routes/SKILL.md +29 -2
  45. package/skills/observability/SKILL.md +202 -0
  46. package/skills/parallel/SKILL.md +40 -10
  47. package/skills/ppr/SKILL.md +616 -0
  48. package/skills/prerender/SKILL.md +72 -60
  49. package/skills/rango/SKILL.md +318 -26
  50. package/skills/react-compiler/SKILL.md +168 -0
  51. package/skills/response-routes/SKILL.md +138 -49
  52. package/skills/route/SKILL.md +117 -9
  53. package/skills/router-setup/SKILL.md +44 -9
  54. package/skills/scripts/SKILL.md +179 -0
  55. package/skills/server-actions/SKILL.md +776 -0
  56. package/skills/shell-manifest/SKILL.md +185 -0
  57. package/skills/streams-and-websockets/SKILL.md +283 -0
  58. package/skills/tailwind/SKILL.md +28 -4
  59. package/skills/testing/SKILL.md +130 -0
  60. package/skills/testing/bindings.md +103 -0
  61. package/skills/testing/cache-prerender.md +127 -0
  62. package/skills/testing/client-components.md +124 -0
  63. package/skills/testing/e2e-parity.md +125 -0
  64. package/skills/testing/flight.md +91 -0
  65. package/skills/testing/handles.md +131 -0
  66. package/skills/testing/loader.md +128 -0
  67. package/skills/testing/middleware.md +99 -0
  68. package/skills/testing/render-handler.md +122 -0
  69. package/skills/testing/response-routes.md +95 -0
  70. package/skills/testing/reverse-and-types.md +85 -0
  71. package/skills/testing/server-actions.md +107 -0
  72. package/skills/testing/server-tree.md +128 -0
  73. package/skills/testing/setup.md +123 -0
  74. package/skills/theme/SKILL.md +1 -1
  75. package/skills/typesafety/SKILL.md +45 -626
  76. package/skills/typesafety/env-and-bindings.md +254 -0
  77. package/skills/typesafety/generated-files-and-cli.md +335 -0
  78. package/skills/typesafety/params-and-search.md +153 -0
  79. package/skills/typesafety/route-types.md +209 -0
  80. package/skills/use-cache/SKILL.md +74 -15
  81. package/skills/vercel/SKILL.md +128 -0
  82. package/skills/view-transitions/SKILL.md +337 -0
  83. package/src/__augment-tests__/augment.ts +81 -0
  84. package/src/__augment-tests__/augmented.check.ts +116 -0
  85. package/src/__internal.ts +0 -65
  86. package/src/browser/action-coordinator.ts +53 -36
  87. package/src/browser/action-fence.ts +47 -0
  88. package/src/browser/app-shell.ts +39 -0
  89. package/src/browser/connection-warmup.ts +134 -0
  90. package/src/browser/cookie-name.ts +140 -0
  91. package/src/browser/event-controller.ts +252 -158
  92. package/src/browser/history-state.ts +21 -0
  93. package/src/browser/index.ts +3 -3
  94. package/src/browser/invalidate-client-cache.ts +52 -0
  95. package/src/browser/logging.ts +28 -0
  96. package/src/browser/merge-segment-loaders.ts +6 -4
  97. package/src/browser/navigation-bridge.ts +94 -25
  98. package/src/browser/navigation-client.ts +144 -79
  99. package/src/browser/navigation-store-handle.ts +38 -0
  100. package/src/browser/navigation-store.ts +161 -73
  101. package/src/browser/navigation-transaction.ts +9 -59
  102. package/src/browser/network-error-handler.ts +34 -7
  103. package/src/browser/partial-update.ts +183 -144
  104. package/src/browser/prefetch/cache.ts +242 -77
  105. package/src/browser/prefetch/fetch.ts +325 -69
  106. package/src/browser/prefetch/queue.ts +61 -12
  107. package/src/browser/rango-state.ts +158 -76
  108. package/src/browser/react/Link.tsx +58 -20
  109. package/src/browser/react/NavigationProvider.tsx +202 -120
  110. package/src/browser/react/ScrollRestoration.tsx +10 -6
  111. package/src/browser/react/filter-segment-order.ts +66 -7
  112. package/src/browser/react/index.ts +0 -48
  113. package/src/browser/react/location-state-shared.ts +178 -8
  114. package/src/browser/react/location-state.ts +39 -14
  115. package/src/browser/react/use-action.ts +6 -15
  116. package/src/browser/react/use-handle.ts +17 -14
  117. package/src/browser/react/use-href.tsx +8 -1
  118. package/src/browser/react/use-link-status.ts +33 -8
  119. package/src/browser/react/use-navigation.ts +32 -7
  120. package/src/browser/react/use-params.ts +20 -10
  121. package/src/browser/react/use-reverse.ts +106 -0
  122. package/src/browser/react/use-router.ts +25 -3
  123. package/src/browser/react/use-search-params.ts +0 -5
  124. package/src/browser/react/use-segments.ts +11 -21
  125. package/src/browser/response-adapter.ts +99 -8
  126. package/src/browser/rsc-router.tsx +145 -28
  127. package/src/browser/scroll-restoration.ts +37 -22
  128. package/src/browser/segment-reconciler.ts +31 -21
  129. package/src/browser/segment-structure-assert.ts +2 -2
  130. package/src/browser/server-action-bridge.ts +236 -65
  131. package/src/browser/types.ts +102 -9
  132. package/src/browser/validate-redirect-origin.ts +43 -16
  133. package/src/build/collect-fallback-refs.ts +107 -0
  134. package/src/build/generate-manifest.ts +203 -154
  135. package/src/build/generate-route-types.ts +3 -1
  136. package/src/build/index.ts +11 -3
  137. package/src/build/prefix-tree-utils.ts +123 -0
  138. package/src/build/route-trie.ts +152 -21
  139. package/src/build/route-types/ast-route-extraction.ts +15 -8
  140. package/src/build/route-types/codegen.ts +16 -5
  141. package/src/build/route-types/include-resolution.ts +456 -62
  142. package/src/build/route-types/param-extraction.ts +6 -3
  143. package/src/build/route-types/per-module-writer.ts +22 -6
  144. package/src/build/route-types/router-processing.ts +128 -51
  145. package/src/build/route-types/scan-filter.ts +1 -1
  146. package/src/build/route-types/source-scan.ts +216 -0
  147. package/src/build/runtime-discovery.ts +13 -21
  148. package/src/cache/cache-error.ts +104 -0
  149. package/src/cache/cache-key-utils.ts +58 -13
  150. package/src/cache/cache-policy.ts +108 -34
  151. package/src/cache/cache-runtime.ts +421 -58
  152. package/src/cache/cache-scope.ts +187 -96
  153. package/src/cache/cache-tag.ts +149 -0
  154. package/src/cache/cf/cf-base64.ts +33 -0
  155. package/src/cache/cf/cf-cache-constants.ts +127 -0
  156. package/src/cache/cf/cf-cache-store.ts +2202 -372
  157. package/src/cache/cf/cf-cache-types.ts +349 -0
  158. package/src/cache/cf/cf-kv-utils.ts +46 -0
  159. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  160. package/src/cache/cf/index.ts +6 -16
  161. package/src/cache/document-cache.ts +126 -41
  162. package/src/cache/handle-snapshot.ts +70 -0
  163. package/src/cache/index.ts +23 -20
  164. package/src/cache/memory-segment-store.ts +243 -37
  165. package/src/cache/profile-registry.ts +46 -31
  166. package/src/cache/read-through-swr.ts +56 -12
  167. package/src/cache/segment-codec.ts +13 -21
  168. package/src/cache/shell-snapshot.ts +417 -0
  169. package/src/cache/tag-invalidation.ts +230 -0
  170. package/src/cache/types.ts +180 -99
  171. package/src/cache/vercel/index.ts +11 -0
  172. package/src/cache/vercel/vercel-cache-store.ts +1127 -0
  173. package/src/client.rsc.tsx +41 -21
  174. package/src/client.tsx +33 -61
  175. package/src/cloudflare/index.ts +11 -0
  176. package/src/cloudflare/tracing.ts +108 -0
  177. package/src/component-utils.ts +19 -0
  178. package/src/components/DefaultDocument.tsx +8 -2
  179. package/src/context-var.ts +18 -6
  180. package/src/decode-loader-results.ts +52 -0
  181. package/src/defer.ts +185 -0
  182. package/src/deps/ssr.ts +0 -1
  183. package/src/encode-kv.ts +49 -0
  184. package/src/errors.ts +30 -4
  185. package/src/escape-script.ts +52 -0
  186. package/src/handle.ts +67 -37
  187. package/src/handles/MetaTags.tsx +24 -53
  188. package/src/handles/Scripts.tsx +183 -0
  189. package/src/handles/breadcrumbs.ts +35 -8
  190. package/src/handles/deferred-resolution.ts +127 -0
  191. package/src/handles/is-thenable.ts +18 -0
  192. package/src/handles/meta.ts +14 -40
  193. package/src/handles/script.ts +244 -0
  194. package/src/host/cookie-handler.ts +9 -60
  195. package/src/host/errors.ts +13 -22
  196. package/src/host/index.ts +9 -2
  197. package/src/host/pattern-matcher.ts +23 -52
  198. package/src/host/router.ts +107 -99
  199. package/src/host/testing.ts +40 -27
  200. package/src/host/types.ts +37 -4
  201. package/src/host/utils.ts +1 -1
  202. package/src/href-client.ts +137 -22
  203. package/src/index.rsc.ts +97 -12
  204. package/src/index.ts +98 -14
  205. package/src/internal-debug.ts +11 -10
  206. package/src/loader-store.ts +500 -0
  207. package/src/loader.rsc.ts +20 -13
  208. package/src/loader.ts +12 -11
  209. package/src/missing-id-error.ts +68 -0
  210. package/src/outlet-context.ts +1 -1
  211. package/src/outlet-provider.tsx +1 -5
  212. package/src/prerender/param-hash.ts +16 -16
  213. package/src/prerender/store.ts +32 -37
  214. package/src/prerender.ts +78 -10
  215. package/src/redirect-origin.ts +114 -0
  216. package/src/regex-escape.ts +8 -0
  217. package/src/render-error-thrower.tsx +20 -0
  218. package/src/response-utils.ts +62 -0
  219. package/src/reverse.ts +65 -39
  220. package/src/root-error-boundary.tsx +1 -19
  221. package/src/route-content-wrapper.tsx +19 -77
  222. package/src/route-definition/dsl-helpers.ts +304 -309
  223. package/src/route-definition/helper-factories.ts +28 -140
  224. package/src/route-definition/helpers-types.ts +87 -59
  225. package/src/route-definition/index.ts +1 -2
  226. package/src/route-definition/redirect.ts +44 -11
  227. package/src/route-definition/resolve-handler-use.ts +12 -1
  228. package/src/route-definition/use-item-types.ts +29 -0
  229. package/src/route-map-builder.ts +41 -20
  230. package/src/route-types.ts +19 -46
  231. package/src/router/basename.ts +14 -0
  232. package/src/router/content-negotiation.ts +73 -25
  233. package/src/router/error-handling.ts +45 -18
  234. package/src/router/find-match.ts +129 -30
  235. package/src/router/handler-context.ts +27 -42
  236. package/src/router/instrument.ts +355 -0
  237. package/src/router/intercept-resolution.ts +39 -20
  238. package/src/router/lazy-includes.ts +82 -59
  239. package/src/router/loader-resolution.ts +167 -72
  240. package/src/router/logging.ts +0 -6
  241. package/src/router/manifest.ts +74 -40
  242. package/src/router/match-api.ts +80 -55
  243. package/src/router/match-context.ts +0 -22
  244. package/src/router/match-handlers.ts +211 -165
  245. package/src/router/match-middleware/background-revalidation.ts +40 -24
  246. package/src/router/match-middleware/cache-lookup.ts +159 -285
  247. package/src/router/match-middleware/cache-store.ts +64 -52
  248. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  249. package/src/router/match-middleware/segment-resolution.ts +0 -22
  250. package/src/router/match-pipelines.ts +1 -42
  251. package/src/router/match-result.ts +69 -79
  252. package/src/router/metrics.ts +0 -34
  253. package/src/router/middleware-types.ts +7 -134
  254. package/src/router/middleware.ts +298 -172
  255. package/src/router/navigation-snapshot.ts +7 -56
  256. package/src/router/params-util.ts +23 -0
  257. package/src/router/parse-pattern.ts +115 -0
  258. package/src/router/pattern-matching.ts +181 -150
  259. package/src/router/prefetch-cache-ttl.ts +51 -0
  260. package/src/router/prefetch-limits.ts +37 -0
  261. package/src/router/prerender-match.ts +112 -67
  262. package/src/router/preview-match.ts +6 -2
  263. package/src/router/request-classification.ts +50 -69
  264. package/src/router/revalidation.ts +123 -73
  265. package/src/router/route-snapshot.ts +14 -3
  266. package/src/router/router-context.ts +6 -29
  267. package/src/router/router-interfaces.ts +115 -36
  268. package/src/router/router-options.ts +166 -5
  269. package/src/router/router-registry.ts +2 -5
  270. package/src/router/segment-resolution/fresh.ts +131 -86
  271. package/src/router/segment-resolution/helpers.ts +86 -6
  272. package/src/router/segment-resolution/loader-cache.ts +139 -39
  273. package/src/router/segment-resolution/loader-mask.ts +67 -0
  274. package/src/router/segment-resolution/loader-snapshot.ts +251 -0
  275. package/src/router/segment-resolution/revalidation.ts +272 -320
  276. package/src/router/segment-resolution/static-store.ts +19 -5
  277. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  278. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  279. package/src/router/segment-resolution.ts +5 -1
  280. package/src/router/segment-wrappers.ts +6 -5
  281. package/src/router/state-cookie-name.ts +33 -0
  282. package/src/router/substitute-pattern-params.ts +75 -0
  283. package/src/router/telemetry-otel.ts +160 -200
  284. package/src/router/telemetry.ts +105 -20
  285. package/src/router/timeout.ts +0 -20
  286. package/src/router/tracing.ts +215 -0
  287. package/src/router/trie-matching.ts +171 -59
  288. package/src/router/types.ts +9 -63
  289. package/src/router/url-params.ts +57 -0
  290. package/src/router.ts +157 -71
  291. package/src/rsc/full-payload.ts +70 -0
  292. package/src/rsc/handler-context.ts +3 -2
  293. package/src/rsc/handler.ts +291 -217
  294. package/src/rsc/helpers.ts +168 -46
  295. package/src/rsc/index.ts +2 -5
  296. package/src/rsc/json-route-result.ts +38 -0
  297. package/src/rsc/loader-fetch.ts +114 -38
  298. package/src/rsc/manifest-init.ts +29 -42
  299. package/src/rsc/nonce.ts +10 -1
  300. package/src/rsc/origin-guard.ts +39 -25
  301. package/src/rsc/progressive-enhancement.ts +124 -13
  302. package/src/rsc/redirect-guard.ts +100 -0
  303. package/src/rsc/response-cache-serve.ts +238 -0
  304. package/src/rsc/response-error.ts +79 -12
  305. package/src/rsc/response-route-handler.ts +99 -189
  306. package/src/rsc/rsc-rendering.ts +421 -76
  307. package/src/rsc/runtime-warnings.ts +23 -10
  308. package/src/rsc/server-action.ts +282 -116
  309. package/src/rsc/shell-capture.ts +1158 -0
  310. package/src/rsc/shell-serve.ts +150 -0
  311. package/src/rsc/ssr-setup.ts +16 -0
  312. package/src/rsc/transition-gate.ts +89 -0
  313. package/src/rsc/types.ts +53 -5
  314. package/src/runtime-env.ts +18 -0
  315. package/src/search-params.ts +35 -30
  316. package/src/segment-loader-promise.ts +49 -4
  317. package/src/segment-system.tsx +350 -149
  318. package/src/serialize.ts +243 -0
  319. package/src/server/context.ts +208 -51
  320. package/src/server/cookie-parse.ts +32 -0
  321. package/src/server/cookie-store.ts +152 -5
  322. package/src/server/handle-store.ts +21 -38
  323. package/src/server/loader-registry.ts +33 -42
  324. package/src/server/request-context.ts +395 -176
  325. package/src/ssr/index.tsx +458 -178
  326. package/src/ssr/ssr-root.tsx +228 -0
  327. package/src/static-handler.ts +10 -13
  328. package/src/testing/cache-status.ts +162 -0
  329. package/src/testing/collect-handle.ts +46 -0
  330. package/src/testing/dispatch.ts +813 -0
  331. package/src/testing/dom.entry.ts +22 -0
  332. package/src/testing/e2e/fixture.ts +188 -0
  333. package/src/testing/e2e/index.ts +128 -0
  334. package/src/testing/e2e/matchers.ts +35 -0
  335. package/src/testing/e2e/page-helpers.ts +272 -0
  336. package/src/testing/e2e/parity.ts +387 -0
  337. package/src/testing/e2e/server.ts +195 -0
  338. package/src/testing/flight-matchers.ts +97 -0
  339. package/src/testing/flight-normalize.ts +11 -0
  340. package/src/testing/flight-runtime.d.ts +57 -0
  341. package/src/testing/flight-tree.ts +682 -0
  342. package/src/testing/flight.entry.ts +52 -0
  343. package/src/testing/flight.ts +257 -0
  344. package/src/testing/generated-routes.ts +199 -0
  345. package/src/testing/index.ts +105 -0
  346. package/src/testing/internal/context.ts +371 -0
  347. package/src/testing/internal/flight-client-globals.ts +30 -0
  348. package/src/testing/internal/seed-vars.ts +54 -0
  349. package/src/testing/render-handler.ts +357 -0
  350. package/src/testing/render-route.tsx +584 -0
  351. package/src/testing/run-loader.ts +385 -0
  352. package/src/testing/run-middleware.ts +205 -0
  353. package/src/testing/run-transition-when.ts +164 -0
  354. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  355. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  356. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  357. package/src/testing/vitest-stubs/version.ts +5 -0
  358. package/src/testing/vitest.ts +305 -0
  359. package/src/theme/ThemeProvider.tsx +56 -84
  360. package/src/theme/ThemeScript.tsx +7 -9
  361. package/src/theme/constants.ts +52 -13
  362. package/src/theme/index.ts +0 -7
  363. package/src/theme/theme-context.ts +1 -5
  364. package/src/theme/theme-script.ts +22 -21
  365. package/src/theme/use-theme.ts +0 -3
  366. package/src/types/boundaries.ts +0 -35
  367. package/src/types/cache-types.ts +13 -4
  368. package/src/types/error-types.ts +30 -90
  369. package/src/types/global-namespace.ts +54 -41
  370. package/src/types/handler-context.ts +110 -62
  371. package/src/types/index.ts +3 -10
  372. package/src/types/loader-types.ts +11 -9
  373. package/src/types/request-scope.ts +112 -0
  374. package/src/types/route-config.ts +20 -52
  375. package/src/types/route-entry.ts +0 -6
  376. package/src/types/segments.ts +135 -14
  377. package/src/urls/include-helper.ts +19 -64
  378. package/src/urls/include-provider.ts +71 -0
  379. package/src/urls/index.ts +2 -11
  380. package/src/urls/path-helper-types.ts +63 -17
  381. package/src/urls/path-helper.ts +22 -106
  382. package/src/urls/pattern-types.ts +72 -19
  383. package/src/urls/response-types.ts +22 -29
  384. package/src/urls/type-extraction.ts +98 -154
  385. package/src/urls/urls-function.ts +1 -19
  386. package/src/use-loader.tsx +292 -107
  387. package/src/vercel/index.ts +11 -0
  388. package/src/vercel/tracing.ts +88 -0
  389. package/src/vite/debug.ts +185 -0
  390. package/src/vite/discovery/bundle-postprocess.ts +8 -7
  391. package/src/vite/discovery/dev-prerender-cache.ts +117 -0
  392. package/src/vite/discovery/discover-routers.ts +127 -86
  393. package/src/vite/discovery/discovery-errors.ts +255 -0
  394. package/src/vite/discovery/gate-state.ts +171 -0
  395. package/src/vite/discovery/prerender-collection.ts +96 -68
  396. package/src/vite/discovery/route-types-writer.ts +40 -84
  397. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  398. package/src/vite/discovery/state.ts +45 -1
  399. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  400. package/src/vite/index.ts +4 -0
  401. package/src/vite/inject-client-debug.ts +88 -0
  402. package/src/vite/plugin-types.ts +210 -10
  403. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  404. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  405. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  406. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  407. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  408. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  409. package/src/vite/plugins/expose-action-id.ts +48 -95
  410. package/src/vite/plugins/expose-id-utils.ts +88 -55
  411. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  412. package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
  413. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  414. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  415. package/src/vite/plugins/expose-internal-ids.ts +505 -486
  416. package/src/vite/plugins/performance-tracks.ts +26 -25
  417. package/src/vite/plugins/refresh-cmd.ts +1 -1
  418. package/src/vite/plugins/use-cache-transform.ts +73 -83
  419. package/src/vite/plugins/vercel-output.ts +384 -0
  420. package/src/vite/plugins/version-injector.ts +40 -29
  421. package/src/vite/plugins/version-plugin.ts +37 -40
  422. package/src/vite/plugins/virtual-entries.ts +138 -27
  423. package/src/vite/rango.ts +236 -138
  424. package/src/vite/router-discovery.ts +927 -136
  425. package/src/vite/utils/ast-handler-extract.ts +26 -35
  426. package/src/vite/utils/banner.ts +1 -1
  427. package/src/vite/utils/bundle-analysis.ts +10 -15
  428. package/src/vite/utils/client-chunks.ts +184 -0
  429. package/src/vite/utils/directive-prologue.ts +40 -0
  430. package/src/vite/utils/forward-user-plugins.ts +171 -0
  431. package/src/vite/utils/manifest-utils.ts +4 -59
  432. package/src/vite/utils/package-resolution.ts +20 -52
  433. package/src/vite/utils/prerender-utils.ts +71 -43
  434. package/src/vite/utils/shared-utils.ts +142 -43
  435. package/src/browser/action-response-classifier.ts +0 -99
  436. package/src/browser/react/use-client-cache.ts +0 -58
  437. package/src/browser/shallow.ts +0 -40
  438. package/src/handles/index.ts +0 -7
  439. package/src/network-error-thrower.tsx +0 -23
  440. package/src/router/middleware-cookies.ts +0 -55
@@ -28,7 +28,6 @@ import type {
28
28
  ParallelUseItem,
29
29
  InterceptUseItem,
30
30
  LoaderUseItem,
31
- WhenItem,
32
31
  TypedCacheItem,
33
32
  TransitionItem,
34
33
  TypedTransitionItem,
@@ -42,7 +41,6 @@ import type {
42
41
  PassthroughHandlerDefinition,
43
42
  } from "../prerender.js";
44
43
  import type { StaticHandlerDefinition } from "../static-handler.js";
45
- import type { InterceptWhenFn } from "../server/context";
46
44
  import type {
47
45
  ResponseHandler,
48
46
  ResponseHandlerContext,
@@ -114,6 +112,12 @@ export type ResponsePathFn<TEnv> = <
114
112
  * Path function for JSON response routes (path.json()).
115
113
  * Handler can return plain JSON-serializable values or Response.
116
114
  * TData is inferred from the handler's return type (excluding Response/Promise wrappers).
115
+ *
116
+ * Note: a nested Promise in the return (a forgotten await) is caught at runtime
117
+ * by response-route-handler.ts (it throws instead of silently emitting `{}`). A
118
+ * compile-time JsonValue constraint was evaluated and rejected — it breaks
119
+ * interface-typed returns (interfaces lack the index signature JsonValue
120
+ * requires) and preserves literal types in the inferred response shape.
117
121
  */
118
122
  export type JsonResponsePathFn<TEnv> = <
119
123
  const TPattern extends string,
@@ -148,6 +152,30 @@ export type TextResponsePathFn<TEnv> = <
148
152
  use?: () => UseItems<ResponseRouteUseItem>,
149
153
  ) => TypedRouteItem<TName, TPattern, string, TSearch>;
150
154
 
155
+ /**
156
+ * What an async include() provider resolves to. Route types (`TRoutes`) are
157
+ * inferred from the resolved `urls()` value so `href()` and named routes stay
158
+ * type-safe through a code-split module (`() => import("./routes")`).
159
+ */
160
+ type IncludeResolved<
161
+ TEnv,
162
+ TRoutes extends Record<string, any>,
163
+ TResponses extends Record<string, unknown>,
164
+ > =
165
+ | UrlPatterns<TEnv, TRoutes, TResponses>
166
+ | { default: UrlPatterns<TEnv, TRoutes, TResponses> };
167
+
168
+ /** include() argument: an eager `urls()` value or an async provider thunk. */
169
+ export type IncludeArg<
170
+ TEnv,
171
+ TRoutes extends Record<string, any>,
172
+ TResponses extends Record<string, unknown>,
173
+ > =
174
+ | UrlPatterns<TEnv, TRoutes, TResponses>
175
+ | (() =>
176
+ | IncludeResolved<TEnv, TRoutes, TResponses>
177
+ | Promise<IncludeResolved<TEnv, TRoutes, TResponses>>);
178
+
151
179
  /**
152
180
  * Base include function signature.
153
181
  */
@@ -158,7 +186,7 @@ export type IncludeFn<TEnv> = <
158
186
  TResponses extends Record<string, unknown> = Record<string, unknown>,
159
187
  >(
160
188
  prefix: TUrlPrefix,
161
- patterns: UrlPatterns<TEnv, TRoutes, TResponses>,
189
+ patterns: IncludeArg<TEnv, TRoutes, TResponses>,
162
190
  options?: IncludeOptions<TNamePrefix>,
163
191
  ) => TypedIncludeItem<TRoutes, TNamePrefix, TUrlPrefix, TResponses>;
164
192
 
@@ -240,9 +268,16 @@ export type PathHelpers<TEnv> = {
240
268
  * `{ handler, use? }` whose `use` is scoped to that slot only. Per-slot
241
269
  * merge order is `handler.use` → shared `use` → slot-local `use`, with
242
270
  * narrowest scope winning for last-write-wins items like `loading()`.
271
+ *
272
+ * Not generic over the slots record: an inferred type parameter makes the
273
+ * object literal an inference site, which suppresses contextual typing of
274
+ * arrow slot handlers (`(ctx) => ...` was implicit any). Bare handlers infer
275
+ * now; a descriptor's `handler:` arrow still needs an explicit ctx annotation
276
+ * because StaticHandlerDefinition's own `.handler` joins the contextual union
277
+ * (two callables — see parallel-slot-handler-types.test.ts).
243
278
  */
244
- parallel: <
245
- TSlots extends Record<
279
+ parallel: (
280
+ slots: Record<
246
281
  `@${string}`,
247
282
  | Handler<any, any, TEnv>
248
283
  | ReactNode
@@ -255,8 +290,6 @@ export type PathHelpers<TEnv> = {
255
290
  use?: () => ParallelUseItem[];
256
291
  }
257
292
  >,
258
- >(
259
- slots: TSlots,
260
293
  use?: () => ParallelUseItem[],
261
294
  ) => ParallelItem;
262
295
 
@@ -264,17 +297,23 @@ export type PathHelpers<TEnv> = {
264
297
  * Define an intercepting route for soft navigation
265
298
  * Note: routeName must match a named path() in this urlpatterns
266
299
  */
267
- intercept: keyof RSCRouter.GeneratedRouteMap extends never
300
+ intercept: keyof Rango.GeneratedRouteMap extends never
268
301
  ? (
269
302
  slotName: `@${string}`,
270
303
  routeName: string,
271
304
  handler: ReactNode | Handler<any, any, TEnv>,
305
+ config?:
306
+ | import("../server/context.js").InterceptConfig<TEnv>
307
+ | (() => InterceptUseItem[]),
272
308
  use?: () => InterceptUseItem[],
273
309
  ) => InterceptItem
274
310
  : (
275
311
  slotName: `@${string}`,
276
- routeName: (keyof RSCRouter.GeneratedRouteMap & string) | `.${string}`,
312
+ routeName: (keyof Rango.GeneratedRouteMap & string) | `.${string}`,
277
313
  handler: ReactNode | Handler<any, any, TEnv>,
314
+ config?:
315
+ | import("../server/context.js").InterceptConfig<TEnv>
316
+ | (() => InterceptUseItem[]),
278
317
  use?: () => InterceptUseItem[],
279
318
  ) => InterceptItem;
280
319
 
@@ -329,11 +368,6 @@ export type PathHelpers<TEnv> = {
329
368
  fallback: ReactNode | NotFoundBoundaryHandler,
330
369
  ) => NotFoundBoundaryItem;
331
370
 
332
- /**
333
- * Define a condition for when an intercept should activate
334
- */
335
- when: (fn: InterceptWhenFn) => WhenItem;
336
-
337
371
  /**
338
372
  * Define cache configuration for segments
339
373
  */
@@ -342,15 +376,27 @@ export type PathHelpers<TEnv> = {
342
376
  <const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(
343
377
  children: () => TChildren,
344
378
  ): TypedCacheItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
345
- (options: PartialCacheOptions | false): TypedCacheItem<{}, {}>;
379
+ (options: PartialCacheOptions<TEnv> | false): TypedCacheItem<{}, {}>;
346
380
  <const TChildren extends readonly (AllUseItems | readonly AllUseItems[])[]>(
347
- options: PartialCacheOptions | false,
381
+ options: PartialCacheOptions<TEnv> | false,
348
382
  use: () => TChildren,
349
383
  ): TypedCacheItem<ExtractRoutes<TChildren>, ExtractResponses<TChildren>>;
350
384
  };
351
385
 
352
386
  /**
353
- * Attach a ViewTransition boundary to the current segment or a group of routes
387
+ * Opt a route (or group of routes) into transition-driven navigation.
388
+ *
389
+ * Two independent layers: (1) startTransition, on all React versions, holds
390
+ * the previous content across a same-route nav (no skeleton flash) and is the
391
+ * precondition for any view transition; (2) on experimental React, an
392
+ * additional `<ViewTransition>` boundary cross-fades/morphs the swap. Pass
393
+ * `{ viewTransition: false }` to keep #1 without the router boundary. A view
394
+ * transition cannot fire without a startTransition. See
395
+ * skills/view-transitions for the startTransition x ViewTransition matrix.
396
+ *
397
+ * Pass `when: (ctx) => boolean` to gate the transition per request: it runs
398
+ * server-side after the route handler (can read `ctx.get(...)`), and returning
399
+ * false drops the transition so the navigation streams its loading() skeleton.
354
400
  */
355
401
  transition: {
356
402
  (): TransitionItem;
@@ -1,16 +1,11 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { Handler } from "../types.js";
3
- import type {
4
- AllUseItems,
5
- RouteItem,
6
- RouteUseItem,
7
- UseItems,
8
- } from "../route-types.js";
3
+ import type { RouteItem, RouteUseItem, UseItems } from "../route-types.js";
9
4
  import {
10
- getContext,
11
5
  getUrlPrefix,
12
6
  getNamePrefix,
13
7
  getRootScoped,
8
+ requireDslContext,
14
9
  } from "../server/context";
15
10
  import { invariant, DataNotFoundError } from "../errors";
16
11
  import { validateUserRouteName } from "../route-name.js";
@@ -39,40 +34,11 @@ import {
39
34
  resolveHandlerUse,
40
35
  mergeHandlerUse,
41
36
  } from "../route-definition/resolve-handler-use.js";
37
+ import {
38
+ emptySegmentBase,
39
+ runAndValidateUseItems,
40
+ } from "../route-definition/dsl-helpers.js";
42
41
 
43
- /**
44
- * Check if a value is a valid use item
45
- */
46
- const isValidUseItem = (item: any): item is AllUseItems | undefined | null => {
47
- return (
48
- typeof item === "undefined" ||
49
- item === null ||
50
- (item &&
51
- typeof item === "object" &&
52
- "type" in item &&
53
- [
54
- "layout",
55
- "route",
56
- "middleware",
57
- "revalidate",
58
- "parallel",
59
- "intercept",
60
- "loader",
61
- "loading",
62
- "errorBoundary",
63
- "notFoundBoundary",
64
- "when",
65
- "cache",
66
- "transition",
67
- "include",
68
- ].includes(item.type))
69
- );
70
- };
71
-
72
- /**
73
- * Apply URL prefix to a pattern
74
- * Handles edge cases like "/" patterns and double slashes
75
- */
76
42
  function applyUrlPrefix(prefix: string, pattern: string): string {
77
43
  if (!prefix) return pattern;
78
44
  if (pattern === "/") return prefix;
@@ -82,29 +48,17 @@ function applyUrlPrefix(prefix: string, pattern: string): string {
82
48
  return prefix + pattern;
83
49
  }
84
50
 
85
- /**
86
- * Apply name prefix to a route name
87
- */
88
51
  function applyNamePrefix(prefix: string | undefined, name: string): string {
89
52
  if (!prefix) return name;
90
53
  return `${prefix}.${name}`;
91
54
  }
92
55
 
93
- /**
94
- * Resolve response type from path options (set by path.json(), path.text(), etc.)
95
- */
96
56
  function resolveResponseType(
97
57
  options: PathOptions | undefined,
98
58
  ): string | undefined {
99
59
  return options?.[RESPONSE_TYPE];
100
60
  }
101
61
 
102
- /**
103
- * Create path() helper
104
- *
105
- * The path() function is the key new feature - it combines URL pattern
106
- * with handler at the definition site.
107
- */
108
62
  export function createPathHelper<TEnv>(): PathFn<TEnv> {
109
63
  return ((
110
64
  pattern: string,
@@ -112,17 +66,15 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
112
66
  optionsOrUse?: PathOptions | (() => UseItems<RouteUseItem>),
113
67
  maybeUse?: () => UseItems<RouteUseItem>,
114
68
  ): RouteItem => {
115
- const store = getContext();
116
- const ctx = store.getStore();
117
- if (!ctx) throw new Error("path() must be called inside urls()");
69
+ const { store, ctx } = requireDslContext(
70
+ "path() must be called inside urls()",
71
+ );
118
72
 
119
73
  invariant(
120
74
  !ctx.parent || ctx.parent.type !== "parallel",
121
75
  "path() cannot be used inside parallel()",
122
76
  );
123
77
 
124
- // Walk the parent chain to prevent path() nested under another path(),
125
- // even when separated by intermediate layouts (e.g. path(layout(path())))
126
78
  {
127
79
  let ancestor = ctx.parent;
128
80
  while (ancestor) {
@@ -134,7 +86,6 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
134
86
  }
135
87
  }
136
88
 
137
- // Determine options and use based on argument types
138
89
  let options: PathOptions | undefined;
139
90
  let use: (() => UseItems<RouteUseItem>) | undefined;
140
91
 
@@ -147,49 +98,29 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
147
98
  use = maybeUse;
148
99
  }
149
100
 
150
- // Merge handler.use() defaults with explicit use()
151
- // Response routes (path.json, path.text, etc.) only allow middleware + cache
152
101
  const handlerUseFn = resolveHandlerUse(handler);
153
102
  const mountSite = resolveResponseType(options) ? "response" : "path";
154
103
  const mergedUse = mergeHandlerUse(handlerUseFn, use, mountSite);
155
104
 
156
- // Get prefixes from context (set by include())
157
105
  const urlPrefix = getUrlPrefix();
158
106
  const namePrefix = getNamePrefix();
159
107
 
160
- // Apply URL prefix to pattern
161
108
  const prefixedPattern = applyUrlPrefix(urlPrefix, pattern);
162
109
 
163
- // Generate route name - use provided name or generate from pattern
164
110
  const localName =
165
111
  options?.name || `$path_${pattern.replace(/[/:*?]/g, "_")}`;
166
112
  if (options?.name) {
167
113
  validateUserRouteName(options.name);
168
114
  }
169
- // Apply name prefix if set (from include())
170
115
  const routeName = applyNamePrefix(namePrefix, localName);
171
116
 
172
117
  const namespace = `${ctx.namespace}.${store.getNextIndex("route")}.${routeName}`;
173
118
 
174
- // Per-request pruning: skip registration for routes that won't be rendered.
175
- // forRoute is set by loadManifest() to the matched route name. During
176
- // evaluateLazyEntry() (route matching), forRoute is unset so all routes
177
- // register normally. We still increment counters to keep shortCodes stable
178
- // across different routes (needed for segment reconciliation on navigation).
179
- //
180
- // include() does not need its own forRoute pruning. include() creates lazy
181
- // entries that defer handler execution until route matching. When the lazy
182
- // handler eventually runs inside loadManifest(), this path() check already
183
- // covers all routes defined inside the include.
184
119
  if (ctx.forRoute && routeName !== ctx.forRoute) {
185
120
  store.getShortCode("route");
186
121
  return { type: "route" } as RouteItem;
187
122
  }
188
123
 
189
- // Ensure handler is always a function (wrap ReactNode or extract from prerender/static def)
190
- // For prerender stubs (production builds where handler code is evicted),
191
- // handler.handler is undefined — provide a notFound fallback so requests
192
- // for non-prerendered params get 404 instead of "handler is not a function".
193
124
  const wrappedHandler: Handler<any, any, TEnv> =
194
125
  typeof handler === "function"
195
126
  ? (handler as Handler<any, any, TEnv>)
@@ -214,22 +145,13 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
214
145
  : () => handler;
215
146
 
216
147
  const entry = {
148
+ ...emptySegmentBase(),
217
149
  id: namespace,
218
150
  shortCode: store.getShortCode("route"),
219
151
  type: "route" as const,
220
152
  parent: ctx.parent,
221
153
  handler: wrappedHandler,
222
- // Store the PREFIXED pattern for route matching
223
154
  pattern: prefixedPattern,
224
- loading: undefined,
225
- middleware: [],
226
- revalidate: [],
227
- errorBoundary: [],
228
- notFoundBoundary: [],
229
- layout: [],
230
- parallel: {},
231
- intercept: [],
232
- loader: [],
233
155
  ...(urlPrefix ? { mountPath: urlPrefix } : {}),
234
156
  ...(isPassthroughHandler(handler)
235
157
  ? {
@@ -253,31 +175,30 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
253
175
  ...(resolveResponseType(options)
254
176
  ? { responseType: resolveResponseType(options) }
255
177
  : {}),
178
+ // PPR shell-caching opt-in (document-level). Stored raw; the integrated
179
+ // serve path normalizes it via resolvePprConfig (rsc/shell-serve.ts).
180
+ ...(options?.ppr !== undefined && options.ppr !== false
181
+ ? { ppr: options.ppr }
182
+ : {}),
256
183
  };
257
184
 
258
- // Capture namespace prefix on static handler for build-time reverse() resolution
259
185
  if (isStaticHandler(handler) && handler.$$id && ctx.namePrefix) {
260
186
  (handler as any).$$routePrefix = ctx.namePrefix;
261
187
  }
262
188
 
263
- // Check for duplicate route names (TypeScript should catch this, but runtime check too)
264
189
  invariant(
265
190
  ctx.manifest.get(routeName) === undefined,
266
191
  `Duplicate route name: ${routeName} at ${namespace}`,
267
192
  );
268
193
 
269
- // Register route entry with prefixed name
270
194
  ctx.manifest.set(routeName, entry);
271
195
 
272
- // Register root-scope flag for dot-local reverse resolution
273
196
  registerRouteRootScope(routeName, getRootScoped());
274
197
 
275
- // Also store pattern in a separate map for URL generation
276
198
  if (ctx.patterns) {
277
199
  ctx.patterns.set(routeName, prefixedPattern);
278
200
  }
279
201
 
280
- // Store pattern grouped by URL prefix for separate entry creation
281
202
  if (ctx.patternsByPrefix) {
282
203
  const urlPrefix = getUrlPrefix() || "";
283
204
  if (!ctx.patternsByPrefix.has(urlPrefix)) {
@@ -286,12 +207,10 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
286
207
  ctx.patternsByPrefix.get(urlPrefix)!.set(routeName, prefixedPattern);
287
208
  }
288
209
 
289
- // Store trailing slash config if specified
290
210
  if (options?.trailingSlash && ctx.trailingSlash) {
291
211
  ctx.trailingSlash.set(routeName, options.trailingSlash);
292
212
  }
293
213
 
294
- // Store search schema if specified
295
214
  if (options?.search) {
296
215
  if (ctx.searchSchemas) {
297
216
  ctx.searchSchemas.set(routeName, options.search);
@@ -299,12 +218,14 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
299
218
  registerSearchSchema(routeName, options.search);
300
219
  }
301
220
 
302
- // Run merged use callback (handler.use defaults + explicit use) if present
303
221
  if (mergedUse) {
304
- const result = store.run(namespace, entry, mergedUse)?.flat(3);
305
- invariant(
306
- Array.isArray(result) && result.every((item) => isValidUseItem(item)),
307
- `path() use() callback must return an array of use items [${namespace}]`,
222
+ const result = runAndValidateUseItems(
223
+ store,
224
+ namespace,
225
+ entry,
226
+ mergedUse,
227
+ "path",
228
+ "use",
308
229
  );
309
230
  return { name: namespace, type: "route", uses: result } as RouteItem;
310
231
  }
@@ -313,10 +234,6 @@ export function createPathHelper<TEnv>(): PathFn<TEnv> {
313
234
  }) as PathFn<TEnv>;
314
235
  }
315
236
 
316
- /**
317
- * Attach response type tag methods (.json, .text, .html, .xml, .md, .image, .stream, .any) to a path helper.
318
- * Each tag wraps the original path() call with the RESPONSE_TYPE option set.
319
- */
320
237
  export function attachPathResponseTags<TEnv>(
321
238
  pathFn: PathFn<TEnv>,
322
239
  ): PathFn<TEnv> & {
@@ -338,7 +255,6 @@ export function attachPathResponseTags<TEnv>(
338
255
  ) => {
339
256
  let options: PathOptions;
340
257
  let use: (() => any[]) | undefined;
341
-
342
258
  if (typeof optionsOrUse === "function") {
343
259
  options = { [RESPONSE_TYPE]: responseType };
344
260
  use = optionsOrUse;
@@ -1,10 +1,5 @@
1
- import type { ReactNode } from "react";
2
- import type { Handler, TrailingSlashMode } from "../types.js";
3
- import type {
4
- AllUseItems,
5
- RouteUseItem,
6
- UrlPatternsBrand,
7
- } from "../route-types.js";
1
+ import type { TrailingSlashMode } from "../types.js";
2
+ import type { AllUseItems, UrlPatternsBrand } from "../route-types.js";
8
3
  import type { SearchSchema } from "../search-params.js";
9
4
  import { RESPONSE_TYPE } from "./response-types.js";
10
5
  import type { DefaultEnv } from "../types.js";
@@ -40,12 +35,48 @@ export type LocalOnlyInclude = string & { [LOCAL_ONLY_BRAND]: void };
40
35
  /**
41
36
  * Options for path() function
42
37
  */
38
+ /**
39
+ * Options for the `ppr` path option (PPR shell caching — Axis 2, see
40
+ * docs/design/ppr-shell-resume.md and the /ppr skill). Declaring
41
+ * `ppr: true | PartialPrerenderProps` on a page route opts that DOCUMENT into
42
+ * shell capture: the rendered HTML shell (everything that is not a live hole) is
43
+ * cached and, on a later GET, flushed immediately while fizz resumes only the
44
+ * holes. Serving is integral to the router — there is no middleware to mount;
45
+ * the shell store is the app-level `createRouter({ cache })` store (which must
46
+ * implement the `getShell`/`putShell` family).
47
+ */
48
+ export interface PartialPrerenderProps {
49
+ /**
50
+ * Shell time-to-live in seconds. Defaults to 300 (`ppr: true` uses the same
51
+ * default).
52
+ */
53
+ ttl?: number;
54
+ /**
55
+ * Stale-while-revalidate window in seconds: a stale shell is still served
56
+ * while a background recapture refreshes it.
57
+ */
58
+ swr?: number;
59
+ /**
60
+ * Operational tags attached to the captured shell entry for
61
+ * `updateTag()`/`revalidateTag()`-driven eviction. UNIONED with the tags the
62
+ * capture render auto-collects (the shell's own non-loader request tags).
63
+ */
64
+ tags?: string[];
65
+ }
66
+
43
67
  export interface PathOptions<
44
68
  TName extends string = string,
45
69
  TSearch extends SearchSchema = {},
46
70
  > {
47
71
  /** Route name for href() lookups */
48
72
  name?: TName;
73
+ /**
74
+ * PPR shell caching opt-in for this page route (document-level). `true` uses
75
+ * the default policy (ttl 300); an object sets ttl/swr/tags. See
76
+ * {@link PartialPrerenderProps}. Routes without this option are pure axis 1 —
77
+ * no capture, no store reads, no logs.
78
+ */
79
+ ppr?: boolean | PartialPrerenderProps;
49
80
  /** Search param schema for typed query parameters */
50
81
  search?: TSearch;
51
82
  /** Trailing slash behavior: "never" (redirect /path/ to /path), "always" (redirect /path to /path/), "ignore" (match both) */
@@ -54,16 +85,6 @@ export interface PathOptions<
54
85
  [RESPONSE_TYPE]?: string;
55
86
  }
56
87
 
57
- /**
58
- * Internal representation of a URL pattern definition
59
- */
60
- export interface PathDefinition {
61
- pattern: string;
62
- name?: string;
63
- handler: ReactNode | Handler<any, any, any>;
64
- use?: RouteUseItem[];
65
- }
66
-
67
88
  /**
68
89
  * Result of urls() - contains the route definitions
69
90
  */
@@ -72,8 +93,6 @@ export interface UrlPatterns<
72
93
  TRoutes extends Record<string, any> = Record<string, string>,
73
94
  TResponses extends Record<string, unknown> = Record<string, unknown>,
74
95
  > {
75
- /** Internal: route definitions */
76
- readonly definitions: PathDefinition[];
77
96
  /** Internal: compiled handler function */
78
97
  readonly handler: () => AllUseItems[];
79
98
  /** Internal: trailing slash config per route name */
@@ -88,6 +107,40 @@ export interface UrlPatterns<
88
107
  readonly _responses?: TResponses;
89
108
  }
90
109
 
110
+ /**
111
+ * Extract the phantom env type carried by a UrlPatterns value.
112
+ */
113
+ export type UrlPatternsEnv<T> =
114
+ T extends UrlPatterns<infer TEnv, any, any> ? TEnv : never;
115
+
116
+ /**
117
+ * Guards `routes()` env compatibility without over-constraining.
118
+ *
119
+ * - An env-agnostic block (its env is `unknown` — e.g. a shared urls() module,
120
+ * or an app that does not augment `Rango.Env`) attaches to any router.
121
+ * - A block carrying a concrete env is accepted only when the router env
122
+ * (`TRouterEnv`) satisfies it; resolves to `never` otherwise, so a
123
+ * `urls<{ DB: D1Database }>()` cannot be mounted on a `createRouter<{}>()`.
124
+ *
125
+ * Use as `patterns: T & EnvCompatible<T, TEnv>` so `T` still infers from the
126
+ * argument — a bare `EnvCompatible<T, TEnv>` parameter sits in a non-inferrable
127
+ * conditional position and would collapse `T` to its constraint.
128
+ *
129
+ * Known limitation: `TRouterEnv extends ...` distributes over a union router env,
130
+ * so a `urls<A>()` block is accepted on `createRouter<A | B>()` even though the
131
+ * `B` arm cannot supply `A`'s env. Suppressing distribution with
132
+ * `[TRouterEnv] extends [...]` would close that edge but breaks the common
133
+ * generic-`TEnv` call sites (a deferred type parameter can't resolve the tuple
134
+ * conditional, so the intersection stops reducing to `T`). A router has one env,
135
+ * so a union env is not a supported pattern; the distributive form is kept.
136
+ */
137
+ export type EnvCompatible<TPatterns, TRouterEnv> =
138
+ unknown extends UrlPatternsEnv<TPatterns>
139
+ ? TPatterns
140
+ : TRouterEnv extends UrlPatternsEnv<TPatterns>
141
+ ? TPatterns
142
+ : never;
143
+
91
144
  /**
92
145
  * Options for include()
93
146
  */
@@ -5,6 +5,7 @@ import type {
5
5
  DefaultVars,
6
6
  } from "../types/global-namespace.js";
7
7
  import type { UseItems, ResponseRouteUseItem } from "../route-types.js";
8
+ import type { RequestScope } from "../types/request-scope.js";
8
9
 
9
10
  /**
10
11
  * Reverse function for response handler contexts.
@@ -31,21 +32,32 @@ type ResponseReverseFunction = [DefaultReverseRouteMap] extends [
31
32
  * Symbol marking a route as a response route (non-RSC).
32
33
  * Stored on PathOptions and UrlPatterns to signal the trie to short-circuit.
33
34
  */
34
- export const RESPONSE_TYPE: unique symbol = Symbol.for(
35
- "rangojs.responseType",
36
- ) as any;
35
+ export const RESPONSE_TYPE: unique symbol = Symbol.for("rangojs.responseType");
37
36
 
38
37
  /**
39
- * Handler that must return Response (not ReactNode).
40
- * Used by path.image(), path.stream(), path.any() (binary/streaming data).
38
+ * Shared shape of a response-route handler: a function returning TReturn (or a
39
+ * promise of it), plus an optional composable `use` thunk merged at mount time.
41
40
  */
42
- export type ResponseHandler<TParams = Record<string, string>, TEnv = any> = ((
41
+ type ResponseHandlerOf<
42
+ TReturn,
43
+ TParams = Record<string, string>,
44
+ TEnv = any,
45
+ > = ((
43
46
  ctx: ResponseHandlerContext<TParams, TEnv>,
44
- ) => Response | Promise<Response>) & {
47
+ ) => TReturn | Promise<TReturn>) & {
45
48
  /** Composable default DSL items merged when the handler is mounted. */
46
49
  use?: () => UseItems<ResponseRouteUseItem>;
47
50
  };
48
51
 
52
+ /**
53
+ * Handler that must return Response (not ReactNode).
54
+ * Used by path.image(), path.stream(), path.any() (binary/streaming data).
55
+ */
56
+ export type ResponseHandler<
57
+ TParams = Record<string, string>,
58
+ TEnv = any,
59
+ > = ResponseHandlerOf<Response, TParams, TEnv>;
60
+
49
61
  /**
50
62
  * JSON-serializable value type for auto-wrap support.
51
63
  */
@@ -64,12 +76,7 @@ export type JsonValue =
64
76
  export type JsonResponseHandler<
65
77
  TParams = Record<string, string>,
66
78
  TEnv = any,
67
- > = ((
68
- ctx: ResponseHandlerContext<TParams, TEnv>,
69
- ) => JsonValue | Response | Promise<JsonValue | Response>) & {
70
- /** Composable default DSL items merged when the handler is mounted. */
71
- use?: () => UseItems<ResponseRouteUseItem>;
72
- };
79
+ > = ResponseHandlerOf<JsonValue | Response, TParams, TEnv>;
73
80
 
74
81
  /**
75
82
  * Handler for text-based response routes (text, html, xml).
@@ -78,12 +85,7 @@ export type JsonResponseHandler<
78
85
  export type TextResponseHandler<
79
86
  TParams = Record<string, string>,
80
87
  TEnv = any,
81
- > = ((
82
- ctx: ResponseHandlerContext<TParams, TEnv>,
83
- ) => string | Response | Promise<string | Response>) & {
84
- /** Composable default DSL items merged when the handler is mounted. */
85
- use?: () => UseItems<ResponseRouteUseItem>;
86
- };
88
+ > = ResponseHandlerOf<string | Response, TParams, TEnv>;
87
89
 
88
90
  /**
89
91
  * Lighter handler context for response routes.
@@ -93,19 +95,10 @@ export type TextResponseHandler<
93
95
  export interface ResponseHandlerContext<
94
96
  TParams = Record<string, string>,
95
97
  TEnv = any,
96
- > {
97
- request: Request;
98
+ > extends RequestScope<TEnv> {
98
99
  params: TParams;
99
100
  /** @internal Phantom property for params type invariance. Prevents mounting handlers on wrong routes. */
100
101
  readonly _paramCheck?: (params: TParams) => TParams;
101
- /** Platform bindings (DB, KV, secrets, etc.). */
102
- env: TEnv;
103
- /** Query parameters from the URL (system params like `_rsc*` are filtered). */
104
- searchParams: URLSearchParams;
105
- /** The full URL object (with system params filtered). */
106
- url: URL;
107
- /** The pathname portion of the request URL. */
108
- pathname: string;
109
102
  reverse: ResponseReverseFunction;
110
103
  /** Read a variable set by middleware via ctx.set(key, value) or ctx.set(ContextVar, value). */
111
104
  get: {