@rangojs/router 0.0.0-experimental.32 → 0.0.0-experimental.3232cd17

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 (376) hide show
  1. package/AGENTS.md +4 -0
  2. package/README.md +198 -44
  3. package/dist/bin/rango.js +287 -105
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +3248 -1117
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +73 -21
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +107 -1
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +245 -21
  12. package/skills/caching/SKILL.md +302 -6
  13. package/skills/composability/SKILL.md +27 -2
  14. package/skills/css/SKILL.md +76 -0
  15. package/skills/document-cache/SKILL.md +78 -55
  16. package/skills/handler-use/SKILL.md +364 -0
  17. package/skills/hooks/SKILL.md +270 -30
  18. package/skills/host-router/SKILL.md +82 -22
  19. package/skills/i18n/SKILL.md +276 -0
  20. package/skills/intercept/SKILL.md +49 -5
  21. package/skills/layout/SKILL.md +35 -9
  22. package/skills/links/SKILL.md +249 -17
  23. package/skills/loader/SKILL.md +294 -30
  24. package/skills/middleware/SKILL.md +52 -13
  25. package/skills/migrate-nextjs/SKILL.md +584 -0
  26. package/skills/migrate-react-router/SKILL.md +769 -0
  27. package/skills/mime-routes/SKILL.md +27 -0
  28. package/skills/observability/SKILL.md +137 -0
  29. package/skills/parallel/SKILL.md +203 -7
  30. package/skills/prerender/SKILL.md +123 -100
  31. package/skills/rango/SKILL.md +250 -22
  32. package/skills/react-compiler/SKILL.md +168 -0
  33. package/skills/response-routes/SKILL.md +122 -47
  34. package/skills/route/SKILL.md +97 -5
  35. package/skills/router-setup/SKILL.md +90 -5
  36. package/skills/server-actions/SKILL.md +775 -0
  37. package/skills/streams-and-websockets/SKILL.md +283 -0
  38. package/skills/tailwind/SKILL.md +27 -3
  39. package/skills/testing/SKILL.md +129 -0
  40. package/skills/testing/bindings.md +89 -0
  41. package/skills/testing/cache-prerender.md +124 -0
  42. package/skills/testing/client-components.md +122 -0
  43. package/skills/testing/e2e-parity.md +125 -0
  44. package/skills/testing/flight.md +92 -0
  45. package/skills/testing/handles.md +129 -0
  46. package/skills/testing/loader.md +128 -0
  47. package/skills/testing/middleware.md +99 -0
  48. package/skills/testing/render-handler.md +121 -0
  49. package/skills/testing/response-routes.md +95 -0
  50. package/skills/testing/reverse-and-types.md +84 -0
  51. package/skills/testing/server-actions.md +107 -0
  52. package/skills/testing/server-tree.md +128 -0
  53. package/skills/testing/setup.md +120 -0
  54. package/skills/typesafety/SKILL.md +329 -27
  55. package/skills/use-cache/SKILL.md +36 -5
  56. package/skills/view-transitions/SKILL.md +294 -0
  57. package/src/__augment-tests__/augment.ts +81 -0
  58. package/src/__augment-tests__/augmented.check.ts +116 -0
  59. package/src/__internal.ts +67 -40
  60. package/src/browser/action-coordinator.ts +53 -36
  61. package/src/browser/action-fence.ts +47 -0
  62. package/src/browser/app-shell.ts +39 -0
  63. package/src/browser/app-version.ts +14 -0
  64. package/src/browser/cookie-name.ts +140 -0
  65. package/src/browser/event-controller.ts +86 -147
  66. package/src/browser/history-state.ts +21 -0
  67. package/src/browser/index.ts +3 -3
  68. package/src/browser/invalidate-client-cache.ts +52 -0
  69. package/src/browser/link-interceptor.ts +4 -0
  70. package/src/browser/navigation-bridge.ts +148 -19
  71. package/src/browser/navigation-client.ts +187 -67
  72. package/src/browser/navigation-store-handle.ts +38 -0
  73. package/src/browser/navigation-store.ts +76 -67
  74. package/src/browser/navigation-transaction.ts +18 -66
  75. package/src/browser/partial-update.ts +123 -94
  76. package/src/browser/prefetch/cache.ts +214 -36
  77. package/src/browser/prefetch/fetch.ts +260 -38
  78. package/src/browser/prefetch/policy.ts +6 -0
  79. package/src/browser/prefetch/queue.ts +126 -20
  80. package/src/browser/prefetch/resource-ready.ts +77 -0
  81. package/src/browser/rango-state.ts +158 -76
  82. package/src/browser/react/Link.tsx +93 -11
  83. package/src/browser/react/NavigationProvider.tsx +115 -34
  84. package/src/browser/react/ScrollRestoration.tsx +10 -6
  85. package/src/browser/react/context.ts +7 -2
  86. package/src/browser/react/filter-segment-order.ts +49 -7
  87. package/src/browser/react/index.ts +0 -48
  88. package/src/browser/react/location-state-shared.ts +166 -8
  89. package/src/browser/react/location-state.ts +39 -14
  90. package/src/browser/react/use-action.ts +6 -15
  91. package/src/browser/react/use-handle.ts +23 -69
  92. package/src/browser/react/use-link-status.ts +0 -4
  93. package/src/browser/react/use-navigation.ts +22 -5
  94. package/src/browser/react/use-params.ts +20 -10
  95. package/src/browser/react/use-reverse.ts +106 -0
  96. package/src/browser/react/use-router.ts +46 -11
  97. package/src/browser/react/use-search-params.ts +0 -5
  98. package/src/browser/react/use-segments.ts +11 -21
  99. package/src/browser/response-adapter.ts +52 -1
  100. package/src/browser/rsc-router.tsx +215 -76
  101. package/src/browser/scroll-restoration.ts +46 -39
  102. package/src/browser/segment-reconciler.ts +36 -9
  103. package/src/browser/segment-structure-assert.ts +2 -2
  104. package/src/browser/server-action-bridge.ts +176 -50
  105. package/src/browser/types.ts +95 -11
  106. package/src/browser/validate-redirect-origin.ts +43 -16
  107. package/src/build/collect-fallback-refs.ts +107 -0
  108. package/src/build/generate-manifest.ts +65 -40
  109. package/src/build/generate-route-types.ts +5 -0
  110. package/src/build/index.ts +8 -2
  111. package/src/build/prefix-tree-utils.ts +123 -0
  112. package/src/build/route-trie.ts +137 -32
  113. package/src/build/route-types/codegen.ts +4 -4
  114. package/src/build/route-types/include-resolution.ts +9 -2
  115. package/src/build/route-types/param-extraction.ts +6 -3
  116. package/src/build/route-types/per-module-writer.ts +7 -4
  117. package/src/build/route-types/router-processing.ts +278 -96
  118. package/src/build/route-types/scan-filter.ts +9 -2
  119. package/src/build/route-types/source-scan.ts +118 -0
  120. package/src/build/runtime-discovery.ts +9 -20
  121. package/src/cache/cache-error.ts +104 -0
  122. package/src/cache/cache-policy.ts +68 -28
  123. package/src/cache/cache-runtime.ts +149 -43
  124. package/src/cache/cache-scope.ts +148 -81
  125. package/src/cache/cache-tag.ts +98 -0
  126. package/src/cache/cf/cf-cache-store.ts +2550 -93
  127. package/src/cache/cf/index.ts +11 -17
  128. package/src/cache/document-cache.ts +78 -27
  129. package/src/cache/handle-snapshot.ts +63 -0
  130. package/src/cache/index.ts +23 -20
  131. package/src/cache/memory-segment-store.ts +136 -37
  132. package/src/cache/profile-registry.ts +6 -30
  133. package/src/cache/read-through-swr.ts +41 -11
  134. package/src/cache/segment-codec.ts +0 -16
  135. package/src/cache/tag-invalidation.ts +230 -0
  136. package/src/cache/taint.ts +55 -0
  137. package/src/cache/types.ts +33 -100
  138. package/src/cache/vercel/index.ts +11 -0
  139. package/src/cache/vercel/vercel-cache-store.ts +799 -0
  140. package/src/client.rsc.tsx +6 -21
  141. package/src/client.tsx +108 -290
  142. package/src/component-utils.ts +19 -0
  143. package/src/context-var.ts +84 -2
  144. package/src/debug.ts +2 -2
  145. package/src/decode-loader-results.ts +36 -0
  146. package/src/defer.ts +196 -0
  147. package/src/deps/ssr.ts +0 -1
  148. package/src/errors.ts +30 -4
  149. package/src/handle.ts +70 -22
  150. package/src/handles/MetaTags.tsx +0 -14
  151. package/src/handles/breadcrumbs.ts +16 -5
  152. package/src/handles/meta.ts +0 -39
  153. package/src/host/cookie-handler.ts +0 -36
  154. package/src/host/errors.ts +0 -24
  155. package/src/host/index.ts +8 -2
  156. package/src/host/pattern-matcher.ts +7 -50
  157. package/src/host/router.ts +107 -99
  158. package/src/host/testing.ts +40 -27
  159. package/src/host/types.ts +37 -4
  160. package/src/host/utils.ts +1 -1
  161. package/src/href-client.ts +137 -22
  162. package/src/index.rsc.ts +52 -26
  163. package/src/index.ts +100 -38
  164. package/src/internal-debug.ts +2 -4
  165. package/src/loader-store.ts +500 -0
  166. package/src/loader.rsc.ts +20 -13
  167. package/src/loader.ts +12 -11
  168. package/src/missing-id-error.ts +68 -0
  169. package/src/network-error-thrower.tsx +1 -6
  170. package/src/outlet-context.ts +1 -1
  171. package/src/outlet-provider.tsx +1 -5
  172. package/src/prerender/param-hash.ts +10 -11
  173. package/src/prerender/store.ts +37 -41
  174. package/src/prerender.ts +198 -82
  175. package/src/redirect-origin.ts +100 -0
  176. package/src/response-utils.ts +37 -0
  177. package/src/reverse.ts +65 -15
  178. package/src/root-error-boundary.tsx +1 -19
  179. package/src/route-content-wrapper.tsx +7 -72
  180. package/src/route-definition/dsl-helpers.ts +437 -274
  181. package/src/route-definition/helper-factories.ts +29 -139
  182. package/src/route-definition/helpers-types.ts +113 -37
  183. package/src/route-definition/index.ts +3 -0
  184. package/src/route-definition/redirect.ts +52 -10
  185. package/src/route-definition/resolve-handler-use.ts +161 -0
  186. package/src/route-definition/use-item-types.ts +32 -0
  187. package/src/route-map-builder.ts +7 -17
  188. package/src/route-types.ts +37 -41
  189. package/src/router/basename.ts +14 -0
  190. package/src/router/content-negotiation.ts +108 -9
  191. package/src/router/error-handling.ts +13 -17
  192. package/src/router/find-match.ts +45 -22
  193. package/src/router/handler-context.ts +83 -41
  194. package/src/router/intercept-resolution.ts +25 -23
  195. package/src/router/lazy-includes.ts +19 -53
  196. package/src/router/loader-resolution.ts +213 -30
  197. package/src/router/logging.ts +5 -8
  198. package/src/router/manifest.ts +49 -45
  199. package/src/router/match-api.ts +120 -204
  200. package/src/router/match-context.ts +0 -22
  201. package/src/router/match-handlers.ts +58 -58
  202. package/src/router/match-middleware/background-revalidation.ts +27 -6
  203. package/src/router/match-middleware/cache-lookup.ts +205 -249
  204. package/src/router/match-middleware/cache-store.ts +45 -32
  205. package/src/router/match-middleware/intercept-resolution.ts +8 -28
  206. package/src/router/match-middleware/segment-resolution.ts +52 -18
  207. package/src/router/match-pipelines.ts +1 -42
  208. package/src/router/match-result.ts +104 -40
  209. package/src/router/metrics.ts +5 -34
  210. package/src/router/middleware-types.ts +13 -142
  211. package/src/router/middleware.ts +173 -143
  212. package/src/router/navigation-snapshot.ts +131 -0
  213. package/src/router/params-util.ts +23 -0
  214. package/src/router/pattern-matching.ts +109 -63
  215. package/src/router/prerender-match.ts +190 -54
  216. package/src/router/preview-match.ts +32 -102
  217. package/src/router/request-classification.ts +276 -0
  218. package/src/router/revalidation.ts +63 -55
  219. package/src/router/route-snapshot.ts +244 -0
  220. package/src/router/router-context.ts +6 -28
  221. package/src/router/router-interfaces.ts +100 -35
  222. package/src/router/router-options.ts +91 -11
  223. package/src/router/router-registry.ts +2 -5
  224. package/src/router/segment-resolution/fresh.ts +242 -75
  225. package/src/router/segment-resolution/helpers.ts +63 -24
  226. package/src/router/segment-resolution/loader-cache.ts +41 -37
  227. package/src/router/segment-resolution/revalidation.ts +456 -372
  228. package/src/router/segment-resolution/static-store.ts +19 -5
  229. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  230. package/src/router/segment-resolution/view-transition-default.ts +36 -0
  231. package/src/router/segment-resolution.ts +4 -1
  232. package/src/router/segment-wrappers.ts +2 -3
  233. package/src/router/state-cookie-name.ts +33 -0
  234. package/src/router/substitute-pattern-params.ts +56 -0
  235. package/src/router/telemetry-otel.ts +0 -20
  236. package/src/router/telemetry.ts +96 -19
  237. package/src/router/timeout.ts +0 -20
  238. package/src/router/trie-matching.ts +91 -46
  239. package/src/router/types.ts +10 -63
  240. package/src/router/url-params.ts +44 -0
  241. package/src/router.ts +134 -43
  242. package/src/rsc/handler-context.ts +3 -2
  243. package/src/rsc/handler.ts +492 -383
  244. package/src/rsc/helpers.ts +162 -46
  245. package/src/rsc/index.ts +1 -1
  246. package/src/rsc/json-route-result.ts +38 -0
  247. package/src/rsc/loader-fetch.ts +23 -3
  248. package/src/rsc/manifest-init.ts +33 -42
  249. package/src/rsc/origin-guard.ts +39 -25
  250. package/src/rsc/progressive-enhancement.ts +30 -3
  251. package/src/rsc/redirect-guard.ts +99 -0
  252. package/src/rsc/response-error.ts +79 -12
  253. package/src/rsc/response-route-handler.ts +90 -63
  254. package/src/rsc/rsc-rendering.ts +56 -54
  255. package/src/rsc/runtime-warnings.ts +23 -10
  256. package/src/rsc/server-action.ts +74 -67
  257. package/src/rsc/ssr-setup.ts +18 -2
  258. package/src/rsc/types.ts +25 -6
  259. package/src/runtime-env.ts +18 -0
  260. package/src/search-params.ts +4 -20
  261. package/src/segment-content-promise.ts +67 -0
  262. package/src/segment-loader-promise.ts +134 -0
  263. package/src/segment-system.tsx +272 -129
  264. package/src/serialize.ts +243 -0
  265. package/src/server/context.ts +309 -61
  266. package/src/server/cookie-store.ts +80 -5
  267. package/src/server/handle-store.ts +26 -24
  268. package/src/server/loader-registry.ts +10 -28
  269. package/src/server/request-context.ts +338 -126
  270. package/src/ssr/index.tsx +23 -15
  271. package/src/static-handler.ts +27 -18
  272. package/src/testing/cache-status.ts +162 -0
  273. package/src/testing/collect-handle.ts +40 -0
  274. package/src/testing/dispatch.ts +618 -0
  275. package/src/testing/dom.entry.ts +22 -0
  276. package/src/testing/e2e/fixture.ts +188 -0
  277. package/src/testing/e2e/index.ts +128 -0
  278. package/src/testing/e2e/matchers.ts +35 -0
  279. package/src/testing/e2e/page-helpers.ts +272 -0
  280. package/src/testing/e2e/parity.ts +387 -0
  281. package/src/testing/e2e/server.ts +195 -0
  282. package/src/testing/flight-matchers.ts +97 -0
  283. package/src/testing/flight-normalize.ts +11 -0
  284. package/src/testing/flight-runtime.d.ts +57 -0
  285. package/src/testing/flight-tree.ts +682 -0
  286. package/src/testing/flight.entry.ts +52 -0
  287. package/src/testing/flight.ts +232 -0
  288. package/src/testing/generated-routes.ts +183 -0
  289. package/src/testing/index.ts +99 -0
  290. package/src/testing/internal/context.ts +348 -0
  291. package/src/testing/internal/flight-client-globals.ts +30 -0
  292. package/src/testing/internal/seed-vars.ts +54 -0
  293. package/src/testing/render-handler.ts +330 -0
  294. package/src/testing/render-route.tsx +566 -0
  295. package/src/testing/run-loader.ts +378 -0
  296. package/src/testing/run-middleware.ts +205 -0
  297. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  298. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  299. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  300. package/src/testing/vitest-stubs/version.ts +5 -0
  301. package/src/testing/vitest.ts +305 -0
  302. package/src/theme/ThemeProvider.tsx +0 -52
  303. package/src/theme/ThemeScript.tsx +0 -6
  304. package/src/theme/constants.ts +0 -12
  305. package/src/theme/index.ts +0 -7
  306. package/src/theme/theme-context.ts +1 -5
  307. package/src/theme/theme-script.ts +0 -14
  308. package/src/theme/use-theme.ts +0 -3
  309. package/src/types/boundaries.ts +0 -35
  310. package/src/types/cache-types.ts +17 -8
  311. package/src/types/error-types.ts +30 -90
  312. package/src/types/global-namespace.ts +54 -41
  313. package/src/types/handler-context.ts +233 -81
  314. package/src/types/index.ts +1 -10
  315. package/src/types/loader-types.ts +44 -15
  316. package/src/types/request-scope.ts +107 -0
  317. package/src/types/route-config.ts +6 -50
  318. package/src/types/route-entry.ts +19 -7
  319. package/src/types/segments.ts +37 -14
  320. package/src/urls/include-helper.ts +33 -70
  321. package/src/urls/index.ts +1 -11
  322. package/src/urls/path-helper-types.ts +58 -11
  323. package/src/urls/path-helper.ts +57 -111
  324. package/src/urls/pattern-types.ts +48 -19
  325. package/src/urls/response-types.ts +25 -22
  326. package/src/urls/type-extraction.ts +58 -139
  327. package/src/urls/urls-function.ts +1 -18
  328. package/src/use-loader.tsx +346 -89
  329. package/src/vite/debug.ts +185 -0
  330. package/src/vite/discovery/bundle-postprocess.ts +36 -38
  331. package/src/vite/discovery/discover-routers.ts +130 -85
  332. package/src/vite/discovery/discovery-errors.ts +194 -0
  333. package/src/vite/discovery/gate-state.ts +171 -0
  334. package/src/vite/discovery/prerender-collection.ts +192 -99
  335. package/src/vite/discovery/route-types-writer.ts +40 -84
  336. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  337. package/src/vite/discovery/state.ts +51 -6
  338. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  339. package/src/vite/index.ts +8 -0
  340. package/src/vite/plugin-types.ts +187 -69
  341. package/src/vite/plugins/cjs-to-esm.ts +8 -18
  342. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  343. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  344. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  345. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  346. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  347. package/src/vite/plugins/expose-action-id.ts +49 -98
  348. package/src/vite/plugins/expose-id-utils.ts +11 -50
  349. package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
  350. package/src/vite/plugins/expose-ids/handler-transform.ts +10 -48
  351. package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
  352. package/src/vite/plugins/expose-ids/router-transform.ts +20 -16
  353. package/src/vite/plugins/expose-internal-ids.ts +554 -317
  354. package/src/vite/plugins/performance-tracks.ts +89 -0
  355. package/src/vite/plugins/refresh-cmd.ts +89 -27
  356. package/src/vite/plugins/use-cache-transform.ts +73 -83
  357. package/src/vite/plugins/vercel-output.ts +258 -0
  358. package/src/vite/plugins/version-injector.ts +21 -25
  359. package/src/vite/plugins/version-plugin.ts +41 -20
  360. package/src/vite/plugins/virtual-entries.ts +2 -17
  361. package/src/vite/rango.ts +257 -289
  362. package/src/vite/router-discovery.ts +930 -140
  363. package/src/vite/utils/ast-handler-extract.ts +15 -31
  364. package/src/vite/utils/banner.ts +4 -4
  365. package/src/vite/utils/bundle-analysis.ts +10 -15
  366. package/src/vite/utils/client-chunks.ts +184 -0
  367. package/src/vite/utils/forward-user-plugins.ts +171 -0
  368. package/src/vite/utils/manifest-utils.ts +4 -59
  369. package/src/vite/utils/package-resolution.ts +20 -52
  370. package/src/vite/utils/prerender-utils.ts +27 -29
  371. package/src/vite/utils/shared-utils.ts +92 -42
  372. package/src/browser/action-response-classifier.ts +0 -99
  373. package/src/browser/react/use-client-cache.ts +0 -58
  374. package/src/browser/shallow.ts +0 -40
  375. package/src/handles/index.ts +0 -7
  376. package/src/router/middleware-cookies.ts +0 -55
