@rangojs/router 0.0.0-experimental.eb0645d3 → 0.0.0-experimental.f1468e3c

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 (392) hide show
  1. package/AGENTS.md +8 -0
  2. package/README.md +126 -16
  3. package/dist/bin/rango.js +319 -95
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +2724 -1053
  6. package/package.json +68 -14
  7. package/skills/api-client/SKILL.md +211 -0
  8. package/skills/breadcrumbs/SKILL.md +64 -2
  9. package/skills/bundle-analysis/SKILL.md +159 -0
  10. package/skills/cache-guide/SKILL.md +224 -32
  11. package/skills/caching/SKILL.md +279 -17
  12. package/skills/composability/SKILL.md +27 -3
  13. package/skills/css/SKILL.md +76 -0
  14. package/skills/debug-manifest/SKILL.md +4 -2
  15. package/skills/document-cache/SKILL.md +78 -55
  16. package/skills/handler-use/SKILL.md +11 -9
  17. package/skills/hooks/SKILL.md +243 -29
  18. package/skills/host-router/SKILL.md +83 -23
  19. package/skills/i18n/SKILL.md +276 -0
  20. package/skills/intercept/SKILL.md +68 -19
  21. package/skills/layout/SKILL.md +13 -9
  22. package/skills/links/SKILL.md +190 -23
  23. package/skills/loader/SKILL.md +235 -9
  24. package/skills/middleware/SKILL.md +18 -10
  25. package/skills/migrate-nextjs/SKILL.md +43 -19
  26. package/skills/migrate-react-router/SKILL.md +8 -2
  27. package/skills/mime-routes/SKILL.md +28 -1
  28. package/skills/observability/SKILL.md +172 -0
  29. package/skills/parallel/SKILL.md +18 -7
  30. package/skills/prerender/SKILL.md +65 -60
  31. package/skills/rango/SKILL.md +251 -24
  32. package/skills/react-compiler/SKILL.md +168 -0
  33. package/skills/response-routes/SKILL.md +115 -48
  34. package/skills/route/SKILL.md +46 -5
  35. package/skills/router-setup/SKILL.md +30 -8
  36. package/skills/scripts/SKILL.md +179 -0
  37. package/skills/server-actions/SKILL.md +775 -0
  38. package/skills/tailwind/SKILL.md +27 -3
  39. package/skills/testing/SKILL.md +130 -0
  40. package/skills/testing/bindings.md +103 -0
  41. package/skills/testing/cache-prerender.md +127 -0
  42. package/skills/testing/client-components.md +124 -0
  43. package/skills/testing/e2e-parity.md +125 -0
  44. package/skills/testing/flight.md +91 -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 +122 -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 +123 -0
  54. package/skills/typesafety/SKILL.md +322 -29
  55. package/skills/use-cache/SKILL.md +57 -14
  56. package/skills/view-transitions/SKILL.md +337 -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 +0 -65
  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/connection-warmup.ts +134 -0
  64. package/src/browser/cookie-name.ts +140 -0
  65. package/src/browser/event-controller.ts +192 -150
  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/navigation-bridge.ts +94 -25
  70. package/src/browser/navigation-client.ts +121 -84
  71. package/src/browser/navigation-store-handle.ts +38 -0
  72. package/src/browser/navigation-store.ts +115 -67
  73. package/src/browser/navigation-transaction.ts +9 -59
  74. package/src/browser/network-error-handler.ts +34 -7
  75. package/src/browser/partial-update.ts +147 -128
  76. package/src/browser/prefetch/cache.ts +107 -56
  77. package/src/browser/prefetch/fetch.ts +204 -34
  78. package/src/browser/prefetch/queue.ts +6 -3
  79. package/src/browser/rango-state.ts +158 -76
  80. package/src/browser/react/Link.tsx +30 -7
  81. package/src/browser/react/NavigationProvider.tsx +283 -118
  82. package/src/browser/react/ScrollRestoration.tsx +10 -6
  83. package/src/browser/react/deferred-handle-resolution.ts +75 -0
  84. package/src/browser/react/filter-segment-order.ts +66 -7
  85. package/src/browser/react/index.ts +0 -48
  86. package/src/browser/react/location-state-shared.ts +178 -8
  87. package/src/browser/react/location-state.ts +39 -14
  88. package/src/browser/react/use-action.ts +6 -15
  89. package/src/browser/react/use-handle.ts +17 -14
  90. package/src/browser/react/use-href.tsx +8 -1
  91. package/src/browser/react/use-link-status.ts +33 -8
  92. package/src/browser/react/use-navigation.ts +10 -5
  93. package/src/browser/react/use-params.ts +11 -11
  94. package/src/browser/react/use-reverse.ts +106 -0
  95. package/src/browser/react/use-router.ts +25 -3
  96. package/src/browser/react/use-search-params.ts +0 -5
  97. package/src/browser/react/use-segments.ts +11 -21
  98. package/src/browser/response-adapter.ts +99 -8
  99. package/src/browser/rsc-router.tsx +91 -24
  100. package/src/browser/scroll-restoration.ts +30 -17
  101. package/src/browser/segment-structure-assert.ts +2 -2
  102. package/src/browser/server-action-bridge.ts +214 -55
  103. package/src/browser/types.ts +80 -9
  104. package/src/browser/validate-redirect-origin.ts +43 -16
  105. package/src/build/collect-fallback-refs.ts +107 -0
  106. package/src/build/generate-manifest.ts +60 -35
  107. package/src/build/generate-route-types.ts +2 -1
  108. package/src/build/index.ts +8 -2
  109. package/src/build/prefix-tree-utils.ts +123 -0
  110. package/src/build/route-trie.ts +117 -14
  111. package/src/build/route-types/ast-route-extraction.ts +15 -8
  112. package/src/build/route-types/codegen.ts +16 -5
  113. package/src/build/route-types/include-resolution.ts +117 -23
  114. package/src/build/route-types/param-extraction.ts +6 -3
  115. package/src/build/route-types/per-module-writer.ts +22 -6
  116. package/src/build/route-types/router-processing.ts +55 -28
  117. package/src/build/route-types/scan-filter.ts +1 -1
  118. package/src/build/route-types/source-scan.ts +216 -0
  119. package/src/build/runtime-discovery.ts +9 -20
  120. package/src/cache/cache-error.ts +104 -0
  121. package/src/cache/cache-key-utils.ts +29 -13
  122. package/src/cache/cache-policy.ts +108 -34
  123. package/src/cache/cache-runtime.ts +224 -41
  124. package/src/cache/cache-scope.ts +188 -82
  125. package/src/cache/cache-tag.ts +103 -0
  126. package/src/cache/cf/cf-base64.ts +33 -0
  127. package/src/cache/cf/cf-cache-constants.ts +127 -0
  128. package/src/cache/cf/cf-cache-store.ts +1989 -378
  129. package/src/cache/cf/cf-cache-types.ts +349 -0
  130. package/src/cache/cf/cf-kv-utils.ts +46 -0
  131. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  132. package/src/cache/cf/index.ts +6 -16
  133. package/src/cache/document-cache.ts +89 -21
  134. package/src/cache/handle-snapshot.ts +70 -0
  135. package/src/cache/index.ts +10 -20
  136. package/src/cache/memory-segment-store.ts +136 -37
  137. package/src/cache/profile-registry.ts +46 -31
  138. package/src/cache/read-through-swr.ts +56 -12
  139. package/src/cache/segment-codec.ts +9 -17
  140. package/src/cache/tag-invalidation.ts +230 -0
  141. package/src/cache/types.ts +37 -100
  142. package/src/client.rsc.tsx +44 -21
  143. package/src/client.tsx +36 -61
  144. package/src/cloudflare/index.ts +11 -0
  145. package/src/cloudflare/tracing.ts +109 -0
  146. package/src/component-utils.ts +19 -0
  147. package/src/components/DefaultDocument.tsx +8 -2
  148. package/src/context-var.ts +18 -6
  149. package/src/decode-loader-results.ts +52 -0
  150. package/src/defer.ts +196 -0
  151. package/src/deps/ssr.ts +0 -1
  152. package/src/encode-kv.ts +49 -0
  153. package/src/errors.ts +30 -4
  154. package/src/escape-script.ts +52 -0
  155. package/src/handle.ts +31 -23
  156. package/src/handles/MetaTags.tsx +62 -19
  157. package/src/handles/Scripts.tsx +183 -0
  158. package/src/handles/breadcrumbs.ts +37 -8
  159. package/src/handles/is-thenable.ts +19 -0
  160. package/src/handles/meta.ts +51 -40
  161. package/src/handles/script.ts +244 -0
  162. package/src/host/cookie-handler.ts +9 -60
  163. package/src/host/errors.ts +0 -24
  164. package/src/host/index.ts +8 -2
  165. package/src/host/pattern-matcher.ts +23 -52
  166. package/src/host/router.ts +107 -99
  167. package/src/host/testing.ts +40 -27
  168. package/src/host/types.ts +37 -4
  169. package/src/host/utils.ts +1 -1
  170. package/src/href-client.ts +137 -22
  171. package/src/index.rsc.ts +96 -12
  172. package/src/index.ts +94 -14
  173. package/src/internal-debug.ts +11 -10
  174. package/src/loader-store.ts +500 -0
  175. package/src/loader.rsc.ts +20 -13
  176. package/src/loader.ts +12 -11
  177. package/src/missing-id-error.ts +68 -0
  178. package/src/outlet-context.ts +1 -1
  179. package/src/outlet-provider.tsx +1 -5
  180. package/src/prerender/param-hash.ts +16 -16
  181. package/src/prerender/store.ts +32 -37
  182. package/src/prerender.ts +61 -6
  183. package/src/redirect-origin.ts +100 -0
  184. package/src/regex-escape.ts +8 -0
  185. package/src/render-error-thrower.tsx +20 -0
  186. package/src/response-utils.ts +34 -0
  187. package/src/reverse.ts +65 -40
  188. package/src/root-error-boundary.tsx +1 -19
  189. package/src/route-content-wrapper.tsx +19 -77
  190. package/src/route-definition/dsl-helpers.ts +304 -309
  191. package/src/route-definition/helper-factories.ts +28 -140
  192. package/src/route-definition/helpers-types.ts +82 -55
  193. package/src/route-definition/index.ts +1 -2
  194. package/src/route-definition/redirect.ts +44 -11
  195. package/src/route-definition/resolve-handler-use.ts +12 -1
  196. package/src/route-definition/use-item-types.ts +29 -0
  197. package/src/route-map-builder.ts +0 -16
  198. package/src/route-types.ts +19 -46
  199. package/src/router/basename.ts +14 -0
  200. package/src/router/content-negotiation.ts +73 -25
  201. package/src/router/error-handling.ts +45 -18
  202. package/src/router/find-match.ts +44 -23
  203. package/src/router/handler-context.ts +27 -43
  204. package/src/router/instrument.ts +350 -0
  205. package/src/router/intercept-resolution.ts +39 -20
  206. package/src/router/lazy-includes.ts +10 -47
  207. package/src/router/loader-resolution.ts +155 -72
  208. package/src/router/logging.ts +0 -6
  209. package/src/router/manifest.ts +18 -29
  210. package/src/router/match-api.ts +9 -24
  211. package/src/router/match-context.ts +0 -22
  212. package/src/router/match-handlers.ts +58 -58
  213. package/src/router/match-middleware/background-revalidation.ts +40 -24
  214. package/src/router/match-middleware/cache-lookup.ts +159 -285
  215. package/src/router/match-middleware/cache-store.ts +64 -52
  216. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  217. package/src/router/match-middleware/segment-resolution.ts +0 -22
  218. package/src/router/match-pipelines.ts +1 -42
  219. package/src/router/match-result.ts +44 -74
  220. package/src/router/metrics.ts +0 -34
  221. package/src/router/middleware-types.ts +7 -134
  222. package/src/router/middleware.ts +247 -166
  223. package/src/router/navigation-snapshot.ts +0 -51
  224. package/src/router/params-util.ts +23 -0
  225. package/src/router/pattern-matching.ts +85 -94
  226. package/src/router/prefetch-cache-ttl.ts +51 -0
  227. package/src/router/prerender-match.ts +104 -65
  228. package/src/router/preview-match.ts +3 -1
  229. package/src/router/request-classification.ts +28 -62
  230. package/src/router/revalidation.ts +123 -73
  231. package/src/router/route-snapshot.ts +0 -1
  232. package/src/router/router-context.ts +3 -28
  233. package/src/router/router-interfaces.ts +83 -35
  234. package/src/router/router-options.ts +136 -5
  235. package/src/router/router-registry.ts +2 -5
  236. package/src/router/segment-resolution/fresh.ts +97 -84
  237. package/src/router/segment-resolution/helpers.ts +86 -6
  238. package/src/router/segment-resolution/loader-cache.ts +76 -39
  239. package/src/router/segment-resolution/revalidation.ts +272 -320
  240. package/src/router/segment-resolution/static-store.ts +19 -5
  241. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  242. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  243. package/src/router/segment-resolution.ts +5 -1
  244. package/src/router/segment-wrappers.ts +6 -5
  245. package/src/router/state-cookie-name.ts +33 -0
  246. package/src/router/substitute-pattern-params.ts +56 -0
  247. package/src/router/telemetry-otel.ts +161 -199
  248. package/src/router/telemetry.ts +96 -19
  249. package/src/router/timeout.ts +0 -20
  250. package/src/router/tracing.ts +206 -0
  251. package/src/router/trie-matching.ts +162 -64
  252. package/src/router/types.ts +9 -63
  253. package/src/router/url-params.ts +0 -5
  254. package/src/router.ts +110 -55
  255. package/src/rsc/handler-context.ts +3 -2
  256. package/src/rsc/handler.ts +264 -220
  257. package/src/rsc/helpers.ts +100 -6
  258. package/src/rsc/index.ts +2 -5
  259. package/src/rsc/json-route-result.ts +38 -0
  260. package/src/rsc/loader-fetch.ts +114 -38
  261. package/src/rsc/manifest-init.ts +28 -41
  262. package/src/rsc/origin-guard.ts +39 -25
  263. package/src/rsc/progressive-enhancement.ts +117 -11
  264. package/src/rsc/redirect-guard.ts +99 -0
  265. package/src/rsc/response-cache-serve.ts +238 -0
  266. package/src/rsc/response-error.ts +79 -12
  267. package/src/rsc/response-route-handler.ts +88 -188
  268. package/src/rsc/rsc-rendering.ts +98 -76
  269. package/src/rsc/runtime-warnings.ts +23 -10
  270. package/src/rsc/server-action.ts +281 -117
  271. package/src/rsc/ssr-setup.ts +16 -0
  272. package/src/rsc/transition-gate.ts +89 -0
  273. package/src/rsc/types.ts +23 -5
  274. package/src/runtime-env.ts +18 -0
  275. package/src/search-params.ts +35 -30
  276. package/src/segment-loader-promise.ts +31 -4
  277. package/src/segment-system.tsx +254 -143
  278. package/src/serialize.ts +243 -0
  279. package/src/server/context.ts +163 -51
  280. package/src/server/cookie-parse.ts +32 -0
  281. package/src/server/cookie-store.ts +80 -5
  282. package/src/server/handle-store.ts +21 -38
  283. package/src/server/loader-registry.ts +33 -42
  284. package/src/server/request-context.ts +287 -178
  285. package/src/ssr/index.tsx +21 -16
  286. package/src/static-handler.ts +10 -13
  287. package/src/testing/cache-status.ts +162 -0
  288. package/src/testing/collect-handle.ts +40 -0
  289. package/src/testing/dispatch.ts +701 -0
  290. package/src/testing/dom.entry.ts +22 -0
  291. package/src/testing/e2e/fixture.ts +188 -0
  292. package/src/testing/e2e/index.ts +128 -0
  293. package/src/testing/e2e/matchers.ts +35 -0
  294. package/src/testing/e2e/page-helpers.ts +272 -0
  295. package/src/testing/e2e/parity.ts +387 -0
  296. package/src/testing/e2e/server.ts +195 -0
  297. package/src/testing/flight-matchers.ts +97 -0
  298. package/src/testing/flight-normalize.ts +11 -0
  299. package/src/testing/flight-runtime.d.ts +57 -0
  300. package/src/testing/flight-tree.ts +682 -0
  301. package/src/testing/flight.entry.ts +52 -0
  302. package/src/testing/flight.ts +257 -0
  303. package/src/testing/generated-routes.ts +183 -0
  304. package/src/testing/index.ts +105 -0
  305. package/src/testing/internal/context.ts +371 -0
  306. package/src/testing/internal/flight-client-globals.ts +30 -0
  307. package/src/testing/internal/seed-vars.ts +54 -0
  308. package/src/testing/render-handler.ts +357 -0
  309. package/src/testing/render-route.tsx +581 -0
  310. package/src/testing/run-loader.ts +385 -0
  311. package/src/testing/run-middleware.ts +205 -0
  312. package/src/testing/run-transition-when.ts +164 -0
  313. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  314. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  315. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  316. package/src/testing/vitest-stubs/version.ts +5 -0
  317. package/src/testing/vitest.ts +305 -0
  318. package/src/theme/ThemeProvider.tsx +20 -58
  319. package/src/theme/ThemeScript.tsx +7 -9
  320. package/src/theme/constants.ts +52 -13
  321. package/src/theme/index.ts +0 -7
  322. package/src/theme/theme-context.ts +1 -5
  323. package/src/theme/theme-script.ts +22 -21
  324. package/src/theme/use-theme.ts +0 -3
  325. package/src/types/boundaries.ts +0 -35
  326. package/src/types/cache-types.ts +13 -4
  327. package/src/types/error-types.ts +30 -90
  328. package/src/types/global-namespace.ts +54 -41
  329. package/src/types/handler-context.ts +110 -62
  330. package/src/types/index.ts +3 -10
  331. package/src/types/loader-types.ts +11 -9
  332. package/src/types/request-scope.ts +112 -0
  333. package/src/types/route-config.ts +6 -50
  334. package/src/types/route-entry.ts +0 -6
  335. package/src/types/segments.ts +135 -14
  336. package/src/urls/include-helper.ts +9 -56
  337. package/src/urls/index.ts +1 -11
  338. package/src/urls/path-helper-types.ts +29 -12
  339. package/src/urls/path-helper.ts +17 -106
  340. package/src/urls/pattern-types.ts +36 -19
  341. package/src/urls/response-types.ts +22 -29
  342. package/src/urls/type-extraction.ts +58 -139
  343. package/src/urls/urls-function.ts +1 -19
  344. package/src/use-loader.tsx +292 -107
  345. package/src/vite/debug.ts +185 -0
  346. package/src/vite/discovery/bundle-postprocess.ts +8 -7
  347. package/src/vite/discovery/discover-routers.ts +126 -85
  348. package/src/vite/discovery/discovery-errors.ts +194 -0
  349. package/src/vite/discovery/gate-state.ts +171 -0
  350. package/src/vite/discovery/prerender-collection.ts +96 -68
  351. package/src/vite/discovery/route-types-writer.ts +40 -84
  352. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  353. package/src/vite/discovery/state.ts +44 -0
  354. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  355. package/src/vite/index.ts +2 -0
  356. package/src/vite/inject-client-debug.ts +36 -0
  357. package/src/vite/plugin-types.ts +126 -8
  358. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  359. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  360. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  361. package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
  362. package/src/vite/plugins/expose-action-id.ts +48 -95
  363. package/src/vite/plugins/expose-id-utils.ts +88 -55
  364. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  365. package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
  366. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  367. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  368. package/src/vite/plugins/expose-internal-ids.ts +505 -486
  369. package/src/vite/plugins/performance-tracks.ts +26 -25
  370. package/src/vite/plugins/refresh-cmd.ts +1 -1
  371. package/src/vite/plugins/use-cache-transform.ts +73 -83
  372. package/src/vite/plugins/version-injector.ts +40 -29
  373. package/src/vite/plugins/version-plugin.ts +37 -40
  374. package/src/vite/plugins/virtual-entries.ts +39 -25
  375. package/src/vite/rango.ts +109 -118
  376. package/src/vite/router-discovery.ts +718 -119
  377. package/src/vite/utils/ast-handler-extract.ts +26 -35
  378. package/src/vite/utils/banner.ts +1 -1
  379. package/src/vite/utils/bundle-analysis.ts +10 -15
  380. package/src/vite/utils/client-chunks.ts +184 -0
  381. package/src/vite/utils/directive-prologue.ts +40 -0
  382. package/src/vite/utils/forward-user-plugins.ts +171 -0
  383. package/src/vite/utils/manifest-utils.ts +4 -59
  384. package/src/vite/utils/package-resolution.ts +20 -52
  385. package/src/vite/utils/prerender-utils.ts +54 -39
  386. package/src/vite/utils/shared-utils.ts +90 -41
  387. package/src/browser/action-response-classifier.ts +0 -99
  388. package/src/browser/react/use-client-cache.ts +0 -58
  389. package/src/browser/shallow.ts +0 -40
  390. package/src/handles/index.ts +0 -7
  391. package/src/network-error-thrower.tsx +0 -23
  392. package/src/router/middleware-cookies.ts +0 -55
