@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
@@ -2,20 +2,21 @@ import type { ComponentType, ReactNode } from "react";
2
2
  import type { SerializedManifest } from "../debug.js";
3
3
  import type { ReverseFunction } from "../reverse.js";
4
4
  import type { UrlPatterns } from "../urls.js";
5
- import type { UrlBuilder } from "../urls/pattern-types.js";
5
+ import type { UrlBuilder, EnvCompatible } from "../urls/pattern-types.js";
6
6
  import type { EntryData } from "../server/context";
7
7
  import type { ErrorInfo, MatchResult } from "../types";
8
8
  import type { NonceProvider } from "../rsc/types.js";
9
9
  import type { ExecutionContext } from "../server/request-context.js";
10
- import type {
11
- SerializedSegmentData,
12
- SegmentHandleData,
13
- } from "../cache/types.js";
10
+ import type { SerializedSegmentData } from "../cache/types.js";
14
11
  import type { MiddlewareEntry, MiddlewareFn } from "./middleware.js";
12
+ import type { RouteMatchResult } from "./pattern-matching.js";
13
+ import type { ExtractParams } from "../types/route-config.js";
15
14
  import { RSC_ROUTER_BRAND } from "./router-registry.js";
16
- import type { RSCRouterOptions, RootLayoutProps } from "./router-options.js";
15
+ import type { RangoOptions, RootLayoutProps } from "./router-options.js";
17
16
  import type { DefaultVars } from "../types/global-namespace.js";
18
17
  import type { ResolvedTimeouts, OnTimeoutCallback } from "./timeout.js";
18
+ import type { ResolvedTracing } from "./tracing.js";
19
+ import type { TelemetrySink } from "./telemetry.js";
19
20
 
20
21
  /**
21
22
  * Options passed to router.fetch(), router.match(), and other request entrypoints.
@@ -49,16 +50,16 @@ type MergeRoutesWithResponses<
49
50
  };
50
51
 
51
52
  /**
52
- * Public RSC Router interface — the user-facing API surface.
53
+ * Public Rango router interface — the user-facing API surface.
53
54
  *
54
55
  * Users interact with this type when building and using routers.
55
- * Internal framework code uses RSCRouterInternal (via toInternal()) to access
56
+ * Internal framework code uses RangoInternal (via toInternal()) to access
56
57
  * matching, build-time, and configuration members that are not part of the
57
58
  * public contract.
58
59
  *
59
60
  * TRoutes accumulates all registered route types through the builder chain.
60
61
  */
61
- export interface RSCRouter<
62
+ export interface Rango<
62
63
  TEnv = any,
63
64
  TRoutes extends Record<string, unknown> = Record<string, string>,
64
65
  > {
@@ -89,16 +90,16 @@ export interface RSCRouter<
89
90
  * ])
90
91
  * ```
91
92
  */
92
- routes<T extends UrlPatterns<TEnv, any>>(
93
- patterns: T,
94
- ): RSCRouter<
93
+ routes<T extends UrlPatterns<any, any, any>>(
94
+ patterns: T & EnvCompatible<T, TEnv>,
95
+ ): Rango<
95
96
  TEnv,
96
97
  TRoutes &
97
98
  (NonNullable<T["_routes"]> extends Record<string, unknown>
98
99
  ? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
99
100
  : Record<string, string>)
100
101
  >;
101
- routes(builder: UrlBuilder<TEnv>): RSCRouter<TEnv, TRoutes>;
102
+ routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
102
103
 
103
104
  /**
104
105
  * Add global middleware that runs on all routes
@@ -108,13 +109,18 @@ export interface RSCRouter<
108
109
  * createRouter({ document: RootLayout })
109
110
  * .use(loggerMiddleware) // All routes
110
111
  * .use("/api/*", rateLimiter) // Pattern match
112
+ * .use("/users/:id", (ctx) => {}) // ctx.params.id is typed
111
113
  * .routes(urlpatterns)
112
114
  * ```
113
115
  */
