@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
@@ -23,7 +23,7 @@ export function generatePerModuleTypesSource(
23
23
  const valid = routes.filter(({ name }) => {
24
24
  if (!name || /["'\\`\n\r]/.test(name)) {
25
25
  console.warn(
26
- `[rsc-router] Skipping route with invalid name: ${JSON.stringify(name)}`,
26
+ `[rango] Skipping route with invalid name: ${JSON.stringify(name)}`,
27
27
  );
28
28
  return false;
29
29
  }
@@ -42,7 +42,7 @@ export function generatePerModuleTypesSource(
42
42
  for (const { name, pattern, params, search } of valid) {
43
43
  if (deduped.has(name)) {
44
44
  console.warn(
45
- `[rsc-router] Duplicate route name "${name}" — keeping first definition`,
45
+ `[rango] Duplicate route name "${name}" — keeping first definition`,
46
46
  );
47
47
  continue;
48
48
  }
@@ -59,7 +59,7 @@ export function generatePerModuleTypesSource(
59
59
  }
60
60
 
61
61
  /**
62
- * Generates a .ts file that augments RSCRouter.GeneratedRouteMap
62
+ * Generates a .ts file that augments Rango.GeneratedRouteMap
63
63
  * with route name -> pattern mappings. This enables Handler<"routeName">
64
64
  * without circular references since the file has no imports from the app.
65
65
  */
@@ -88,14 +88,25 @@ export function generateRouteTypesSource(
88
88
  })
89
89
  .join("\n");
90
90
 
91
+ // The global augmentation extends an alias of `typeof NamedRoutes` rather than
92
+ // `Readonly<typeof NamedRoutes>`. `as const` already makes the members readonly,
93
+ // so the two are behaviour-identical, but `Readonly<>` is a homomorphic mapped
94
+ // type the compiler instantiates once per route at the augmentation site
95
+ // (~4 instantiations/route). An interface `extends` clause cannot name a bare
96
+ // `typeof` query, so the alias is what lets us drop the wrapper. Measured: ~35%
97
+ // fewer type instantiations on a 14k-route app; negligible (but free) on small.
91
98
  return `// Auto-generated by @rangojs/router - do not edit
92
99
  export const NamedRoutes = {
93
100
  ${objectBody}
94
101
  } as const;
95
102
 
103
+ // Aliased so the augmentation below does not pay a homomorphic mapped-type
104
+ // instantiation per route; \`as const\` already makes the members readonly.
105
+ type NamedRoutesShape = typeof NamedRoutes;
106
+
96
107
  declare global {
97
- namespace RSCRouter {
98
- interface GeneratedRouteMap extends Readonly<typeof NamedRoutes> {}
108
+ namespace Rango {
109
+ interface GeneratedRouteMap extends NamedRoutesShape {}
99
110
  }
100
111
  }
101
112
  `;
@@ -22,6 +22,61 @@ export interface UnresolvableInclude {
22
22
  detail: string;
23
23
  }
24
24
 
25
+ // ---------------------------------------------------------------------------
26
+ // Per-scan memo
27
+ // ---------------------------------------------------------------------------
28
+
29
+ /**
30
+ * Per-scan memo shared across the include-resolution recursion. Keys are
31
+ * absolute file paths; values cache the readFileSync result and the
32
+ * ts.SourceFile parsed from the FULL file source. A separate blockSources map
33
+ * caches parses of extracted sub-blocks (urls() call text), keyed by the exact
34
+ * block string, so the two extractors (routes + includes) for the same block
35
+ * share a single parse.
36
+ *
37
+ * The memo is purely a performance accelerator: same input -> same parse, so
38
+ * generated output is identical to the un-memoized path. A fresh memo is
39
+ * created per top-level scan entry, so stale file edits between scans are never
40
+ * served.
41
+ */
42
+ export interface ScanMemo {
43
+ files: Map<string, string>;
44
+ blockSourceFiles: Map<string, ts.SourceFile>;
45
+ }
46
+
47
+ export function createScanMemo(): ScanMemo {
48
+ return { files: new Map(), blockSourceFiles: new Map() };
49
+ }
50
+
51
+ function parseBlock(memo: ScanMemo | undefined, block: string): ts.SourceFile {
52
+ if (memo) {
53
+ const cached = memo.blockSourceFiles.get(block);
54
+ if (cached) return cached;
55
+ }
56
+ const sf = ts.createSourceFile(
57
+ "input.tsx",
58
+ block,
59
+ ts.ScriptTarget.Latest,
60
+ true,
61
+ ts.ScriptKind.TSX,
62
+ );
63
+ if (memo) memo.blockSourceFiles.set(block, sf);
64
+ return sf;
65
+ }
66
+
67
+ function readSourceMemoized(
68
+ memo: ScanMemo | undefined,
69
+ realPath: string,
70
+ ): string {
71
+ if (memo) {
72
+ const cached = memo.files.get(realPath);
73
+ if (cached !== undefined) return cached;
74
+ }
75
+ const source = readFileSync(realPath, "utf-8");
76
+ if (memo) memo.files.set(realPath, source);
77
+ return source;
78
+ }
79
+
25
80
  // ---------------------------------------------------------------------------
26
81
  // AST-based include() parsing
27
82
  // ---------------------------------------------------------------------------
@@ -47,7 +102,10 @@ function extractNamePrefixFromInclude(node: ts.CallExpression): string | null {
47
102
  * Returns both resolved includes (identifier second args) and unresolvable
48
103
  * includes (factory calls, etc.) with reasons.
49
104
  */
50
- export function extractIncludesWithDiagnostics(code: string): {
105
+ export function extractIncludesWithDiagnostics(
106
+ code: string,
107
+ sourceFileArg?: ts.SourceFile,
108
+ ): {
51
109
  resolved: Array<{
52
110
  pathPrefix: string;
53
111
  variableName: string;
@@ -60,13 +118,16 @@ export function extractIncludesWithDiagnostics(code: string): {
60
118
  detail: string;
61
119
  }>;
62
120
  } {
63
- const sourceFile = ts.createSourceFile(
64
- "input.tsx",
65
- code,
66
- ts.ScriptTarget.Latest,
67
- true,
68
- ts.ScriptKind.TSX,
69
- );
121
+ // Reuse a caller-provided SourceFile (parsed once per scan) when given.
122
+ const sourceFile =
123
+ sourceFileArg ??
124
+ ts.createSourceFile(
125
+ "input.tsx",
126
+ code,
127
+ ts.ScriptTarget.Latest,
128
+ true,
129
+ ts.ScriptKind.TSX,
130
+ );
70
131
  const resolved: Array<{
71
132
  pathPrefix: string;
72
133
  variableName: string;
@@ -140,7 +201,13 @@ export function resolveImportedVariable(
140
201
  code: string,
141
202
  localName: string,
142
203
  ): { specifier: string; exportedName: string } | null {
143
- const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
204
+ // Allow an optional leading default binding before the named-import brace so
205
+ // a combined `import Foo, { bar } from "..."` is matched (the named members
206
+ // are the only part we resolve; the default binding is skipped). Without the
207
+ // optional `(?:[\w$]+\s*,\s*)?` segment, the `Foo, ` prefix breaks the match
208
+ // and a legitimate static named import surfaces as `unresolvable-import`.
209
+ const importRegex =
210
+ /import\s*(?:[\w$]+\s*,\s*)?\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
144
211
  let match;
145
212
 
146
213
  while ((match = importRegex.exec(code)) !== null) {
@@ -206,14 +273,18 @@ export function resolveImportPath(
206
273
  function extractUrlsBlockForVariable(
207
274
  code: string,
208
275
  varName: string,
276
+ sourceFileArg?: ts.SourceFile,
209
277
  ): string | null {
210
- const sourceFile = ts.createSourceFile(
211
- "input.tsx",
212
- code,
213
- ts.ScriptTarget.Latest,
214
- true,
215
- ts.ScriptKind.TSX,
216
- );
278
+ // Reuse a caller-provided full-source SourceFile (parsed once per scan).
279
+ const sourceFile =
280
+ sourceFileArg ??
281
+ ts.createSourceFile(
282
+ "input.tsx",
283
+ code,
284
+ ts.ScriptTarget.Latest,
285
+ true,
286
+ ts.ScriptKind.TSX,
287
+ );
217
288
  let result: string | null = null;
218
289
 
219
290
  function visit(node: ts.Node) {
@@ -249,11 +320,15 @@ function buildRouteMapFromBlock(
249
320
  visited: Set<string>,
250
321
  searchSchemasOut?: Record<string, Record<string, string>>,
251
322
  diagnosticsOut?: UnresolvableInclude[],
323
+ memo?: ScanMemo,
252
324
  ): Record<string, string> {
253
325
  const routeMap: Record<string, string> = {};
254
326
 
327
+ // Parse the block once and share the SourceFile between both extractors.
328
+ const blockSourceFile = parseBlock(memo, block);
329
+
255
330
  // Extract local path() routes
256
- const localRoutes = extractRoutesFromSource(block);
331
+ const localRoutes = extractRoutesFromSource(block, blockSourceFile);
257
332
  for (const { name, pattern, search } of localRoutes) {
258
333
  routeMap[name] = pattern;
259
334
  if (search && searchSchemasOut) {
@@ -262,8 +337,10 @@ function buildRouteMapFromBlock(
262
337
  }
263
338
 
264
339
  // Extract include() calls with diagnostics for unresolvable ones
265
- const { resolved: includes, unresolvable } =
266
- extractIncludesWithDiagnostics(block);
340
+ const { resolved: includes, unresolvable } = extractIncludesWithDiagnostics(
341
+ block,
342
+ blockSourceFile,
343
+ );
267
344
 
268
345
  if (diagnosticsOut) {
269
346
  for (const entry of unresolvable) {
@@ -298,12 +375,17 @@ function buildRouteMapFromBlock(
298
375
  imported.exportedName,
299
376
  visited,
300
377
  diagnosticsOut,
378
+ undefined,
379
+ memo,
301
380
  );
302
381
  } else {
303
- // Check if variable exists as a same-file urls() definition
382
+ // Check if variable exists as a same-file urls() definition. Share the
383
+ // full-source SourceFile parse via the memo (block === fullSource hits the
384
+ // same cache entry already used above).
304
385
  const sameFileBlock = extractUrlsBlockForVariable(
305
386
  fullSource,
306
387
  variableName,
388
+ parseBlock(memo, fullSource),
307
389
  );
308
390
  if (!sameFileBlock) {
309
391
  if (diagnosticsOut) {
@@ -322,6 +404,8 @@ function buildRouteMapFromBlock(
322
404
  variableName,
323
405
  visited,
324
406
  diagnosticsOut,
407
+ undefined,
408
+ memo,
325
409
  );
326
410
  }
327
411
 
@@ -361,6 +445,9 @@ function buildRouteMapFromBlock(
361
445
  * @param inlineBlock - Optional pre-extracted code block (e.g. from an inline
362
446
  * builder function). When provided, variableName is ignored and the block
363
447
  * is parsed directly for path()/include() calls.
448
+ * @param memo - Per-scan readFileSync/parse memo. A fresh one is created at the
449
+ * top-level entry and threaded through the recursion so each file is read and
450
+ * parsed once per scan. Behavior-preserving (same input -> same output).
364
451
  */
365
452
  export function buildCombinedRouteMapWithSearch(
366
453
  filePath: string,
@@ -368,22 +455,24 @@ export function buildCombinedRouteMapWithSearch(
368
455
  visited?: Set<string>,
369
456
  diagnosticsOut?: UnresolvableInclude[],
370
457
  inlineBlock?: string,
458
+ memo?: ScanMemo,
371
459
  ): {
372
460
  routes: Record<string, string>;
373
461
  searchSchemas: Record<string, Record<string, string>>;
374
462
  } {
375
463
  visited = visited ?? new Set();
464
+ memo = memo ?? createScanMemo();
376
465
  const realPath = resolve(filePath);
377
466
  const key = variableName ? `${realPath}:${variableName}` : realPath;
378
467
  if (visited.has(key)) {
379
- console.warn(`[rsc-router] Circular include detected, skipping: ${key}`);
468
+ console.warn(`[rango] Circular include detected, skipping: ${key}`);
380
469
  return { routes: {}, searchSchemas: {} };
381
470
  }
382
471
  visited.add(key);
383
472
 
384
473
  let source: string;
385
474
  try {
386
- source = readFileSync(realPath, "utf-8");
475
+ source = readSourceMemoized(memo, realPath);
387
476
  } catch {
388
477
  return { routes: {}, searchSchemas: {} };
389
478
  }
@@ -392,7 +481,11 @@ export function buildCombinedRouteMapWithSearch(
392
481
  if (inlineBlock) {
393
482
  block = inlineBlock;
394
483
  } else if (variableName) {
395
- const extracted = extractUrlsBlockForVariable(source, variableName);
484
+ const extracted = extractUrlsBlockForVariable(
485
+ source,
486
+ variableName,
487
+ parseBlock(memo, source),
488
+ );
396
489
  if (!extracted) return { routes: {}, searchSchemas: {} };
397
490
  block = extracted;
398
491
  } else {
@@ -407,6 +500,7 @@ export function buildCombinedRouteMapWithSearch(
407
500
  visited,
408
501
  searchSchemas,
409
502
  diagnosticsOut,
503
+ memo,
410
504
  );
411
505
 
412
506
  // Remove from visited so sibling branches can include the same variable
@@ -37,12 +37,15 @@ export function formatRouteEntry(
37
37
  ): string {
38
38
  const hasSearch = search && Object.keys(search).length > 0;
39
39
 
40
+ // JSON.stringify the pattern and search values so backslashes and quotes in a
41
+ // route pattern (e.g. a custom regex constraint) survive interpolation into
42
+ // both the type-level string and the runtime NamedRoutes value.
40
43
  if (!hasSearch) {
41
- return ` ${key}: "${pattern}",`;
44
+ return ` ${key}: ${JSON.stringify(pattern)},`;
42
45
  }
43
46
 
44
47
  const searchBody = Object.entries(search!)
45
- .map(([k, v]) => `${k}: "${v}"`)
48
+ .map(([k, v]) => `${k}: ${JSON.stringify(v)}`)
46
49
  .join(", ");
47
- return ` ${key}: { path: "${pattern}", search: { ${searchBody} } },`;
50
+ return ` ${key}: { path: ${JSON.stringify(pattern)}, search: { ${searchBody} } },`;
48
51
  }
@@ -3,7 +3,10 @@ import ts from "typescript";
3
3
  import { extractParamsFromPattern } from "./param-extraction.js";
4
4
  import { extractRoutesFromSource } from "./ast-route-extraction.js";
5
5
  import { generatePerModuleTypesSource } from "./codegen.js";
6
- import { buildCombinedRouteMapWithSearch } from "./include-resolution.js";
6
+ import {
7
+ buildCombinedRouteMapWithSearch,
8
+ createScanMemo,
9
+ } from "./include-resolution.js";
7
10
  import type { ScanFilter } from "./scan-filter.js";
8
11
  import { findTsFiles } from "./scan-filter.js";
9
12
 
@@ -78,10 +81,20 @@ export function writePerModuleRouteTypesForFile(filePath: string): void {
78
81
  if (varNames.length > 0) {
79
82
  // Follow includes recursively via the combined route map builder.
80
83
  // The visited set in buildCombinedRouteMapWithSearch prevents infinite loops.
84
+ // Share one per-file scan memo across all urls() variables so a shared
85
+ // include target is read+parsed once for this file, not once per variable.
81
86
  routes = [];
87
+ const memo = createScanMemo();
82
88
  for (const varName of varNames) {
83
89
  const { routes: routeMap, searchSchemas } =
84
- buildCombinedRouteMapWithSearch(filePath, varName);
90
+ buildCombinedRouteMapWithSearch(
91
+ filePath,
92
+ varName,
93
+ undefined,
94
+ undefined,
95
+ undefined,
96
+ memo,
97
+ );
85
98
  for (const [name, pattern] of Object.entries(routeMap)) {
86
99
  const params = extractParamsFromPattern(pattern);
87
100
  routes.push({
@@ -97,7 +110,10 @@ export function writePerModuleRouteTypesForFile(filePath: string): void {
97
110
  routes = extractRoutesFromSource(source);
98
111
  }
99
112
 
100
- const genPath = filePath.replace(/\.(tsx?)$/, ".gen.ts");
113
+ // Match .ts/.tsx/.js/.jsx (same as router-processing.ts / router-transform.ts).
114
+ // Without the jsx? branch a .jsx/.js source produced genPath === filePath,
115
+ // overwriting the source file instead of writing a sibling .gen.ts.
116
+ const genPath = filePath.replace(/\.(tsx?|jsx?)$/, ".gen.ts");
101
117
 
102
118
  // When a urls() variable was found but static resolution yields zero
103
119
  // routes, write an empty placeholder so generated imports stay
@@ -106,7 +122,7 @@ export function writePerModuleRouteTypesForFile(filePath: string): void {
106
122
  if (varNames.length > 0 && !existsSync(genPath)) {
107
123
  writeFileSync(genPath, generatePerModuleTypesSource([]));
108
124
  console.log(
109
- `[rsc-router] Generated route types (placeholder) -> ${genPath}`,
125
+ `[rango] Generated route types (placeholder) -> ${genPath}`,
110
126
  );
111
127
  }
112
128
  return;
@@ -118,11 +134,11 @@ export function writePerModuleRouteTypesForFile(filePath: string): void {
118
134
  : null;
119
135
  if (existing !== genSource) {
120
136
  writeFileSync(genPath, genSource);
121
- console.log(`[rsc-router] Generated route types -> ${genPath}`);
137
+ console.log(`[rango] Generated route types -> ${genPath}`);
122
138
  }
123
139
  } catch (err) {
124
140
  console.warn(
125
- `[rsc-router] Failed to generate route types for ${filePath}: ${(err as Error).message}`,
141
+ `[rango] Failed to generate route types for ${filePath}: ${(err as Error).message}`,
126
142
  );
127
143
  }
128
144
  }
@@ -15,6 +15,7 @@ import {
15
15
  import ts from "typescript";
16
16
  import { generateRouteTypesSource } from "./codegen.js";
17
17
  import type { ScanFilter } from "./scan-filter.js";
18
+ import { firstCodeMatchIndex } from "./source-scan.js";
18
19
  import {
19
20
  resolveImportedVariable,
20
21
  resolveImportPath,
@@ -38,6 +39,8 @@ function countPublicRouteEntries(source: string): number {
38
39
  }
39
40
 
40
41
  const ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
42
+ // Global variant for the code-region scan (firstCodeMatchIndex sets lastIndex).
43
+ const ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
41
44
 
42
45
  function isRoutableSourceFile(name: string): boolean {
43
46
  return (
@@ -61,7 +64,7 @@ function findRouterFilesRecursive(
61
64
  entries = readdirSync(dir, { withFileTypes: true });
62
65
  } catch (err) {
63
66
  console.warn(
64
- `[rsc-router] Failed to scan directory ${dir}: ${(err as Error).message}`,
67
+ `[rango] Failed to scan directory ${dir}: ${(err as Error).message}`,
65
68
  );
66
69
  return;
67
70
  }
@@ -90,7 +93,17 @@ function findRouterFilesRecursive(
90
93
 
91
94
  try {
92
95
  const source = readFileSync(fullPath, "utf-8");
93
- if (ROUTER_CALL_PATTERN.test(source)) {
96
+ // Fast path: most files contain no `createRouter(` at all, so the cheap
97
+ // raw regex short-circuits before the code-region scan. Only a file that
98
+ // mentions the token (real call OR a comment/string mention) is rescanned
99
+ // over code regions — allocation-free, never building a stripped copy —
100
+ // so a mention inside a comment or string is not mistaken for a real
101
+ // router file (which previously triggered a spurious "Multiple routers
102
+ // found" error).
103
+ if (
104
+ ROUTER_CALL_PATTERN.test(source) &&
105
+ firstCodeMatchIndex(source, ROUTER_CALL_PATTERN_G) >= 0
106
+ ) {
94
107
  routerFilesInDir.push(fullPath);
95
108
  }
96
109
  } catch {
@@ -142,7 +155,7 @@ export function findNestedRouterConflict(
142
155
 
143
156
  export function formatNestedRouterConflictError(
144
157
  conflict: { ancestor: string; nested: string },
145
- prefix = "[rsc-router]",
158
+ prefix = "[rango]",
146
159
  ): string {
147
160
  return (
148
161
  `${prefix} Nested router roots are not supported.\n` +
@@ -309,12 +322,6 @@ export function extractBasenameFromRouter(code: string): string | undefined {
309
322
  return result;
310
323
  }
311
324
 
312
- /** @deprecated Use extractUrlsFromRouter instead */
313
- export function extractUrlsVariableFromRouter(code: string): string | null {
314
- const result = extractUrlsFromRouter(code);
315
- return result?.kind === "variable" ? result.name : null;
316
- }
317
-
318
325
  /** Apply a basename prefix to all route patterns in a result set. */
319
326
  function applyBasenameToRoutes(
320
327
  result: {
@@ -339,6 +346,36 @@ function applyBasenameToRoutes(
339
346
  return { routes: prefixed, searchSchemas: result.searchSchemas };
340
347
  }
341
348
 
349
+ // Filesystem path of the generated route-types file for a router source file.
350
+ // Native separators — matches the self-gen-tracking Map key the watcher compares.
351
+ export function genFileTsPath(sourceFile: string): string {
352
+ const base = pathBasename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
353
+ return join(dirname(sourceFile), `${base}.named-routes.gen.ts`);
354
+ }
355
+
356
+ // Search schemas for the gen file: prefer the runtime manifest's; when it omits
357
+ // them (some module-runner flows) fall back to static parsing filtered to the
358
+ // public route-name set. Returns the runtime value unchanged otherwise.
359
+ export function resolveSearchSchemas(
360
+ publicRouteNames: string[],
361
+ runtimeSchemas: Record<string, Record<string, string>> | undefined,
362
+ sourceFile: string,
363
+ ): Record<string, Record<string, string>> | undefined {
364
+ if (runtimeSchemas && Object.keys(runtimeSchemas).length > 0) {
365
+ return runtimeSchemas;
366
+ }
367
+ const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
368
+ if (Object.keys(staticParsed.searchSchemas).length === 0) {
369
+ return runtimeSchemas;
370
+ }
371
+ const filtered: Record<string, Record<string, string>> = {};
372
+ for (const name of publicRouteNames) {
373
+ const schema = staticParsed.searchSchemas[name];
374
+ if (schema) filtered[name] = schema;
375
+ }
376
+ return Object.keys(filtered).length > 0 ? filtered : runtimeSchemas;
377
+ }
378
+
342
379
  /**
343
380
  * Resolve routes and search schemas from a router source file by following the
344
381
  * variable passed to `.routes(...)` or `urls: ...` in createRouter options,
@@ -528,7 +565,10 @@ export function findRouterFiles(root: string, filter?: ScanFilter): string[] {
528
565
  export function writeCombinedRouteTypes(
529
566
  root: string,
530
567
  knownRouterFiles?: string[],
531
- opts?: { preserveIfLarger?: boolean },
568
+ opts?: {
569
+ preserveIfLarger?: boolean;
570
+ onWrite?: (outPath: string, content: string) => void;
571
+ },
532
572
  ): void {
533
573
  // Delete old combined named-routes.gen.ts if it exists (stale from older versions)
534
574
  try {
@@ -536,7 +576,7 @@ export function writeCombinedRouteTypes(
536
576
  if (existsSync(oldCombinedPath)) {
537
577
  unlinkSync(oldCombinedPath);
538
578
  console.log(
539
- `[rsc-router] Removed stale combined route types: ${oldCombinedPath}`,
579
+ `[rango] Removed stale combined route types: ${oldCombinedPath}`,
540
580
  );
541
581
  }
542
582
  } catch {}
@@ -566,24 +606,15 @@ export function writeCombinedRouteTypes(
566
606
  if (!extractUrlsFromRouter(routerSource)) continue;
567
607
  }
568
608
 
569
- const routerBasename = pathBasename(routerFilePath).replace(
570
- /\.(tsx?|jsx?)$/,
571
- "",
572
- );
573
- const outPath = join(
574
- dirname(routerFilePath),
575
- `${routerBasename}.named-routes.gen.ts`,
576
- );
609
+ const outPath = genFileTsPath(routerFilePath);
577
610
  const existing = existsSync(outPath)
578
611
  ? readFileSync(outPath, "utf-8")
579
612
  : null;
580
613
 
581
- // When the static parser can't extract routes (e.g. callback-style urls()),
582
- // write an empty placeholder so the build-time transform's injected import
583
- // resolves. Runtime discovery will overwrite this with the real routes.
584
614
  if (Object.keys(result.routes).length === 0) {
585
615
  if (!existing) {
586
616
  const emptySource = generateRouteTypesSource({});
617
+ opts?.onWrite?.(outPath, emptySource);
587
618
  writeFileSync(outPath, emptySource);
588
619
  }
589
620
  continue;
@@ -595,11 +626,6 @@ export function writeCombinedRouteTypes(
595
626
  hasSearchSchemas ? result.searchSchemas : undefined,
596
627
  );
597
628
  if (existing !== source) {
598
- // On initial dev startup, don't overwrite a file from runtime discovery
599
- // (which has all dynamic routes) with a smaller set from the static
600
- // parser. The static parser can't see routes generated by Array.from()
601
- // or other dynamic code. During HMR (file watcher), always write so
602
- // newly added routes appear immediately.
603
629
  if (opts?.preserveIfLarger && existing) {
604
630
  const existingCount = countPublicRouteEntries(existing);
605
631
  const newCount = Object.keys(result.routes).filter(
@@ -609,9 +635,10 @@ export function writeCombinedRouteTypes(
609
635
  continue;
610
636
  }
611
637
  }
638
+ opts?.onWrite?.(outPath, source);
612
639
  writeFileSync(outPath, source);
613
640
  console.log(
614
- `[rsc-router] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`,
641
+ `[rango] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`,
615
642
  );
616
643
  }
617
644
  }
@@ -54,7 +54,7 @@ export function findTsFiles(dir: string, filter?: ScanFilter): string[] {
54
54
  entries = readdirSync(dir, { withFileTypes: true });
55
55
  } catch (err) {
56
56
  console.warn(
57
- `[rsc-router] Failed to scan directory ${dir}: ${(err as Error).message}`,
57
+ `[rango] Failed to scan directory ${dir}: ${(err as Error).message}`,
58
58
  );
59
59
  return results;
60
60
  }