@@ -8,125 +8,41 @@ import {
8
8
  revalidate,
9
9
  parallel,
10
10
  intercept,
11
- when,
12
11
  errorBoundary,
13
12
  notFoundBoundary,
14
- loaderFn,
15
- loadingFn,
16
- transitionFn,
17
- routeFn,
13
+ route,
14
+ loader,
15
+ loading,
16
+ transition,
18
17
  } from "./dsl-helpers.js";
19
18
  import RootLayout from "../server/root-layout";
20
19
  import { invariant } from "../errors";
21
20
 
22
- /*
23
- * Create revalidate helper
24
- */
25
- const createRevalidateHelper = <TEnv>(): RouteHelpers<
26
- any,
27
- TEnv
28
- >["revalidate"] => {
29
- return revalidate as RouteHelpers<any, TEnv>["revalidate"];
30
- };
31
-
32
- /**
33
- * Create errorBoundary helper
34
- */
35
- const createErrorBoundaryHelper = <TEnv>(): RouteHelpers<
36
- any,
37
- TEnv
38
- >["errorBoundary"] => {
39
- return errorBoundary as RouteHelpers<any, TEnv>["errorBoundary"];
40
- };
41
-
42
- /**
43
- * Create notFoundBoundary helper
44
- */
45
- const createNotFoundBoundaryHelper = <TEnv>(): RouteHelpers<
46
- any,
47
- TEnv
48
- >["notFoundBoundary"] => {
49
- return notFoundBoundary as RouteHelpers<any, TEnv>["notFoundBoundary"];
50
- };
51
-
52
21
  /**
53
- * Create middleware helper
22
+ * Assemble the RouteHelpers object. The helpers are the DSL functions
23
+ * themselves; the single cast erases the phantom generics (and the extra
24
+ * `route` key) that the per-router RouteHelpers<T, TEnv> type carries but the
25
+ * runtime functions do not.
54
26
  */