116
+ use<Pattern extends string>(
117
+ pattern: Pattern,
118
+ middleware: MiddlewareFn<TEnv, ExtractParams<Pattern>>,
119
+ ): Rango<TEnv, TRoutes>;
114
120
  use(
115
121
  patternOrMiddleware: string | MiddlewareFn<TEnv>,
116
122
  middleware?: MiddlewareFn<TEnv>,
117
- ): RSCRouter<TEnv, TRoutes>;
123
+ ): Rango<TEnv, TRoutes>;
118
124
 
119
125
  /**
120
126
  * Type-safe URL builder for registered routes
@@ -141,7 +147,7 @@ export interface RSCRouter<
141
147
  * type AppRoutes = typeof _router.routeMap;
142
148
  *
143
149
  * declare global {
144
- * namespace RSCRouter {
150
+ * namespace Rango {
145
151
  * interface RegisteredRoutes extends AppRoutes {}
146
152
  * }
147
153
  * }
@@ -177,16 +183,16 @@ export interface RSCRouter<
177
183
  }
178
184
 
179
185
  /**
180
- * Internal RSC Router interface — the full framework-facing API.
186
+ * Internal Rango router interface — the full framework-facing API.
181
187
  *
182
188
  * This type includes all members used by the Vite plugin, RSC handler,
183
189
  * pre-rendering pipeline, and other framework internals. It is NOT exported
184
190
  * from the public package API.
185
191
  *
186
- * Use toInternal(router) to assert a public RSCRouter into this type
192
+ * Use toInternal(router) to assert a public Rango into this type
187
193
  * at the boundary where framework code receives a user-provided router.
188
194
  */
189
- export interface RSCRouterInternal<
195
+ export interface RangoInternal<
190
196
  TEnv = any,
191
197
  TRoutes extends Record<string, unknown> = Record<string, string>,
192
198
  > {
@@ -206,26 +212,36 @@ export interface RSCRouterInternal<
206
212
  readonly basename: string | undefined;
207
213
 
208
214
  /**
209
- * Register routes using URL patterns from urls() or a builder function
210
- */
211
- routes<T extends UrlPatterns<TEnv, any>>(
212
- patterns: T,
213
- ): RSCRouter<
215
+ * Register routes using URL patterns from urls() or a builder function.
216
+ *
217
+ * Env compatibility is checked by EnvCompatible: an env-agnostic urls() block
218
+ * (its env is `unknown` — e.g. a shared module, or an app that does not augment
219
+ * `Rango.Env`) attaches to any router, while a urls<TEnv>() block carrying a
220
+ * concrete env is accepted only when this router's `TEnv` satisfies it. So a
221
+ * `urls<{ DB }>()` cannot be mounted on a `createRouter<{}>()`.
222
+ */
223
+ routes<T extends UrlPatterns<any, any, any>>(
224
+ patterns: T & EnvCompatible<T, TEnv>,
225
+ ): Rango<
214
226
  TEnv,
215
227
  TRoutes &
216
228
  (NonNullable<T["_routes"]> extends Record<string, unknown>
217
229
  ? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
218
230
  : Record<string, string>)
219
231
  >;
220
- routes(builder: UrlBuilder<TEnv>): RSCRouter<TEnv, TRoutes>;
232
+ routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
221
233
 
222
234
  /**
223
235
  * Add global middleware that runs on all routes
224
236
  */
237
+ use<Pattern extends string>(
238
+ pattern: Pattern,
239
+ middleware: MiddlewareFn<TEnv, ExtractParams<Pattern>>,
240
+ ): Rango<TEnv, TRoutes>;
225
241
  use(
226
242
  patternOrMiddleware: string | MiddlewareFn<TEnv>,
227
243
  middleware?: MiddlewareFn<TEnv>,
228
- ): RSCRouter<TEnv, TRoutes>;
244
+ ): Rango<TEnv, TRoutes>;
229
245
 