@@ -2,17 +2,16 @@ 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, EnvCompatible } from "../urls/pattern-types.js";
5
6
  import type { EntryData } from "../server/context";
6
7
  import type { ErrorInfo, MatchResult } from "../types";
7
8
  import type { NonceProvider } from "../rsc/types.js";
8
9
  import type { ExecutionContext } from "../server/request-context.js";
9
- import type {
10
- SerializedSegmentData,
11
- SegmentHandleData,
12
- } from "../cache/types.js";
10
+ import type { SerializedSegmentData } from "../cache/types.js";
13
11
  import type { MiddlewareEntry, MiddlewareFn } from "./middleware.js";
12
+ import type { ExtractParams } from "../types/route-config.js";
14
13
  import { RSC_ROUTER_BRAND } from "./router-registry.js";
15
- import type { RSCRouterOptions, RootLayoutProps } from "./router-options.js";
14
+ import type { RangoOptions, RootLayoutProps } from "./router-options.js";
16
15
  import type { DefaultVars } from "../types/global-namespace.js";
17
16
  import type { ResolvedTimeouts, OnTimeoutCallback } from "./timeout.js";
18
17
 
@@ -48,16 +47,16 @@ type MergeRoutesWithResponses<
48
47
  };
49
48
 
50
49
  /**
51
- * Public RSC Router interface — the user-facing API surface.
50
+ * Public Rango router interface — the user-facing API surface.
52
51
  *
53
52
  * Users interact with this type when building and using routers.
54
- * Internal framework code uses RSCRouterInternal (via toInternal()) to access
53
+ * Internal framework code uses RangoInternal (via toInternal()) to access
55
54
  * matching, build-time, and configuration members that are not part of the
56
55
  * public contract.
57
56
  *
58
57
  * TRoutes accumulates all registered route types through the builder chain.
59
58
  */