55
- const createMiddlewareHelper = <TEnv>(): RouteHelpers<
56
- any,
27
+ function buildRouteHelpers<T extends RouteDefinition, TEnv>(): RouteHelpers<
28
+ T,
57
29
  TEnv
58
- >["middleware"] => {
59
- return middleware as RouteHelpers<any, TEnv>["middleware"];
60
- };
61
-
62
- /**
63
- * Create parallel helper
64
- */
65
- const createParallelHelper = <TEnv>(): RouteHelpers<any, TEnv>["parallel"] => {
66
- return parallel as RouteHelpers<any, TEnv>["parallel"];
67
- };
68
-
69
- /**
70
- * Create intercept helper
71
- */
72
- const createInterceptHelper = <
73
- const T extends RouteDefinition,
74
- TEnv,
75
- >(): RouteHelpers<T, TEnv>["intercept"] => {
76
- return intercept as RouteHelpers<T, TEnv>["intercept"];
77
- };
78
-
79
- /**
80
- * Create loader helper
81
- */
82
- const createLoaderHelper = <TEnv>(): RouteHelpers<any, TEnv>["loader"] => {
83
- return loaderFn as RouteHelpers<any, TEnv>["loader"];
84
- };
85
-
86
- /**
87
- * Create loading helper
88
- */
89
- const createLoadingHelper = (): RouteHelpers<any, any>["loading"] => {
90
- return loadingFn;
91
- };
92
-
93
- /**
94
- * Create route helper
95
- */
96
- const createRouteHelper = <
97
- const T extends RouteDefinition,
98
- TEnv,
99
- >(): RouteHelpers<T, TEnv>["route"] => {
100
- return routeFn as unknown as RouteHelpers<T, TEnv>["route"];
101
- };
102
-
103
- /**
104
- * Create layout helper
105
- */
106
- const createLayoutHelper = <TEnv>(): RouteHelpers<any, TEnv>["layout"] => {
107
- return layout as RouteHelpers<any, TEnv>["layout"];
108
- };
109
-
110
- /**
111
- * Create when helper for intercept conditions
112
- */
113
- const createWhenHelper = (): RouteHelpers<any, any>["when"] => {
114
- return when;
115
- };
116
-
117
- /**
118
- * Create cache helper for cache configuration
119
- */
120
- const createCacheHelper = (): RouteHelpers<any, any>["cache"] => {
121
- return cache;
122
- };
123
-
124
- /**
125
- * Create transition helper
126
- */
127
- const createTransitionHelper = (): RouteHelpers<any, any>["transition"] => {
128
- return transitionFn as RouteHelpers<any, any>["transition"];
129
- };
30
+ > {
31
+ return {
32
+ route,
33
+ layout,
34
+ parallel,
35
+ intercept,
36
+ middleware,
37
+ revalidate,
38
+ loader,
39
+ loading,
40
+ errorBoundary,
41
+ notFoundBoundary,
42
+ cache,
43
+ transition,
44
+ } as unknown as RouteHelpers<T, TEnv>;
45
+ }
130
46
 