230
246
  /**
231
247
  * Type-safe URL builder for registered routes
@@ -247,17 +263,17 @@ export interface RSCRouterInternal<
247
263
  * Error callback for monitoring/alerting
248
264
  * Called when errors occur in loaders, actions, or routes
249
265
  */
250
- readonly onError?: RSCRouterOptions<TEnv>["onError"];
266
+ readonly onError?: RangoOptions<TEnv>["onError"];
251
267
 
252
268
  /**
253
269
  * Cache configuration
254
270
  */
255
- readonly cache?: RSCRouterOptions<TEnv>["cache"];
271
+ readonly cache?: RangoOptions<TEnv>["cache"];
256
272
 
257
273
  /**
258
274
  * Not found component to render when no route matches
259
275
  */
260
- readonly notFound?: RSCRouterOptions<TEnv>["notFound"];
276
+ readonly notFound?: RangoOptions<TEnv>["notFound"];
261
277
 
262
278
  /**
263
279
  * Resolved theme configuration (null if theme not enabled)
@@ -287,6 +303,27 @@ export interface RSCRouterInternal<
287
303
  */
288
304
  readonly prefetchCacheTTL: number;
289
305
 
306
+ /**
307
+ * Maximum number of decoded prefetch payloads the client keeps in its
308
+ * in-memory prefetch cache (FIFO eviction at capacity). Shipped to the
309
+ * client in payload metadata. Derived from prefetchCacheSize.
310
+ */
311
+ readonly prefetchCacheSize: number;
312
+
313
+ /**
314
+ * Maximum number of speculative prefetch requests the client runs
315
+ * concurrently. Shipped to the client in payload metadata. Derived from
316
+ * prefetchConcurrency.
317
+ */
318
+ readonly prefetchConcurrency: number;
319
+
320
+ /**
321
+ * Resolved rango state cookie name (`{prefix}_{routerId}`), composed once at
322
+ * router init and shipped to the client in payload metadata. The server-side
323
+ * cookie writer reads it from here; the client reads it from metadata.
324
+ */
325
+ readonly resolvedStateCookieName: string;
326
+
290
327
  /**
291
328
  * Whether connection warmup is enabled.
292
329
  * When true, the client sends HEAD /?_rsc_warmup after idle periods
@@ -294,12 +331,34 @@ export interface RSCRouterInternal<
294
331
  */
295
332
  readonly warmupEnabled: boolean;
296
333
 
334
+ /**
335
+ * Whether the client hydrates inside React.StrictMode. Resolved from
336
+ * createRouter({ strictMode }) (default true) and shipped to the client in
337
+ * the initial payload metadata.
338
+ */
339
+ readonly strictMode: boolean;
340
+
297
341
  /**
298
342
  * Whether router-wide performance debugging is enabled.
299
343
  * Used by the request handler to create metrics before middleware runs.
300
344
  */
301
345
  readonly debugPerformance?: boolean;
302
346
 
347
+ /**
348
+ * Resolved platform phase-span tracing (Cloudflare custom spans or OTel), or
349
+ * undefined when off. Threaded onto the request context and read at each
350
+ * traced phase.
351
+ */
352
+ readonly tracing?: ResolvedTracing;
353
+
354
+ /**
355
+ * Raw telemetry sink from RangoOptions, exposed so handler-level emitters
356
+ * (rsc/handler.ts timeout/origin/late-handle) can emit WITHOUT the
357
+ * RouterContext ALS, which only match()/matchPartial() enter. See
358
+ * observeEvent's emitter list in router/instrument.ts.
359
+ */
360
+ readonly telemetry?: TelemetrySink;
361
+
303
362
  /**
304
363
  * Whether ?__debug_manifest is allowed in production.
305
364
  * Always enabled in development.
@@ -359,6 +418,17 @@ export interface RSCRouterInternal<
359
418
  /** @internal basename for runtime manifest generation */
360
419
  readonly __basename?: string;
361
420
 