60
- export interface RSCRouter<
59
+ export interface Rango<
61
60
  TEnv = any,
62
61
  TRoutes extends Record<string, unknown> = Record<string, string>,
63
62
  > {
@@ -68,23 +67,36 @@ export interface RSCRouter<
68
67
  readonly id: string;
69
68
 
70
69
  /**
71
- * Register routes using URL patterns from urls()
70
+ * URL prefix applied to all routes. Undefined when no basename is configured.
71
+ */
72
+ readonly basename: string | undefined;
73
+
74
+ /**
75
+ * Register routes using URL patterns from urls() or a builder function
72
76
  *
73
77
  * @example
74
78
  * ```typescript
75
- * createRouter({})
76
- * .routes(urlpatterns)
79
+ * // With urls()
80
+ * createRouter({}).routes(urlpatterns)
81
+ *
82
+ * // With builder function (urls() is implicit)
83
+ * createRouter({}).routes(({ path, layout }) => [
84
+ * layout(RootLayout, () => [
85
+ * path("/", HomePage),
86
+ * ]),
87
+ * ])
77
88
  * ```
78
89
  */
79
- routes<T extends UrlPatterns<TEnv, any>>(
80
- patterns: T,
81
- ): RSCRouter<
90
+ routes<T extends UrlPatterns<any, any, any>>(
91
+ patterns: T & EnvCompatible<T, TEnv>,
92
+ ): Rango<
82
93
  TEnv,
83
94
  TRoutes &
84
95
  (NonNullable<T["_routes"]> extends Record<string, unknown>
85
96
  ? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
86
97
  : Record<string, string>)
87
98
  >;
99
+ routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
88
100
 
89
101
  /**
90
102
  * Add global middleware that runs on all routes
@@ -94,13 +106,18 @@ export interface RSCRouter<
94
106
  * createRouter({ document: RootLayout })
95
107
  * .use(loggerMiddleware) // All routes
96
108
  * .use("/api/*", rateLimiter) // Pattern match
109
+ * .use("/users/:id", (ctx) => {}) // ctx.params.id is typed
97
110
  * .routes(urlpatterns)
98
111
  * ```
99
112
  */
113
+ use<Pattern extends string>(
114
+ pattern: Pattern,
115
+ middleware: MiddlewareFn<TEnv, ExtractParams<Pattern>>,
116
+ ): Rango<TEnv, TRoutes>;
100
117
  use(
101
118
  patternOrMiddleware: string | MiddlewareFn<TEnv>,
102
119
  middleware?: MiddlewareFn<TEnv>,
103
- ): RSCRouter<TEnv, TRoutes>;
120
+ ): Rango<TEnv, TRoutes>;
104
121
 