131
47
  /**
132
48
  * Branded type for route handlers that carries the route type info.
@@ -152,21 +68,7 @@ export function map<const T extends RouteDefinition, TEnv = DefaultEnv>(
152
68
  "map() expects a builder function as its argument",
153
69
  );
154
70
  // Create helpers
155
- const helpers: RouteHelpers<T, TEnv> = {
156
- route: createRouteHelper<T, TEnv>(),
157
- layout: createLayoutHelper<TEnv>(),
158
- parallel: createParallelHelper<TEnv>(),
159
- intercept: createInterceptHelper<T, TEnv>(),
160
- middleware: createMiddlewareHelper<TEnv>(),
161
- revalidate: createRevalidateHelper<TEnv>(),
162
- loader: createLoaderHelper<TEnv>(),
163
- loading: createLoadingHelper(),
164
- errorBoundary: createErrorBoundaryHelper<TEnv>(),
165
- notFoundBoundary: createNotFoundBoundaryHelper<TEnv>(),
166
- when: createWhenHelper(),
167
- cache: createCacheHelper(),
168
- transition: createTransitionHelper(),
169
- };
71
+ const helpers = buildRouteHelpers<T, TEnv>();
170
72
 
171
73
  return [layout(RootLayout, () => builder(helpers))].flat(3);
172
74
  };
@@ -182,19 +84,5 @@ export function createRouteHelpers<
182
84
  T extends RouteDefinition,
183
85
  TEnv,
184
86
  >(): RouteHelpers<T, TEnv> {
185
- return {
186
- route: createRouteHelper<T, TEnv>(),
187
- layout: createLayoutHelper<TEnv>(),
188
- parallel: createParallelHelper<TEnv>(),
189
- intercept: createInterceptHelper<T, TEnv>(),
190
- middleware: createMiddlewareHelper<TEnv>(),
191
- revalidate: createRevalidateHelper<TEnv>(),
192
- loader: createLoaderHelper<TEnv>(),
193
- loading: createLoadingHelper(),
194
- errorBoundary: createErrorBoundaryHelper<TEnv>(),
195
- notFoundBoundary: createNotFoundBoundaryHelper<TEnv>(),
196
- when: createWhenHelper(),
197
- cache: createCacheHelper(),
198
- transition: createTransitionHelper(),
199
- };
87
+ return buildRouteHelpers<T, TEnv>();
200
88
  }
@@ -29,12 +29,10 @@ import type {
29
29
  ParallelUseItem,
30
30
  InterceptUseItem,
31
31
  LoaderUseItem,
32
- WhenItem,
33
32
  CacheItem,
34
33
  TransitionItem,
35
34
  UseItems,
36
35
  } from "../route-types.js";
37
- import type { InterceptWhenFn } from "../server/context";
38
36
 
39
37
  // Re-export route item types for backward compatibility
40
38
  export type {
@@ -52,12 +50,12 @@ export type {
52
50
  RouteUseItem,
53
51
  ParallelUseItem,
54
52
  InterceptUseItem,
55
- WhenItem,
56
53
  CacheItem,
57
54
  } from "../route-types.js";
58
55
 
59
56
  // Re-export intercept selector types for use in handlers
60
57
  export type {
58
+ InterceptConfig,
61
59
  InterceptSelectorContext,
62
60
  InterceptSegmentsState,
63
61
  InterceptWhenFn,
@@ -183,10 +181,26 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
183
181
  * loader(CardModalLoader),
184
182
  * revalidate(() => false),
185
183
  * ])
184
+ *
185
+ * // Conditional activation via the config object's `when` selector
186
+ * intercept("@modal", "card", <CardModal />, {
187
+ * when: ({ from }) => from.pathname.startsWith("/board"),
188
+ * })
189
+ *
190
+ * // Config + other use-items: config is arg 4, use is arg 5
191
+ * intercept(
192
+ * "@modal",
193
+ * "card",
194
+ * <CardModal />,
195
+ * { when: ({ from }) => from.pathname.startsWith("/board") },
196
+ * () => [loader(CardDetailLoader)],
197
+ * )
186
198
  * ```
187
199
  * @param slotName - Named slot (prefixed with @) where intercept renders
188
200
  * @param routeName - Route name to intercept
189
201
  * @param handler - Component or handler for intercepted render
202
+ * @param config - Optional InterceptConfig (e.g. `{ when }`), or the use
203
+ * callback directly when there is no config
190
204
  * @param use - Optional callback for loaders, middleware, revalidate, etc.
191
205
  */