421
+ /**
422
+ * @internal Router-level error/notFound fallbacks (`createRouter` options),
423
+ * exposed for the build-time clientChunks discovery so a `"use client"`
424
+ * default boundary is routed into the dedicated `app-fallback` chunk. Unlike
425
+ * the route-tree `errorBoundary()`/`notFoundBoundary()` helpers these never
426
+ * land in `EntryData`, so they are read directly off the router instance.
427
+ */
428
+ readonly __defaultErrorBoundary?: RangoOptions<TEnv>["defaultErrorBoundary"];
429
+ readonly __defaultNotFoundBoundary?: RangoOptions<TEnv>["defaultNotFoundBoundary"];
430
+ readonly __notFound?: RangoOptions<TEnv>["notFound"];
431
+
362
432
  match(
363
433
  request: Request,
364
434
  input?: RouterRequestInput<TEnv>,
@@ -378,11 +448,13 @@ export interface RSCRouterInternal<
378
448
  devMode?: boolean,
379
449
  ): Promise<{
380
450
  segments: SerializedSegmentData[];
381
- handles: Record<string, SegmentHandleData>;
451
+ /** RSC-encoded handle map ("" when none) — see handle-snapshot.ts. */
452
+ handles: string;
382
453
  routeName: string;
383
454
  params: Record<string, string>;
384
455
  interceptSegments?: SerializedSegmentData[];
385
- interceptHandles?: Record<string, SegmentHandleData>;
456
+ /** RSC-encoded MERGED (main + intercept) handle map for the intercept artifact. */
457
+ interceptHandles?: string;
386
458
  passthrough?: true;
387
459
  } | null>;
388
460
 
@@ -396,7 +468,7 @@ export interface RSCRouterInternal<
396
468
  routeName?: string,
397
469
  buildEnv?: any,
398
470
  devMode?: boolean,
399
- ): Promise<{ encoded: string; handles: Record<string, unknown[]> } | null>;
471
+ ): Promise<{ encoded: string; handles: string } | null>;
400
472
 
401
473
  /**
402
474
  * Preview match - returns route middleware without segment resolution.
@@ -454,7 +526,14 @@ export interface RSCRouterInternal<
454
526
  * Used by classifyRequest() for request classification without
455
527
  * entering the full match pipeline.
456
528
  */
457
- findMatch(pathname: string, metricsStore?: any): any;
529
+ // Async since a lazy async include (`() => import()`) must resolve before its
530
+ // routes can match. Typed (not `any`) so a consumer doing
531
+ // `const m = router.findMatch(p); if (!m) ...; m.entry` gets a compile error
532
+ // (m is a Promise) instead of the silent always-truthy bug.
533
+ findMatch(
534
+ pathname: string,
535
+ metricsStore?: any,
536
+ ): Promise<RouteMatchResult<TEnv> | null>;
458
537
 
459
538
  /**
460
539
  * Debug utility to serialize the manifest for inspection
@@ -469,16 +548,16 @@ export interface RSCRouterInternal<
469
548
  }
470
549
 
471
550
  /**
472
- * Assert a public RSCRouter into the internal type.
551
+ * Assert a public Rango into the internal type.
473
552
  *
474
553
  * Use this at the boundary where framework code receives a user-provided
475
554
  * router and needs access to internal members (match, config, build-time).
476
555
  * The cast is safe because createRouter() always produces an object that
477
- * satisfies RSCRouterInternal; the public type is just a narrower view.
556
+ * satisfies RangoInternal; the public type is just a narrower view.
478
557
  */
479
558
  export function toInternal<
480
559
  TEnv = any,
481
560
  TRoutes extends Record<string, unknown> = Record<string, string>,