105
122
  /**
106
123
  * Type-safe URL builder for registered routes
@@ -127,7 +144,7 @@ export interface RSCRouter<
127
144
  * type AppRoutes = typeof _router.routeMap;
128
145
  *
129
146
  * declare global {
130
- * namespace RSCRouter {
147
+ * namespace Rango {
131
148
  * interface RegisteredRoutes extends AppRoutes {}
132
149
  * }
133
150
  * }
@@ -163,16 +180,16 @@ export interface RSCRouter<
163
180
  }
164
181
 
165
182
  /**
166
- * Internal RSC Router interface — the full framework-facing API.
183
+ * Internal Rango router interface — the full framework-facing API.
167
184
  *
168
185
  * This type includes all members used by the Vite plugin, RSC handler,
169
186
  * pre-rendering pipeline, and other framework internals. It is NOT exported
170
187
  * from the public package API.
171
188
  *
172
- * Use toInternal(router) to assert a public RSCRouter into this type
189
+ * Use toInternal(router) to assert a public Rango into this type
173
190
  * at the boundary where framework code receives a user-provided router.
174
191
  */
175
- export interface RSCRouterInternal<
192
+ export interface RangoInternal<
176
193
  TEnv = any,
177
194
  TRoutes extends Record<string, unknown> = Record<string, string>,
