@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
package/src/router.ts CHANGED
@@ -1,9 +1,6 @@
1
1
  import { type ReactNode } from "react";
2
2
  import { createCacheScope } from "./cache/cache-scope.js";
3
- import {
4
- setCacheProfiles,
5
- resolveCacheProfiles,
6
- } from "./cache/profile-registry.js";
3
+ import { resolveCacheProfiles } from "./cache/profile-registry.js";
7
4
  import { isCachedFunction } from "./cache/taint.js";
8
5
  import { assertClientComponent } from "./component-utils.js";
9
6
  import { DefaultDocument } from "./components/DefaultDocument.js";
@@ -19,11 +16,13 @@ import {
19
16
  import MapRootLayout from "./server/root-layout.js";
20
17
  import type { AllUseItems } from "./route-types.js";
21
18
  import type { UrlPatterns } from "./urls.js";
19
+ import type { UrlBuilder } from "./urls/pattern-types.js";
20
+ import { urls } from "./urls.js";
21
+ import { buildPrecomputedByPrefix } from "./build/prefix-tree-utils.js";
22
22
  import {
23
- EntryData,
24
- InterceptSelectorContext,
23
+ type EntryData,
25
24
  getContext,
26
- RSCRouterContext,
25
+ RangoContext,
27
26
  type MetricsStore,
28
27
  } from "./server/context";
29
28
  import { createHandleStore, type HandleStore } from "./server/handle-store.js";
@@ -55,6 +54,7 @@ import { buildDebugManifest } from "./router/debug-manifest.js";
55
54
 
56
55
  import type { SegmentResolutionDeps, MatchApiDeps } from "./router/types.js";
57
56
  import { createHandlerContext } from "./router/handler-context.js";
57
+ import { normalizeBasename } from "./router/basename.js";
58
58
  import {
59
59
  setupLoaderAccess,
60
60
  setupLoaderAccessSilent,
@@ -69,6 +69,7 @@ import {
69
69
  } from "./router/middleware.js";
70
70
  import {
71
71
  extractStaticPrefix,
72
+ joinPrefix,
72
73
  traverseBack,
73
74
  } from "./router/pattern-matching.js";
74
75
  import { resolveSink, safeEmit, getRequestId } from "./router/telemetry.js";
@@ -89,13 +90,10 @@ import {
89
90
  RouterRegistry,
90
91
  nextRouterAutoId,
91
92
  } from "./router/router-registry.js";
93
+ import type { RangoOptions, RootLayoutProps } from "./router/router-options.js";
92
94
  import type {
93
- RSCRouterOptions,
94
- RootLayoutProps,
95
- } from "./router/router-options.js";
96
- import type {
97
- RSCRouter,
98
- RSCRouterInternal,
95
+ Rango,
96
+ RangoInternal,
99
97
  RouterRequestInput,
100
98
  } from "./router/router-interfaces.js";
101
99
 
@@ -110,29 +108,31 @@ import {
110
108
  matchForPrerender as _matchForPrerender,
111
109
  renderStaticSegment as _renderStaticSegment,
112
110
  } from "./router/prerender-match.js";
111
+ import { resolveStateCookieName } from "./router/state-cookie-name.js";
113
112
 
114
113
  // Re-export public types and values from extracted modules
115
114
  export { RSC_ROUTER_BRAND, RouterRegistry } from "./router/router-registry.js";
116
115
  export type {
117
- RSCRouterOptions,
116
+ RangoOptions,
118
117
  RootLayoutProps,
119
118
  SSRStreamMode,
120
119
  SSROptions,
121
120
  ResolveStreamingContext,
122
121
  } from "./router/router-options.js";
123
122
  export type {
124
- RSCRouter,
125
- RSCRouterInternal,
123
+ Rango,
124
+ RangoInternal,
126
125
  RouterRequestInput,
127
126
  } from "./router/router-interfaces.js";
128
127
  export { toInternal } from "./router/router-interfaces.js";
129
128
 
130
129
  export function createRouter<TEnv = any>(
131
- options: RSCRouterOptions<TEnv> = {},
132
- ): RSCRouter<TEnv, {}> {
130
+ options: RangoOptions<TEnv> = {},
131
+ ): Rango<TEnv, {}> {
133
132
  const {
134
133
  id: userProvidedId,
135
134
  $$id: injectedId,
135
+ basename: basenameOption,
136
136
  debugPerformance = false,
137
137
  document: documentOption,
138
138
  defaultErrorBoundary,
@@ -148,6 +148,7 @@ export function createRouter<TEnv = any>(
148
148
  nonce,
149
149
  version,
150
150
  prefetchCacheTTL: prefetchCacheTTLOption,
151
+ stateCookiePrefix: stateCookiePrefixOption,
151
152
  warmup: warmupOption,
152
153
  allowDebugManifest: allowDebugManifestOption = false,
153
154
  telemetry: telemetrySink,
@@ -156,16 +157,31 @@ export function createRouter<TEnv = any>(
156
157
  timeouts: timeoutsOption,
157
158
  onTimeout,
158
159
  originCheck: originCheckOption,
160
+ viewTransition: viewTransitionOption = "auto",
161
+ debugCacheSignal: debugCacheSignalOption = false,
159
162
  } = options;
160
163
 
164
+ // Debug cache signal gate (DEVELOPMENT/TEST ONLY). Enabled by the
165
+ // debugCacheSignal option OR the RANGO_TEST_SIGNALS=1 env flag. When off,
166
+ // no X-Rango-Cache header is emitted and output is byte-identical.
167
+ const cacheSignalEnabled =
168
+ debugCacheSignalOption ||
169
+ (typeof process !== "undefined" &&
170
+ (process as { env?: Record<string, string | undefined> }).env
171
+ ?.RANGO_TEST_SIGNALS === "1");
172
+
173
+ // Normalize basename: ensure leading slash, strip trailing slash.
174
+ // A bare "/" is equivalent to no basename. Shared with the testing
175
+ // primitives via normalizeBasename so they can never drift.
176
+ const basename = normalizeBasename(basenameOption);
177
+
161
178
  // Resolve telemetry sink (no-op when not configured)
162
179
  const telemetry = resolveSink(telemetrySink);
163
180
 
164
- // Resolve cache profiles: merge user config with guaranteed default profile.
165
- // This resolved map is both stored on the router (for per-request context)
166
- // and written to the global registry (for DSL-time cache("profileName")).
181
+ // Resolve cache profiles: merge user config with the guaranteed default
182
+ // profile. This resolved map is threaded onto each request context; the
183
+ // "use cache: <profile>" runtime path reads it request-scoped.
167
184
  const resolvedCacheProfiles = resolveCacheProfiles(cacheProfilesOption);
168
- setCacheProfiles(resolvedCacheProfiles);
169
185
 
170
186
  // Source file: prefer Vite-injected path (zero cost), fall back to
171
187
  // stack trace parsing for non-Vite environments (e.g. tests).
@@ -200,6 +216,14 @@ export function createRouter<TEnv = any>(
200
216
  const routerId =
201
217
  userProvidedId ?? injectedId ?? `router_${nextRouterAutoId()}`;
202
218
 
219
+ // Resolve the rango state cookie name once, here, so the two cookie writers
220
+ // (the client document.cookie writer and the server Set-Cookie writer)
221
+ // consume one pre-composed name and cannot drift.
222
+ const resolvedStateCookieName = resolveStateCookieName(
223
+ stateCookiePrefixOption,
224
+ routerId,
225
+ );
226
+
203
227
  // Resolve prefetch cache TTL (default: 300 seconds / 5 minutes)
204
228
  // Clamp to a non-negative integer for valid Cache-Control max-age.
205
229
  const rawTTL =
@@ -246,9 +270,14 @@ export function createRouter<TEnv = any>(
246
270
  invokeOnError(onError, error, phase, context, "Router");
247
271
  }
248
272
 
249
- // Validate document is a client component
273
+ // Validate document is a client component. Under a test runner the "use
274
+ // client" transform has not run, so a real exported document has no marker;
275
+ // allowServerInTest lets the router construct in a bare unit test (for
276
+ // dispatch / assertGeneratedRoutesMatch) while a real build still throws.
250
277
  if (documentOption !== undefined) {
251
- assertClientComponent(documentOption, "document");
278
+ assertClientComponent(documentOption, "document", {
279
+ allowServerInTest: true,
280
+ });
252
281
  }
253
282
 
254
283
  // Use default document if none provided (keeps internal name as rootLayout)
@@ -322,7 +351,6 @@ export function createRouter<TEnv = any>(
322
351
  regex,
323
352
  paramNames,
324
353
  handler,
325
- mountPrefix,
326
354
  });
327
355
  }
328
356
 
@@ -356,9 +384,11 @@ export function createRouter<TEnv = any>(
356
384
  getRouterPrecomputedEntries(routerId) ?? getPrecomputedEntries();
357
385
  if (current !== precomputedSource) {
358
386
  precomputedSource = current;
359
- precomputedByPrefix = current
360
- ? new Map(current.map((e) => [e.staticPrefix, e.routes]))
361
- : null;
387
+ // buildPrecomputedByPrefix drops any staticPrefix owned by more than one
388
+ // leaf include instead of collapsing it last-wins (which would mis-assign
389
+ // one include's routes to another's entry and 500 a valid sibling route).
390
+ // Such shared-prefix includes resolve via the handler path instead.
391
+ precomputedByPrefix = current ? buildPrecomputedByPrefix(current) : null;
362
392
  }
363
393
  return precomputedByPrefix;
364
394
  }
@@ -526,7 +556,9 @@ export function createRouter<TEnv = any>(
526
556
  trackHandler,
527
557
  findNearestErrorBoundary,
528
558
  findNearestNotFoundBoundary,
559
+ notFoundComponent: notFound,
529
560
  callOnError,
561
+ viewTransitionDefault: viewTransitionOption,
530
562
  };
531
563
 
532
564
  // Match API dependencies
@@ -560,6 +592,7 @@ export function createRouter<TEnv = any>(
560
592
  mergedRouteMap,
561
593
  nextMountIndex: () => mountIndex++,
562
594
  getPrecomputedByPrefix,
595
+ routerId,
563
596
  };
564
597
 
565
598
  function evaluateLazyEntry(entry: RouteEntry<TEnv>): void {
@@ -613,6 +646,8 @@ export function createRouter<TEnv = any>(
613
646
  params: Record<string, string>,
614
647
  buildVars?: Record<string, any>,
615
648
  isPassthroughRoute?: boolean,
649
+ buildEnv?: TEnv,
650
+ devMode?: boolean,
616
651
  ) {
617
652
  return _matchForPrerender(
618
653
  pathname,
@@ -620,6 +655,8 @@ export function createRouter<TEnv = any>(
620
655
  prerenderDeps,
621
656
  buildVars,
622
657
  isPassthroughRoute,
658
+ buildEnv,
659
+ devMode,
623
660
  );
624
661
  }
625
662
 
@@ -627,12 +664,16 @@ export function createRouter<TEnv = any>(
627
664
  handler: Function,
628
665
  handlerId: string,
629
666
  routeName?: string,
667
+ buildEnv?: TEnv,
668
+ devMode?: boolean,
630
669
  ) {
631
670
  return _renderStaticSegment<TEnv>(
632
671
  handler,
633
672
  handlerId,
634
673
  mergedRouteMap,
635
674
  routeName,
675
+ buildEnv,
676
+ devMode,
636
677
  );
637
678
  }
638
679
 
@@ -645,6 +686,7 @@ export function createRouter<TEnv = any>(
645
686
  findMatch,
646
687
  findInterceptForRoute,
647
688
  telemetry: telemetrySink,
689
+ cacheSignalEnabled,
648
690
  });
649
691
 
650
692
  const { match, matchPartial, matchError, previewMatch } = matchHandlers;
@@ -654,11 +696,18 @@ export function createRouter<TEnv = any>(
654
696
  * The type system tracks accumulated routes through the builder chain
655
697
  * Initial TRoutes is {} (empty) to avoid poisoning accumulated types with Record<string, string>
656
698
  */
657
- const router: RSCRouterInternal<TEnv, {}> = {
699
+ const router: RangoInternal<TEnv, {}> = {
658
700
  __brand: RSC_ROUTER_BRAND,
659
701
  id: routerId,
702
+ basename,
703
+
704
+ routes(patternsOrBuilder: UrlPatterns<TEnv> | UrlBuilder<TEnv>): any {
705
+ // Wrap builder functions in urls() automatically
706
+ const urlPatterns: UrlPatterns<TEnv> =
707
+ typeof patternsOrBuilder === "function"
708
+ ? (urls(patternsOrBuilder) as UrlPatterns<TEnv>)
709
+ : patternsOrBuilder;
660
710
 
661
- routes(urlPatterns: UrlPatterns<TEnv>): any {
662
711
  // Store reference for runtime manifest generation
663
712
  storedUrlPatterns = urlPatterns;
664
713
  const currentMountIndex = mountIndex++;
@@ -689,13 +738,13 @@ export function createRouter<TEnv = any>(
689
738
  errorBoundary: [],
690
739
  notFoundBoundary: [],
691
740
  layout: [],
692
- parallel: [],
741
+ parallel: {},
693
742
  intercept: [],
694
743
  loader: [],
695
744
  };
696
745
 
697
746
  let handlerResult: AllUseItems[] = [];
698
- RSCRouterContext.run(
747
+ RangoContext.run(
699
748
  {
700
749
  manifest,
701
750
  patterns: routePatterns,
@@ -706,6 +755,10 @@ export function createRouter<TEnv = any>(
706
755
  counters: {},
707
756
  mountIndex: currentMountIndex,
708
757
  cacheProfiles: resolvedCacheProfiles,
758
+ // basename sets the initial URL prefix so all path() patterns
759
+ // are registered with the prefix (e.g. "/admin" + "/users" = "/admin/users").
760
+ // No namePrefix — route names stay unprefixed.
761
+ ...(basename ? { urlPrefix: basename } : {}),
709
762
  },
710
763
  () => {
711
764
  handlerResult = urlPatterns.handler() as AllUseItems[];
@@ -725,7 +778,7 @@ export function createRouter<TEnv = any>(
725
778
  if (entry.type === "route" && entry.isPrerender) {
726
779
  if (!prerenderRouteKeys) prerenderRouteKeys = new Set();
727
780
  prerenderRouteKeys.add(name);
728
- if (entry.prerenderDef?.options?.passthrough === true) {
781
+ if (entry.isPassthrough === true) {
729
782
  if (!passthroughRouteKeys) passthroughRouteKeys = new Set();
730
783
  passthroughRouteKeys.add(name);
731
784
  }
@@ -751,6 +804,7 @@ export function createRouter<TEnv = any>(
751
804
  trailingSlash: trailingSlashConfig,
752
805
  handler: urlPatterns.handler,
753
806
  mountIndex: currentMountIndex,
807
+ routerId,
754
808
  cacheProfiles: resolvedCacheProfiles,
755
809
  ...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
756
810
  ...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
@@ -770,6 +824,7 @@ export function createRouter<TEnv = any>(
770
824
  trailingSlash: trailingSlashConfig,
771
825
  handler: urlPatterns.handler,
772
826
  mountIndex: currentMountIndex,
827
+ routerId,
773
828
  cacheProfiles: resolvedCacheProfiles,
774
829
  ...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
775
830
  ...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
@@ -801,10 +856,13 @@ export function createRouter<TEnv = any>(
801
856
 
802
857
  // Create placeholder RouteEntry for each lazy include
803
858
  for (const lazyInclude of lazyIncludes) {
804
- // Compute the full URL prefix (combining parent prefix if any)
805
- const fullPrefix = lazyInclude.context.urlPrefix
806
- ? lazyInclude.context.urlPrefix + lazyInclude.prefix
807
- : lazyInclude.prefix;
859
+ // Compute the full URL prefix (combining parent prefix if any). Use the
860
+ // slash-collapsing join so a trailing-slash parent prefix does not
861
+ // produce a double-slash staticPrefix the trie's sp can never match.
862
+ const fullPrefix = joinPrefix(
863
+ lazyInclude.context.urlPrefix,
864
+ lazyInclude.prefix,
865
+ );
808
866
 
809
867
  const lazyEntry: RouteEntry<TEnv> & { _lazyPrefix?: string } = {
810
868
  prefix: "",
@@ -813,6 +871,7 @@ export function createRouter<TEnv = any>(
813
871
  trailingSlash: trailingSlashConfig,
814
872
  handler: urlPatterns.handler,
815
873
  mountIndex: mountIndex++,
874
+ routerId,
816
875
  // Lazy evaluation fields
817
876
  lazy: true,
818
877
  lazyPatterns: lazyInclude.patterns,
@@ -851,8 +910,18 @@ export function createRouter<TEnv = any>(
851
910
  patternOrMiddleware: string | MiddlewareFn<TEnv>,
852
911
  middleware?: MiddlewareFn<TEnv>,
853
912
  ): any {
854
- // Global middleware - no mount prefix
855
- addMiddleware(patternOrMiddleware, middleware, null);
913
+ // Auto-prefix pattern with basename so router-level middleware
914
+ // patterns are router-relative (e.g. "/users/*" matches "/app/users/*").
915
+ if (basename && typeof patternOrMiddleware === "string") {
916
+ const pattern = patternOrMiddleware;
917
+ const prefixed =
918
+ pattern === "/*" || pattern === "*"
919
+ ? `${basename}/*`
920
+ : `${basename}${pattern}`;
921
+ addMiddleware(prefixed, middleware, null);
922
+ } else {
923
+ addMiddleware(patternOrMiddleware, middleware, null);
924
+ }
856
925
  return router;
857
926
  },
858
927
 
@@ -889,6 +958,10 @@ export function createRouter<TEnv = any>(
889
958
  prefetchCacheControl,
890
959
  prefetchCacheTTL,
891
960
 
961
+ // Expose the resolved rango state cookie name for the server-side writer
962
+ // (invalidateClientCache) and for shipping to the client in metadata.
963
+ resolvedStateCookieName,
964
+
892
965
  // Expose warmup enabled flag for handler and client
893
966
  warmupEnabled,
894
967
 
@@ -953,6 +1026,16 @@ export function createRouter<TEnv = any>(
953
1026
  // Expose source file for per-router type generation
954
1027
  __sourceFile,
955
1028
 
1029
+ // Expose basename for runtime manifest generation
1030
+ __basename: basename,
1031
+
1032
+ // Expose router-level boundary defaults for build-time clientChunks
1033
+ // discovery (so a "use client" default boundary lands in app-fallback).
1034
+ // These are createRouter options, never pushed onto EntryData.
1035
+ __defaultErrorBoundary: defaultErrorBoundary,
1036
+ __defaultNotFoundBoundary: defaultNotFoundBoundary,
1037
+ __notFound: notFound,
1038
+
956
1039
  // RSC request handler (lazily created on first call)
957
1040
  fetch: (() => {
958
1041
  // Handler is created on first call and reused
@@ -970,8 +1053,10 @@ export function createRouter<TEnv = any>(
970
1053
  if (!handler) {
971
1054
  // Lazy import deferred to first request to avoid dev mode issues
972
1055
  const { createRSCHandler } = await import("./rsc/handler.js");
973
- // Cast: handler.ts still accepts (request, env) will be updated
974
- // separately to accept RouterRequestInput.
1056
+ // Cast: createRSCHandler receives `router as any`, which erases TEnv
1057
+ // and infers its handler as RouterRequestInput<unknown>. Re-narrow the
1058
+ // returned handler to RouterRequestInput<TEnv> so the call below stays
1059
+ // typed. (The handler already accepts (request, RouterRequestInput).)
975
1060
  handler = createRSCHandler({
976
1061
  router: router as any,
977
1062
  cache,
@@ -986,6 +1071,10 @@ export function createRouter<TEnv = any>(
986
1071
  };
987
1072
  })(),
988
1073
 
1074
+ // Low-level route matching for request classification
1075
+ findMatch: (pathname: string, metricsStore?: any) =>
1076
+ findMatch(pathname, metricsStore),
1077
+
989
1078
  // Debug utility for manifest inspection
990
1079
  debugManifest: () => buildDebugManifest<TEnv>(routesEntries),
991
1080
  };
@@ -994,8 +1083,10 @@ export function createRouter<TEnv = any>(
994
1083
  RouterRegistry.set(routerId, router);
995
1084
 
996
1085
  // If urls option was provided, auto-register them
997
- if (urlsOption) {
998
- return router.routes(urlsOption) as RSCRouter<TEnv, {}>;
1086
+ if (typeof urlsOption === "function") {
1087
+ return router.routes(urlsOption) as Rango<TEnv, {}>;
1088
+ } else if (urlsOption) {
1089
+ return router.routes(urlsOption) as Rango<TEnv, {}>;
999
1090
  }
1000
1091
 
1001
1092
  return router;
@@ -6,14 +6,14 @@
6
6
  * RSC rendering) so they can be standalone modules without closure coupling.
7
7
  */
8
8
 
9
- import type { RSCRouterInternal } from "../router/router-interfaces.js";
9
+ import type { RangoInternal } from "../router/router-interfaces.js";
10
10
  import type { ErrorPhase } from "../types.js";
11
11
  import type { InvokeOnErrorContext } from "../router/error-handling.js";
12
12
  import type { RSCDependencies, LoadSSRModule } from "./types.js";
13
13
  import type { SSRStreamMode } from "../router/router-options.js";
14
14
 
15
15
  export interface HandlerContext<TEnv = unknown> {
16
- router: RSCRouterInternal<TEnv, any>;
16
+ router: RangoInternal<TEnv, any>;
17
17
  version: string;
18
18
  renderToReadableStream: RSCDependencies["renderToReadableStream"];
19
19
  decodeReply: RSCDependencies["decodeReply"];
@@ -31,6 +31,7 @@ export interface HandlerContext<TEnv = unknown> {
31
31
  createRedirectFlightResponse: (
32
32
  redirectUrl: string,
33
33
  locationState?: Record<string, unknown>,
34
+ external?: boolean,
34
35
  ) => Response;
35
36
 
36
37
  /**