482
- >(router: RSCRouter<TEnv, TRoutes>): RSCRouterInternal<TEnv, TRoutes> {
483
- return router as RSCRouterInternal<TEnv, TRoutes>;
561
+ >(router: Rango<TEnv, TRoutes>): RangoInternal<TEnv, TRoutes> {
562
+ return router as RangoInternal<TEnv, TRoutes>;
484
563
  }
@@ -11,6 +11,7 @@ import type { UrlPatterns } from "../urls.js";
11
11
  import type { UrlBuilder } from "../urls/pattern-types.js";
12
12
  import type { NamedRouteEntry } from "./content-negotiation.js";
13
13
  import type { TelemetrySink } from "./telemetry.js";
14
+ import type { RouterTracingConfig } from "./tracing.js";
14
15
  import type { RouterTimeouts, OnTimeoutCallback } from "./timeout.js";
15
16
 
16
17
  /**
@@ -73,7 +74,7 @@ export interface RootLayoutProps {
73
74
  /**
74
75
  * Router configuration options
75
76
  */
76
- export interface RSCRouterOptions<TEnv = any> {
77
+ export interface RangoOptions<TEnv = any> {
77
78
  /**
78
79
  * Unique identifier for this router instance.
79
80
  * Used to namespace static output files and route maps.
@@ -132,6 +133,21 @@ export interface RSCRouterOptions<TEnv = any> {
132
133
  */
133
134
  allowDebugManifest?: boolean;
134
135
 
136
+ /**
137
+ * DEVELOPMENT/TEST ONLY. Emit an `X-Rango-Cache` response header describing
138
+ * the cache status of the matched route, for use by testing primitives such
139
+ * as `assertCacheStatus`.
140
+ *
141
+ * Defaults to `false`. When neither this option nor the
142
+ * `RANGO_TEST_SIGNALS=1` environment flag is set, NO header is emitted and
143
+ * router output is byte-identical to the default.
144
+ *
145
+ * The header encodes per-segment (v1: coarse route-level) status keyed by the
146
+ * route NAME, e.g. `X-Rango-Cache: product.detail=hit`. Do NOT enable in
147
+ * production — it exposes internal cache decisions.
148
+ */
149
+ debugCacheSignal?: boolean;
150
+
135
151
  /**
136
152
  * Document component that wraps the entire application.
137
153
  *
@@ -357,6 +373,30 @@ export interface RSCRouterOptions<TEnv = any> {
357
373
  */
358
374
  theme?: import("../theme/types.js").ThemeConfig | true;
359
375
 
376
+ /**
377
+ * Default for whether the router wraps `transition()` segments in its own
378
+ * React `<ViewTransition>` boundary (experimental React only).
379
+ *
380
+ * - "auto" (default): every route/layout that opts in via `transition()`
381
+ * gets a router-owned cross-fade.
382
+ * - false: the router never places its own boundary. Routes that use
383
+ * `transition()` still drive navigation through startTransition (so loaders
384
+ * hold instead of flashing a skeleton) and still let consumer-placed
385
+ * `<ViewTransition>` elements animate — the router just contributes no
386
+ * cross-fade of its own. This is the "router triggers, you place the
387
+ * transitions" model.
388
+ *
389
+ * A per-segment `transition({ viewTransition })` overrides this default.
390
+ *
391
+ * @example
392
+ * ```typescript
393
+ * // App-wide: drive + hold, but never auto-wrap. Place <ViewTransition>
394
+ * // yourself in components where you want a morph.
395
+ * const router = createRouter<AppEnv>({ viewTransition: false });
396
+ * ```
397
+ */
398
+ viewTransition?: "auto" | false;
399
+
360
400
  /**
361
401
  * URL patterns to register with the router.
362
402
  *
@@ -457,6 +497,51 @@ export interface RSCRouterOptions<TEnv = any> {
457
497
  */
458
498
  prefetchCacheTTL?: number | false;
459
499
 
500
+ /**
501
+ * Maximum number of decoded prefetch payloads the client keeps in its
502
+ * in-memory prefetch cache. When the cache is full the oldest entry is
503
+ * evicted (FIFO) to make room for a new prefetch.
504
+ *
505
+ * Each entry retains a fully decoded RSC payload (and the route's client
506
+ * chunks pulled in while decoding), so this is the lever on client-side
507
+ * prefetch memory: a higher value warms more routes at the cost of more
508
+ * retained payloads. Staleness is bounded separately by `prefetchCacheTTL`;
509
+ * this bounds the entry COUNT.
510
+ *
511
+ * Values below 1 (or non-finite) fall back to the default. To turn
512
+ * prefetching off entirely, set `prefetchCacheTTL: false` instead.
513
+ *
514
+ * @default 100
515
+ */
516
+ prefetchCacheSize?: number;
517
+
518
+ /**
519
+ * Maximum number of speculative prefetch requests (viewport/render strategy)
520
+ * the client runs concurrently. Hover prefetches bypass this queue and fire
521
+ * immediately; this caps only the background, idle-gated queue so prefetches
522
+ * never saturate the browser's connection pool.
523
+ *
524
+ * Values below 1 (or non-finite) fall back to the default.
525
+ *
526
+ * @default 2
527
+ */
528
+ prefetchConcurrency?: number;
529
+
530
+ /**
531
+ * Prefix for the rango state cookie name. The resolved name is
532
+ * `{prefix}_{routerId}`; the prefix is sanitized to cookie-name-safe
533
+ * characters (`[A-Za-z0-9-]`) and an empty result falls back to the default.
534
+ *
535
+ * The rango state cookie keys the client's prefetch / HTTP caches. Overriding
536
+ * the prefix lets you align it with cookie-naming policies or consent-manager
537
+ * classification lists, or avoid colliding with an existing `rango-state`
538
+ * cookie. It is not a full-name override: the `_{routerId}` suffix is what
539
+ * keeps sibling apps on one origin from clobbering each other's state.
540
+ *
541
+ * @default "rango-state"
542
+ */
543
+ stateCookiePrefix?: string;
544
+
460
545
  /**
461
546
  * Enable connection warmup to keep TCP+TLS alive after idle periods.
462
547
  *
@@ -468,6 +553,29 @@ export interface RSCRouterOptions<TEnv = any> {
468
553
  */
469
554
  warmup?: boolean;
470
555
 
556
+ /**
557
+ * Wrap the hydrated client tree in `React.StrictMode`.
558
+ *
559
+ * The Rango browser entry hydrates the app inside `<React.StrictMode>` by
560
+ * default. StrictMode double-invokes render and (in development) mounts,
561
+ * unmounts, then remounts every effect to surface impure renders and missing
562
+ * effect cleanup. Production builds treat StrictMode as a no-op, so this flag
563
+ * only changes development behavior in a normal app.
564
+ *
565
+ * Set to `false` to hydrate without the StrictMode wrapper. The main reason to
566
+ * opt out is to isolate StrictMode's intentional double-render/double-effect
567
+ * from genuine re-renders when measuring client-hook stability — with
568
+ * StrictMode off, render counts are exact in development too.
569
+ *
570
+ * The value is resolved server-side at router creation and shipped to the
571
+ * client in the initial payload metadata; the browser entry reads it once at
572
+ * hydration. Changing it does not affect the SSR HTML (StrictMode emits no
573
+ * DOM), so toggling it never causes a hydration mismatch.
574
+ *
575
+ * @default true
576
+ */
577
+ strictMode?: boolean;
578
+
471
579
  /**
472
580
  * Shorthand timeout (ms) applied to both action execution and render start.
473
581
  * Does NOT apply to streamIdleMs.
@@ -520,11 +628,14 @@ export interface RSCRouterOptions<TEnv = any> {
520
628
  onTimeout?: OnTimeoutCallback<TEnv>;
521
629
 
522
630
  /**
523
- * Telemetry sink for structured lifecycle events.
631
+ * Telemetry sink for structured, discrete lifecycle EVENTS: request
632
+ * start/end/error, loader start/end/error, handler errors, cache decisions,
633
+ * revalidation decisions, timeouts, origin rejections.
524
634
  *
525
- * When provided, the router emits events for request start/end,
526
- * loader start/end/error, handler errors, cache decisions, and
527
- * revalidation decisions.
635
+ * This is the EVENT surface. Phase-duration SPANS (request/middleware/action/
636
+ * handler/loader/render/ssr timing wired into a tracing backend) come from the
637
+ * separate `tracing` option below — a sink does not emit them, because async-context nesting
638
+ * cannot be faithfully reconstructed from after-the-fact start/end events.
528
639
  *
529
640
  * No-op when not configured (zero overhead).
530
641
  *
@@ -537,6 +648,18 @@ export interface RSCRouterOptions<TEnv = any> {
537
648
  * });
538
649
  * ```
539
650
  *
651
+ * @example OpenTelemetry — pair the event sink with the tracing slot
652
+ * ```typescript
653
+ * import { createOTelTracing, createOTelSink } from "@rangojs/router";
654
+ * import { trace } from "@opentelemetry/api";
655
+ *
656
+ * const tracer = trace.getTracer("my-app");
657
+ * const router = createRouter({
658
+ * tracing: createOTelTracing(tracer), // phase spans
659
+ * telemetry: createOTelSink(tracer), // discrete-fact events
660
+ * });
661
+ * ```
662
+ *
540
663
  * @example Custom sink
541
664
  * ```typescript
542
665
  * const router = createRouter({
@@ -550,6 +673,44 @@ export interface RSCRouterOptions<TEnv = any> {
550
673
  */
551
674
  telemetry?: TelemetrySink;
552
675
 
676
+ /**
677
+ * Span tracing for the router's performance phases (request, middleware, action,
678
+ * loaders, render, ssr). Connects the same phases shown in the
679
+ * `debugPerformance` timeline to the host platform's tracing system. This is
680
+ * the SPAN surface (the `telemetry` option above is the event surface).
681
+ *
682
+ * Two factories produce a config, both for this slot:
683
+ * - `createOTelTracing(tracer)` from `@rangojs/router` — any platform with an
684
+ * OpenTelemetry SDK (including Node). Bridges the phases onto
685
+ * `tracer.startActiveSpan`.
686
+ * - `createCloudflareTracing()` from `@rangojs/router/cloudflare` — Cloudflare
687
+ * Workers native custom spans, alongside the automatic KV/D1/fetch spans.
688
+ *
689
+ * When tracing is unset — or off-platform (no OTel SDK / no Cloudflare tracing
690
+ * destination) — every span call falls through to the work directly, so the
691
+ * request behaves exactly as if tracing were off.
692
+ *
693
+ * @example OpenTelemetry
694
+ * ```typescript
695
+ * import { createOTelTracing } from "@rangojs/router";
696
+ * import { trace } from "@opentelemetry/api";
697
+ *
698
+ * const router = createRouter({
699
+ * tracing: createOTelTracing(trace.getTracer("my-app")),
700
+ * });
701
+ * ```
702
+ *
703
+ * @example Cloudflare
704
+ * ```typescript
705
+ * import { createCloudflareTracing } from "@rangojs/router/cloudflare";
706
+ *
707
+ * const router = createRouter({
708
+ * tracing: createCloudflareTracing({ spans: { ssr: false } }),
709
+ * });
710
+ * ```
711
+ */
712
+ tracing?: RouterTracingConfig;
713
+
553
714
  /**
554
715
  * SSR configuration options.
555
716
  *
@@ -1,4 +1,4 @@
1
- import type { RSCRouterInternal } from "./router-interfaces.js";
1
+ import type { RangoInternal } from "./router-interfaces.js";
2
2
 
3
3
  /**
4
4
  * Brand marker for identifying router instances at build time.
@@ -12,10 +12,7 @@ export const RSC_ROUTER_BRAND = "__rsc_router__" as const;
12
12
  * Used by the Vite plugin at build time to discover routers and extract
13
13
  * manifests, prefix trees, and pre-render candidates.
14
14
  */
15
- export const RouterRegistry: Map<
16
- string,
17
- RSCRouterInternal<any, any>
18
- > = new Map();
15
+ export const RouterRegistry: Map<string, RangoInternal<any, any>> = new Map();
19
16
 
20
17
  export let routerAutoId = 0;
21
18