178
195
  > {
@@ -188,26 +205,40 @@ export interface RSCRouterInternal<
188
205
  */
189
206
  readonly id: string;
190
207
 
208
+ /** URL prefix applied to all routes. */
209
+ readonly basename: string | undefined;
210
+
191
211
  /**
192
- * Register routes using URL patterns from urls()
193
- */
194
- routes<T extends UrlPatterns<TEnv, any>>(
195
- patterns: T,
196
- ): RSCRouter<
212
+ * Register routes using URL patterns from urls() or a builder function.
213
+ *
214
+ * Env compatibility is checked by EnvCompatible: an env-agnostic urls() block
215
+ * (its env is `unknown` — e.g. a shared module, or an app that does not augment
216
+ * `Rango.Env`) attaches to any router, while a urls<TEnv>() block carrying a
217
+ * concrete env is accepted only when this router's `TEnv` satisfies it. So a
218
+ * `urls<{ DB }>()` cannot be mounted on a `createRouter<{}>()`.
219
+ */
220
+ routes<T extends UrlPatterns<any, any, any>>(
221
+ patterns: T & EnvCompatible<T, TEnv>,
222
+ ): Rango<
197
223
  TEnv,
198
224
  TRoutes &
199
225
  (NonNullable<T["_routes"]> extends Record<string, unknown>
200
226
  ? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
201
227
  : Record<string, string>)
202
228
  >;
229
+ routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
203
230
 
204
231
  /**
205
232
  * Add global middleware that runs on all routes
206
233
  */
234
+ use<Pattern extends string>(
235
+ pattern: Pattern,
236
+ middleware: MiddlewareFn<TEnv, ExtractParams<Pattern>>,
237
+ ): Rango<TEnv, TRoutes>;
207
238
  use(
208
239
  patternOrMiddleware: string | MiddlewareFn<TEnv>,
209
240
  middleware?: MiddlewareFn<TEnv>,
210
- ): RSCRouter<TEnv, TRoutes>;
241
+ ): Rango<TEnv, TRoutes>;
211
242
 