192
206
  intercept: {
@@ -195,13 +209,19 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
195
209
  slotName: `@${string}`,
196
210
  routeName: `.${K}`,
197
211
  handler: ReactNode | Handler<ExtractRouteParams<T, K>, {}, TEnv>,
212
+ config?:
213
+ | import("../server/context.js").InterceptConfig<TEnv>
214
+ | (() => UseItems<InterceptUseItem>),
198
215
  use?: () => UseItems<InterceptUseItem>,
199
216
  ): InterceptItem;
200
217
  // Global: unprefixed, params inferred from global route map
201
- <K extends keyof RSCRouter.GeneratedRouteMap & string>(
218
+ <K extends keyof Rango.GeneratedRouteMap & string>(
202
219
  slotName: `@${string}`,
203
220
  routeName: K,
204
- handler: ReactNode | Handler<K, RSCRouter.GeneratedRouteMap, TEnv>,
221
+ handler: ReactNode | Handler<K, Rango.GeneratedRouteMap, TEnv>,
222
+ config?:
223
+ | import("../server/context.js").InterceptConfig<TEnv>
224
+ | (() => UseItems<InterceptUseItem>),
205
225
  use?: () => UseItems<InterceptUseItem>,
206
226
  ): InterceptItem;
207
227
  };
@@ -250,8 +270,10 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
250
270
  * )