212
243
  /**
213
244
  * Type-safe URL builder for registered routes
@@ -229,17 +260,17 @@ export interface RSCRouterInternal<
229
260
  * Error callback for monitoring/alerting
230
261
  * Called when errors occur in loaders, actions, or routes
231
262
  */
232
- readonly onError?: RSCRouterOptions<TEnv>["onError"];
263
+ readonly onError?: RangoOptions<TEnv>["onError"];
233
264
 
234
265
  /**
235
266
  * Cache configuration
236
267
  */
237
- readonly cache?: RSCRouterOptions<TEnv>["cache"];
268
+ readonly cache?: RangoOptions<TEnv>["cache"];
238
269
 
239
270
  /**
240
271
  * Not found component to render when no route matches
241
272
  */
242
- readonly notFound?: RSCRouterOptions<TEnv>["notFound"];
273
+ readonly notFound?: RangoOptions<TEnv>["notFound"];
243
274
 
244
275
  /**
245
276
  * Resolved theme configuration (null if theme not enabled)
@@ -269,6 +300,13 @@ export interface RSCRouterInternal<
269
300
  */
270
301
  readonly prefetchCacheTTL: number;
271
302
 
303
+ /**
304
+ * Resolved rango state cookie name (`{prefix}_{routerId}`), composed once at
305
+ * router init and shipped to the client in payload metadata. The server-side
306
+ * cookie writer reads it from here; the client reads it from metadata.
307
+ */
308
+ readonly resolvedStateCookieName: string;
309
+
272
310
  /**
273
311
  * Whether connection warmup is enabled.
274
312
  * When true, the client sends HEAD /?_rsc_warmup after idle periods
@@ -338,6 +376,20 @@ export interface RSCRouterInternal<
338
376
  */
339
377
  readonly __sourceFile?: string;
340
378
 
379
+ /** @internal basename for runtime manifest generation */
380
+ readonly __basename?: string;
381
+
382
+ /**
383
+ * @internal Router-level error/notFound fallbacks (`createRouter` options),
384
+ * exposed for the build-time clientChunks discovery so a `"use client"`
385
+ * default boundary is routed into the dedicated `app-fallback` chunk. Unlike
386
+ * the route-tree `errorBoundary()`/`notFoundBoundary()` helpers these never
387
+ * land in `EntryData`, so they are read directly off the router instance.
388
+ */
389
+ readonly __defaultErrorBoundary?: RangoOptions<TEnv>["defaultErrorBoundary"];
390
+ readonly __defaultNotFoundBoundary?: RangoOptions<TEnv>["defaultNotFoundBoundary"];
391
+ readonly __notFound?: RangoOptions<TEnv>["notFound"];
392
+
341
393
  match(
342
394
  request: Request,
343
395
  input?: RouterRequestInput<TEnv>,
@@ -353,13 +405,17 @@ export interface RSCRouterInternal<
353
405
  params: Record<string, string>,
354
406
  buildVars?: Record<string, any>,
355
407
  isPassthroughRoute?: boolean,
408
+ buildEnv?: any,
409
+ devMode?: boolean,
356
410
  ): Promise<{
357
411
  segments: SerializedSegmentData[];
358
- handles: Record<string, SegmentHandleData>;
412
+ /** RSC-encoded handle map ("" when none) — see handle-snapshot.ts. */
413
+ handles: string;
359
414
  routeName: string;
360
415
  params: Record<string, string>;
361
416
  interceptSegments?: SerializedSegmentData[];
362
- interceptHandles?: Record<string, SegmentHandleData>;
417
+ /** RSC-encoded MERGED (main + intercept) handle map for the intercept artifact. */
418
+ interceptHandles?: string;
363
419
  passthrough?: true;
364
420
  } | null>;
365
421
 
@@ -371,7 +427,9 @@ export interface RSCRouterInternal<
371
427
  handler: Function,
372
428
  handlerId: string,
373
429
  routeName?: string,
374
- ): Promise<{ encoded: string; handles: Record<string, unknown[]> } | null>;
430
+ buildEnv?: any,
431
+ devMode?: boolean,
432
+ ): Promise<{ encoded: string; handles: string } | null>;
375
433
 
376
434
  /**
377
435
  * Preview match - returns route middleware without segment resolution.
@@ -424,6 +482,13 @@ export interface RSCRouterInternal<
424
482
  segmentType?: ErrorInfo["segmentType"],
425
483
  ): Promise<MatchResult | null>;
426
484
 
485
+ /**
486
+ * Low-level route matching function.
487
+ * Used by classifyRequest() for request classification without
488
+ * entering the full match pipeline.
489
+ */
490
+ findMatch(pathname: string, metricsStore?: any): any;
491
+
427
492
  /**
428
493
  * Debug utility to serialize the manifest for inspection
429
494
  * Returns a JSON-friendly representation of all routes and layouts
@@ -437,16 +502,16 @@ export interface RSCRouterInternal<
437
502
  }
438
503
 
439
504
  /**
440
- * Assert a public RSCRouter into the internal type.
505
+ * Assert a public Rango into the internal type.
441
506
  *
442
507
  * Use this at the boundary where framework code receives a user-provided
443
508
  * router and needs access to internal members (match, config, build-time).
444
509
  * The cast is safe because createRouter() always produces an object that
445
- * satisfies RSCRouterInternal; the public type is just a narrower view.
510
+ * satisfies RangoInternal; the public type is just a narrower view.
446
511
  */
447
512
  export function toInternal<
448
513
  TEnv = any,
449
514
  TRoutes extends Record<string, unknown> = Record<string, string>,