251
271
  *
252
272
  * // Revalidate after specific actions (actionId format: "path/to/file.ts#exportName")
273
+ * // Use `|| undefined` (defer), not `?? false` (hard short-circuit), so the
274
+ * // chain and the segment default still apply when there is no match.
253
275
  * revalidate(({ actionId }) =>
254
- * actionId?.includes("Cart") ?? false
276
+ * actionId?.includes("Cart") || undefined
255
277
  * )
256
278
  *
257
279
  * // Soft decision (suggest but allow override)
@@ -259,7 +281,12 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
259
281
  * ({ defaultShouldRevalidate: true })
260
282
  * )
261
283
  * ```
262
- * @param fn - Function that returns boolean (hard) or { defaultShouldRevalidate } (soft)
284
+ * @param fn - Function returning either:
285
+ * - `boolean` (hard decision — short-circuits the chain),
286
+ * - `{ defaultShouldRevalidate: boolean }` (soft — updates the suggestion
287
+ * for downstream revalidators),
288
+ * - or nothing / `null` / `undefined` (defer — leaves the suggestion
289
+ * unchanged and continues to the next revalidator).
263
290
  */
264
291
  revalidate: (fn: ShouldRevalidateFn<any, TEnv>) => RevalidateItem;
265
292
  /**
@@ -269,7 +296,7 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
269
296
  *
270
297
  * // With loader-specific revalidation (match by file or export name)
271
298
  * loader(CartLoader, () => [
272
- * revalidate(({ actionId }) => actionId?.includes("Cart") ?? false),
299
+ * revalidate(({ actionId }) => actionId?.includes("Cart") || undefined),
273
300
  * ])
274
301
  *
275
302
  * // Consume in client components with useLoader()
@@ -340,40 +367,6 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
340
367
  notFoundBoundary: (
341
368
  fallback: ReactNode | NotFoundBoundaryHandler,
342
369
  ) => NotFoundBoundaryItem;
343
- /**
344
- * Define a condition for when an intercept should activate
345
- *
346
- * Only valid inside intercept() use() callback. When multiple when() calls
347
- * are present, ALL must return true for the intercept to activate.
348
- * If no when() is defined, the intercept always activates on soft navigation.
349
- *
350
- * Context properties:
351
- * - `from` - Source URL (where user is navigating from)
352
- * - `to` - Destination URL (where user is navigating to)
353
- * - `params` - Matched route params
354
- * - `segments` - Client's current segments with `path` and `ids`
355
- *
356
- * ```typescript
357
- * // Only intercept when coming from the board page
358
- * intercept("@modal", "card", <CardModal />, () => [
359
- * when(({ from }) => from.pathname.startsWith("/board")),
360
- * loader(CardDetailLoader),
361
- * ])
362
- *
363
- * // Use segments to check current route context
364
- * intercept("@modal", "card", <CardModal />, () => [
365
- * when(({ segments }) => segments.path[0] === "kanban"),
366
- * ])
367
- *
368
- * // Multiple conditions (AND logic)
369
- * intercept("@modal", "card", <CardModal />, () => [
370
- * when(({ from }) => from.pathname.startsWith("/board")),
371
- * when(({ segments }) => segments.ids.includes("kanban-layout")),
372
- * ])
373
- * ```
374
- * @param fn - Selector function receiving navigation context, returns boolean
375
- */
376
- when: (fn: InterceptWhenFn) => WhenItem;
377
370
  /**
378
371
  * Define cache configuration for segments
379
372
  *
@@ -434,18 +427,43 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
434
427
  cache: {
435
428
  (): CacheItem;
436
429
  (children: () => UseItems<AllUseItems>): CacheItem;
437
- (profileName: string): CacheItem;
438
- (profileName: string, use: () => UseItems<AllUseItems>): CacheItem;
439
430
  (
440
- options: PartialCacheOptions | false,
431
+ options: PartialCacheOptions<TEnv> | false,
441
432
  use?: () => UseItems<AllUseItems>,
442
433
  ): CacheItem;
443
434
  };
444
435
  /**
445
- * Attach a ViewTransition boundary to the current segment or a group of routes
446
- *
447
- * Wraps segment content with React's `<ViewTransition>` component.
448
- * Only takes effect when React experimental is used (no-op on stable React).
436
+ * Opt a route (or group of routes) into transition-driven navigation.
437
+ *
438
+ * `transition()` does two independent things, and you choose how far to go:
439
+ * 1. startTransition (ALL React versions): the navigation commit is driven
440
+ * through React's startTransition, so a same-route nav (same route,
441
+ * different params, e.g. /product/1 -> /product/2) holds the previous
442
+ * content while the new loader resolves instead of flashing the route's
443
+ * loading() skeleton (see segment-system.tsx inTransitionScope). This is
444
+ * also the precondition for any view-transition animation.
445
+ * 2. <ViewTransition> (experimental React only): the segment content is also
446
+ * wrapped in React's <ViewTransition>, so the held swap cross-fades/morphs.
447
+ * Layered on by default; pass { viewTransition: false } to keep #1 without
448
+ * the router boundary (and place your own <ViewTransition> instead).
449
+ *
450
+ * A view transition cannot fire without a startTransition, so the meaningful
451
+ * choices are (see skills/view-transitions for the full matrix):
452
+ * - no transition() -> neither (remount + skeleton)
453
+ * - transition({ viewTransition: false }) -> startTransition only (hold)
454
+ * - transition({}) / transition({ enter… }) -> startTransition + ViewTransition
455
+ *
456
+ * Precedence: a bare transition({}) inherits createRouter({ viewTransition })
457
+ * (default "auto"); an explicit per-route `viewTransition` always wins. So
458
+ * transition({}) is startTransition + ViewTransition under the default and
459
+ * startTransition only when the router sets viewTransition: false.
460
+ *
461
+ * Conditional hold: pass `when: (ctx) => boolean` to gate the transition per
462
+ * request. It runs server-side AFTER the route handler (so it can read state
463
+ * the handler set via `ctx.get(...)`); returning false drops this transition
464
+ * for the request, so the navigation streams its loading() skeleton instead of
465
+ * holding. This is a post-handler predicate — distinct from intercept()'s
466
+ * match-time `when` config selector (`intercept(slot, route, Comp, { when })`).
449
467
  *
450
468
  * ```typescript