450
- >(router: RSCRouter<TEnv, TRoutes>): RSCRouterInternal<TEnv, TRoutes> {
451
- return router as RSCRouterInternal<TEnv, TRoutes>;
515
+ >(router: Rango<TEnv, TRoutes>): RangoInternal<TEnv, TRoutes> {
516
+ return router as RangoInternal<TEnv, TRoutes>;
452
517
  }
@@ -8,6 +8,7 @@ import type {
8
8
  import type { NonceProvider } from "../rsc/types.js";
9
9
  import type { ExecutionContext } from "../server/request-context.js";
10
10
  import type { UrlPatterns } from "../urls.js";
11
+ import type { UrlBuilder } from "../urls/pattern-types.js";
11
12
  import type { NamedRouteEntry } from "./content-negotiation.js";
12
13
  import type { TelemetrySink } from "./telemetry.js";
13
14
  import type { RouterTimeouts, OnTimeoutCallback } from "./timeout.js";
@@ -72,7 +73,7 @@ export interface RootLayoutProps {
72
73
  /**
73
74
  * Router configuration options
74
75
  */
75
- export interface RSCRouterOptions<TEnv = any> {
76
+ export interface RangoOptions<TEnv = any> {
76
77
  /**
77
78
  * Unique identifier for this router instance.
78
79
  * Used to namespace static output files and route maps.
@@ -95,6 +96,28 @@ export interface RSCRouterOptions<TEnv = any> {
95
96
  */
96
97
  $$sourceFile?: string;
97
98
 
99
+ /**
100
+ * URL prefix applied to all routes registered with this router.
101
+ *
102
+ * Useful when the app is served under a sub-path (e.g. `/admin` or `/v2`).
103
+ * All `path()` patterns are automatically prefixed and `reverse()` returns
104
+ * full paths including the basename. Route names are NOT prefixed.
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const router = createRouter({
109
+ * basename: "/admin",
110
+ * }).routes(({ path }) => [
111
+ * path("/", Dashboard, { name: "home" }), // matches /admin
112
+ * path("/users", Users, { name: "users" }), // matches /admin/users
113
+ * ]);
114
+ *
115
+ * router.reverse("home"); // "/admin"
116
+ * router.reverse("users"); // "/admin/users"
117
+ * ```
118
+ */
119
+ basename?: string;
120
+
98
121
  /**
99
122
  * Enable performance metrics collection
100
123
  * When enabled, metrics are output to console and available via Server-Timing header
@@ -109,6 +132,21 @@ export interface RSCRouterOptions<TEnv = any> {
109
132
  */
110
133
  allowDebugManifest?: boolean;
111
134
 
135
+ /**
136
+ * DEVELOPMENT/TEST ONLY. Emit an `X-Rango-Cache` response header describing
137
+ * the cache status of the matched route, for use by testing primitives such
138
+ * as `assertCacheStatus`.
139
+ *
140
+ * Defaults to `false`. When neither this option nor the
141
+ * `RANGO_TEST_SIGNALS=1` environment flag is set, NO header is emitted and
142
+ * router output is byte-identical to the default.
143
+ *
144
+ * The header encodes per-segment (v1: coarse route-level) status keyed by the
145
+ * route NAME, e.g. `X-Rango-Cache: product.detail=hit`. Do NOT enable in
146
+ * production — it exposes internal cache decisions.
147
+ */
148
+ debugCacheSignal?: boolean;
149
+
112
150
  /**
113
151
  * Document component that wraps the entire application.
114
152
  *
@@ -335,27 +373,54 @@ export interface RSCRouterOptions<TEnv = any> {
335
373
  theme?: import("../theme/types.js").ThemeConfig | true;
336
374
 
337
375
  /**
338
- * URL patterns to register with the router.
376
+ * Default for whether the router wraps `transition()` segments in its own
377
+ * React `<ViewTransition>` boundary (experimental React only).
378
+ *
379
+ * - "auto" (default): every route/layout that opts in via `transition()`
380
+ * gets a router-owned cross-fade.
381
+ * - false: the router never places its own boundary. Routes that use
382
+ * `transition()` still drive navigation through startTransition (so loaders
383
+ * hold instead of flashing a skeleton) and still let consumer-placed
384
+ * `<ViewTransition>` elements animate — the router just contributes no
385
+ * cross-fade of its own. This is the "router triggers, you place the
386
+ * transitions" model.
339
387
  *
340
- * Alternative to calling `.routes()` method - allows passing patterns
341
- * directly in the config for a more concise setup.
388
+ * A per-segment `transition({ viewTransition })` overrides this default.
342
389
  *
343
390
  * @example
344
391
  * ```typescript
345
- * import { urls } from "@rangojs/router/server";
392
+ * // App-wide: drive + hold, but never auto-wrap. Place <ViewTransition>
393
+ * // yourself in components where you want a morph.
394
+ * const router = createRouter<AppEnv>({ viewTransition: false });
395
+ * ```
396
+ */
397
+ viewTransition?: "auto" | false;
398
+
399
+ /**
400
+ * URL patterns to register with the router.
346
401
  *
347
- * const urlpatterns = urls(({ path, layout }) => [
348
- * path("/", HomePage, { name: "home" }),
349
- * path("/about", AboutPage, { name: "about" }),
350
- * ]);
402
+ * Accepts either a `UrlPatterns` object from `urls()` or a builder function
403
+ * directly (urls() is called implicitly).
351
404
  *
352
- * const router = createRouter<AppEnv>({
405
+ * @example
406
+ * ```typescript
407
+ * // With urls()
408
+ * createRouter<AppEnv>({
353
409
  * document: Document,
354
410
  * urls: urlpatterns,
355
411
  * });
412
+ *
413
+ * // With builder function
414
+ * createRouter<AppEnv>({
415
+ * document: Document,
416
+ * urls: ({ path }) => [
417
+ * path("/", HomePage, { name: "home" }),
418
+ * path("/about", AboutPage, { name: "about" }),
419
+ * ],
420
+ * });
356
421
  * ```
357
422
  */
358
- urls?: UrlPatterns<TEnv, any>;
423
+ urls?: UrlPatterns<TEnv, any> | UrlBuilder<TEnv>;
359
424
 
360
425
  /**
361
426
  * Injected by the Vite transform at compile time.
@@ -431,6 +496,21 @@ export interface RSCRouterOptions<TEnv = any> {
431
496
  */
432
497
  prefetchCacheTTL?: number | false;
433
498
 
499
+ /**
500
+ * Prefix for the rango state cookie name. The resolved name is
501
+ * `{prefix}_{routerId}`; the prefix is sanitized to cookie-name-safe
502
+ * characters (`[A-Za-z0-9-]`) and an empty result falls back to the default.
503
+ *
504
+ * The rango state cookie keys the client's prefetch / HTTP caches. Overriding
505
+ * the prefix lets you align it with cookie-naming policies or consent-manager
506
+ * classification lists, or avoid colliding with an existing `rango-state`
507
+ * cookie. It is not a full-name override: the `_{routerId}` suffix is what
508
+ * keeps sibling apps on one origin from clobbering each other's state.
509
+ *
510
+ * @default "rango-state"
511
+ */
512
+ stateCookiePrefix?: string;
513
+
434
514
  /**
435
515
  * Enable connection warmup to keep TCP+TLS alive after idle periods.
436
516
  *
@@ -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