451
469
  * // Attach to a single route
@@ -459,16 +477,25 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
459
477
  * path("/about", AboutPage),
460
478
  * ])
461
479
  *
462
- * // Direction-aware transitions
463
- * transition({
464
- * enter: { "navigation": "slide-right", "navigation-back": "slide-left" },
465
- * exit: { "navigation": "slide-left", "navigation-back": "slide-right" },
466
- * })
480
+ * // Hold content + drive view transitions, but place no router boundary:
481
+ * path("/product/:id", ProductPage, { name: "product" }, () => [
482
+ * transition({ viewTransition: false }),
483
+ * ])
484
+ *
485
+ * // Hold only when the handler decided to (post-handler predicate):
486
+ * path("/product/:id", ProductPage, { name: "product" }, () => [
487
+ * transition({ when: (ctx) => ctx.get(KeepScroll) === true }),
488
+ * ])
467
489
  * ```
468
- * @param config - ViewTransition configuration (enter, exit, update, share, default, name)
490
+ * @param config - ViewTransition configuration (enter, exit, update, share,
491
+ * default, name), `viewTransition: "auto" | false` to toggle the router
492
+ * boundary (createRouter({ viewTransition }) sets the app-wide default), and
493
+ * `when: (ctx) => boolean` to gate the transition per request post-handler
469
494
  * @param children - Optional callback returning child routes to wrap
470
495
  */
471
496
  transition: {
497
+ (): TransitionItem;
498
+ (children: () => UseItems<AllUseItems>): TransitionItem;
472
499
  (config: TransitionConfig): TransitionItem;
473
500
  (
474
501
  config: TransitionConfig,
@@ -15,8 +15,8 @@ export type {
15
15
  RouteUseItem,
16
16
  ParallelUseItem,
17
17
  InterceptUseItem,
18
- WhenItem,
19
18
  CacheItem,
19
+ InterceptConfig,
20
20
  InterceptSelectorContext,
21
21
  InterceptSegmentsState,
22
22
  InterceptWhenFn,
@@ -30,7 +30,6 @@ export {
30
30
  revalidate,
31
31
  parallel,
32
32
  intercept,
33
- when,
34
33
  errorBoundary,
35
34
  notFoundBoundary,
36
35
  loader,
@@ -1,9 +1,9 @@
1
1
  import type { LocationStateEntry } from "../browser/react/location-state-shared.js";
2
2
  import {
3
- requireRequestContext,
4
3
  getRequestContext,
5
4
  _getRequestContext,
6
5
  } from "../server/request-context.js";
6
+ import { markExternalRedirect } from "../redirect-origin.js";
7
7
 
8
8
  /**
9
9
  * Create a soft redirect Response for middleware short-circuit
@@ -39,6 +39,11 @@ import {
39
39
  * status: 303,
40
40
  * state: [Flash({ text: "Session expired" })],
41
41
  * });
42
+ *
43
+ * // Off-host redirect (opt out of the same-origin guard). Without
44
+ * // `external: true`, a cross-origin target is blocked and replaced with the
45
+ * // app root, matching the client's open-redirect protection.
46
+ * return redirect('https://accounts.example.com/oauth', { external: true });
42
47
  * ```
43
48
  */
44
49
  export function redirect(url: string, status?: number): Response;
@@ -47,13 +52,18 @@ export function redirect(
47
52
  options: {
48
53
  status?: number;
49
54
  state?: LocationStateEntry | LocationStateEntry[];
55
+ external?: boolean;
50
56
  },
51
57
  ): Response;
52
58
  export function redirect(
53
59
  url: string,
54
60
  statusOrOptions?:
55
61
  | number
56
- | { status?: number; state?: LocationStateEntry | LocationStateEntry[] },
62
+ | {
63
+ status?: number;
64
+ state?: LocationStateEntry | LocationStateEntry[];
65
+ external?: boolean;
66
+ },
57
67
  ): Response {
58
68
  const status =
59
69
  typeof statusOrOptions === "number"
@@ -61,9 +71,11 @@ export function redirect(
61
71
  : (statusOrOptions?.status ?? 302);
62
72
  const state =
63
73
  typeof statusOrOptions === "object" ? statusOrOptions?.state : undefined;
74
+ const external =
75
+ typeof statusOrOptions === "object" ? statusOrOptions?.external : undefined;
64
76
 
65
77
  if (state) {
66
- const ctx = requireRequestContext();
78
+ const ctx = getRequestContext();
67
79
  ctx.setLocationState(state);
68
80
 
69
81
  if (process.env.NODE_ENV !== "production") {
@@ -85,17 +97,38 @@ export function redirect(
85
97
  }
86
98
 
87
99
  // Auto-prefix root-relative URLs with basename for app-local redirects.
100
+ // Treat the URL as already-prefixed when the basename is followed by a path
101
+ // separator, a query, a fragment, or end-of-string, so "/admin?tab=x" and
102
+ // "/admin#frag" are not double-prefixed into "/admin/admin?tab=x".
88
103
  const bn = _getRequestContext()?._basename;
89
104
  let resolvedUrl = url;
90
- if (bn && url.startsWith("/") && !url.startsWith(bn + "/") && url !== bn) {
105
+ if (
106
+ bn &&
107
+ url.startsWith("/") &&
108
+ url !== bn &&
109
+ !url.startsWith(bn + "/") &&
110
+ !url.startsWith(bn + "?") &&
111
+ !url.startsWith(bn + "#")
112
+ ) {
91
113
  resolvedUrl = url === "/" ? bn : bn + url;
92
114
  }
93
115
 
94
- return new Response(null, {
95
- status,
96
- headers: {
97
- Location: resolvedUrl,
98
- "X-RSC-Redirect": "soft",
99
- },
100
- });
116
+ const headers: Record<string, string> = {
117
+ Location: resolvedUrl,
118
+ "X-RSC-Redirect": "soft",
119
+ };
120
+
121
+ const response = new Response(null, { status, headers });
122
+
123
+ // Mark an explicit off-host redirect with an out-of-band brand so the
124
+ // same-origin guard (rsc/redirect-guard.ts) lets it through. The brand is a
125
+ // WeakSet membership on this Response object -- NOT a wire header -- so the
126
+ // opt-in cannot be forged by an attacker-controlled upstream response a
127
+ // proxy-style response route might copy. The internal redirect-rebuild paths
128
+ // transfer the brand; the guard reads and clears it (see markExternalRedirect).
129
+ if (external) {
130
+ markExternalRedirect(response);
131
+ }
132
+
133
+ return response;
101
134
  }
@@ -21,6 +21,10 @@ export function resolveHandlerUse(handler: unknown): (() => any[]) | undefined {
21
21
  if (isStaticHandler(handler)) {
22
22
  return (handler as any).use;
23
23
  }
24
+ // Loader definitions from createLoader() — branded objects with optional .use
25
+ if (typeof handler === "object" && (handler as any).__brand === "loader") {
26
+ return (handler as any).use;
27
+ }
24
28
  // Plain handler function
25
29
  if (typeof handler === "function") {
26
30
  return (handler as any).use;
@@ -96,9 +100,10 @@ const MOUNT_SITE_ALLOWED_TYPES: Record<string, Set<string>> = {
96
100
  "notFoundBoundary",
97
101
  "layout",
98
102
  "route",
99
- "when",
100
103
  "transition",
101
104
  ]),
105
+ // LoaderUseItem — only revalidate + cache can attach to a loader entry
106
+ loader: new Set(["revalidate", "cache"]),
102
107
  };
103
108
 
104
109
  /**
@@ -133,6 +138,12 @@ export function mergeHandlerUse(
133
138
  mountSite: string,
134
139
  ): (() => any[]) | undefined {
135
140
  if (!handlerUse && !explicitUse) return undefined;
141
+ // Validation asymmetry (intentional, pre-1.0): only handler.use() items are
142
+ // checked against the mount-site allow-list (validateHandlerUseItems below).
143
+ // Explicit use() items pass through unvalidated on both the explicit-only
144
+ // branch here and the merged branch, so a structurally-valid-but-prohibited
145
+ // item (e.g. middleware() inside a parallel slot) is not rejected at this seam.
146
+ // Documented rather than enforced for now; revisit before 1.0 (#569).
136
147
  if (!handlerUse) return explicitUse;
137
148
  if (!explicitUse) {
138
149
  return () => {
@@ -0,0 +1,29 @@
1
+ import type { AllUseItems } from "../route-types.js";
2
+
3
+ /**
4
+ * The set of valid use-item `type` discriminants — the single runtime source of
5
+ * truth for "is this a well-formed use item?" shape validation.
6
+ *
7
+ * Declared via a `Record<...>` so that adding a member to the union without
8
+ * updating this map is a compile error. This is shape validation only; per-mount-
9
+ * site rules remain the narrower hand-written tables in resolve-handler-use.ts.
10
+ */
11
+ const USE_ITEM_TYPES: Record<AllUseItems["type"], true> = {
12
+ layout: true,
13
+ route: true,
14
+ middleware: true,
15
+ revalidate: true,
16
+ parallel: true,
17
+ intercept: true,
18
+ loader: true,
19
+ loading: true,
20
+ errorBoundary: true,
21
+ notFoundBoundary: true,
22
+ cache: true,
23
+ transition: true,
24
+ include: true,
25
+ };
26
+
27
+ export const ALL_USE_ITEM_TYPES: ReadonlySet<string> = new Set(
28
+ Object.keys(USE_ITEM_TYPES),
29
+ );
@@ -8,15 +8,10 @@
8
8
  * See docs/manifests.md for the full data flow.
9
9
  */
10
10
 
11
- // Singleton route map instance - populated incrementally as routes are encountered
12
11
  let globalRouteMap: Record<string, string> = {};
13
12
 
14
- // Cached complete manifest - includes all routes (including lazy includes)
15
- // Set from runtime cache or build-time import
16
13
  let cachedManifest: Record<string, string> | null = null;
17
14
 
18
- // Pre-computed route entries from build-time prefix tree leaf nodes.
19
- // Used by evaluateLazyEntry() to skip running the handler for route matching.
20
15
  let cachedPrecomputedEntries: Array<{
21
16
  staticPrefix: string;
22
17
  routes: Record<string, string>;
@@ -43,7 +38,6 @@ export function registerRouteMap(map: Record<string, string>): void {
43
38
  * @internal
44
39
  */
45
40
  export function getGlobalRouteMap(): Record<string, string> {
46
- // Cached manifest is complete (includes lazy routes), so prefer it
47
41
  if (cachedManifest) {
48
42
  return cachedManifest;
49
43
  }
@@ -231,10 +225,6 @@ export function waitForManifestReady(): Promise<void> | null {
231
225
  return manifestReadyPromise;
232
226
  }
233
227
 
234
- // ============================================================================
235
- // Route Scope Registry
236
- // ============================================================================
237
-
238
228
  // Tracks whether each route is at root scope (no named include boundary above).
239
229
  // Used by dot-local reverse resolution to decide whether bare-name fallback
240
230
  // is allowed after scoped lookups are exhausted.
@@ -259,14 +249,8 @@ export function isRouteRootScoped(routeName: string): boolean | undefined {
259
249
  return rootScopeRoutes.get(routeName);
260
250
  }
261
251
 
262
- // ============================================================================
263
- // Search Schema Registry
264
- // ============================================================================
265
-
266
252
  import type { SearchSchema } from "./search-params.js";
267
253
 
268
- // Global search schema map: route name -> search schema descriptor.
269
- // Populated by path() when a search option is provided.
270
254
  const globalSearchSchemas: Map<string, SearchSchema> = new Map();
271
255
 
272
256
  export function registerSearchSchema(