@rangojs/router 0.0.0-experimental.9c9afef3 → 0.0.0-experimental.a014d2b7

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 (402) hide show
  1. package/AGENTS.md +8 -0
  2. package/README.md +245 -49
  3. package/dist/bin/rango.js +440 -133
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +3373 -1176
  6. package/dist/vite/index.js.bak +5448 -0
  7. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  8. package/package.json +68 -14
  9. package/skills/api-client/SKILL.md +211 -0
  10. package/skills/breadcrumbs/SKILL.md +64 -2
  11. package/skills/bundle-analysis/SKILL.md +159 -0
  12. package/skills/cache-guide/SKILL.md +224 -32
  13. package/skills/caching/SKILL.md +279 -17
  14. package/skills/composability/SKILL.md +27 -3
  15. package/skills/css/SKILL.md +76 -0
  16. package/skills/debug-manifest/SKILL.md +4 -2
  17. package/skills/document-cache/SKILL.md +78 -55
  18. package/skills/handler-use/SKILL.md +364 -0
  19. package/skills/hooks/SKILL.md +250 -30
  20. package/skills/host-router/SKILL.md +83 -23
  21. package/skills/i18n/SKILL.md +276 -0
  22. package/skills/intercept/SKILL.md +87 -18
  23. package/skills/layout/SKILL.md +35 -9
  24. package/skills/links/SKILL.md +249 -17
  25. package/skills/loader/SKILL.md +235 -9
  26. package/skills/middleware/SKILL.md +52 -13
  27. package/skills/migrate-nextjs/SKILL.md +584 -0
  28. package/skills/migrate-react-router/SKILL.md +771 -0
  29. package/skills/mime-routes/SKILL.md +28 -1
  30. package/skills/observability/SKILL.md +172 -0
  31. package/skills/parallel/SKILL.md +77 -7
  32. package/skills/prerender/SKILL.md +172 -125
  33. package/skills/rango/SKILL.md +251 -22
  34. package/skills/react-compiler/SKILL.md +168 -0
  35. package/skills/response-routes/SKILL.md +123 -48
  36. package/skills/route/SKILL.md +70 -5
  37. package/skills/router-setup/SKILL.md +65 -8
  38. package/skills/scripts/SKILL.md +179 -0
  39. package/skills/server-actions/SKILL.md +775 -0
  40. package/skills/streams-and-websockets/SKILL.md +283 -0
  41. package/skills/tailwind/SKILL.md +27 -3
  42. package/skills/testing/SKILL.md +130 -0
  43. package/skills/testing/bindings.md +103 -0
  44. package/skills/testing/cache-prerender.md +127 -0
  45. package/skills/testing/client-components.md +124 -0
  46. package/skills/testing/e2e-parity.md +125 -0
  47. package/skills/testing/flight.md +91 -0
  48. package/skills/testing/handles.md +129 -0
  49. package/skills/testing/loader.md +128 -0
  50. package/skills/testing/middleware.md +99 -0
  51. package/skills/testing/render-handler.md +122 -0
  52. package/skills/testing/response-routes.md +95 -0
  53. package/skills/testing/reverse-and-types.md +84 -0
  54. package/skills/testing/server-actions.md +107 -0
  55. package/skills/testing/server-tree.md +128 -0
  56. package/skills/testing/setup.md +123 -0
  57. package/skills/typesafety/SKILL.md +322 -29
  58. package/skills/use-cache/SKILL.md +57 -14
  59. package/skills/view-transitions/SKILL.md +337 -0
  60. package/src/__augment-tests__/augment.ts +81 -0
  61. package/src/__augment-tests__/augmented.check.ts +116 -0
  62. package/src/__internal.ts +1 -66
  63. package/src/browser/action-coordinator.ts +53 -36
  64. package/src/browser/action-fence.ts +47 -0
  65. package/src/browser/app-shell.ts +39 -0
  66. package/src/browser/app-version.ts +14 -0
  67. package/src/browser/connection-warmup.ts +134 -0
  68. package/src/browser/cookie-name.ts +140 -0
  69. package/src/browser/event-controller.ts +192 -150
  70. package/src/browser/history-state.ts +21 -0
  71. package/src/browser/index.ts +3 -3
  72. package/src/browser/invalidate-client-cache.ts +52 -0
  73. package/src/browser/navigation-bridge.ts +131 -30
  74. package/src/browser/navigation-client.ts +186 -100
  75. package/src/browser/navigation-store-handle.ts +38 -0
  76. package/src/browser/navigation-store.ts +157 -74
  77. package/src/browser/navigation-transaction.ts +9 -59
  78. package/src/browser/network-error-handler.ts +34 -7
  79. package/src/browser/partial-update.ts +165 -112
  80. package/src/browser/prefetch/cache.ts +205 -62
  81. package/src/browser/prefetch/fetch.ts +347 -39
  82. package/src/browser/prefetch/queue.ts +42 -8
  83. package/src/browser/rango-state.ts +158 -76
  84. package/src/browser/react/Link.tsx +102 -15
  85. package/src/browser/react/NavigationProvider.tsx +295 -119
  86. package/src/browser/react/ScrollRestoration.tsx +10 -6
  87. package/src/browser/react/context.ts +7 -2
  88. package/src/browser/react/deferred-handle-resolution.ts +75 -0
  89. package/src/browser/react/filter-segment-order.ts +66 -7
  90. package/src/browser/react/index.ts +0 -48
  91. package/src/browser/react/location-state-shared.ts +178 -8
  92. package/src/browser/react/location-state.ts +39 -14
  93. package/src/browser/react/use-action.ts +6 -15
  94. package/src/browser/react/use-handle.ts +23 -69
  95. package/src/browser/react/use-href.tsx +8 -1
  96. package/src/browser/react/use-link-status.ts +33 -8
  97. package/src/browser/react/use-navigation.ts +32 -7
  98. package/src/browser/react/use-params.ts +20 -10
  99. package/src/browser/react/use-reverse.ts +106 -0
  100. package/src/browser/react/use-router.ts +46 -11
  101. package/src/browser/react/use-search-params.ts +0 -5
  102. package/src/browser/react/use-segments.ts +11 -21
  103. package/src/browser/response-adapter.ts +99 -8
  104. package/src/browser/rsc-router.tsx +114 -24
  105. package/src/browser/scroll-restoration.ts +37 -22
  106. package/src/browser/segment-reconciler.ts +36 -14
  107. package/src/browser/segment-structure-assert.ts +2 -2
  108. package/src/browser/server-action-bridge.ts +222 -72
  109. package/src/browser/types.ts +102 -12
  110. package/src/browser/validate-redirect-origin.ts +43 -16
  111. package/src/build/collect-fallback-refs.ts +107 -0
  112. package/src/build/generate-manifest.ts +65 -40
  113. package/src/build/generate-route-types.ts +5 -1
  114. package/src/build/index.ts +8 -2
  115. package/src/build/prefix-tree-utils.ts +123 -0
  116. package/src/build/route-trie.ts +165 -36
  117. package/src/build/route-types/ast-route-extraction.ts +15 -8
  118. package/src/build/route-types/codegen.ts +16 -5
  119. package/src/build/route-types/include-resolution.ts +125 -24
  120. package/src/build/route-types/param-extraction.ts +6 -3
  121. package/src/build/route-types/per-module-writer.ts +22 -6
  122. package/src/build/route-types/router-processing.ts +260 -94
  123. package/src/build/route-types/scan-filter.ts +9 -2
  124. package/src/build/route-types/source-scan.ts +216 -0
  125. package/src/build/runtime-discovery.ts +9 -20
  126. package/src/cache/cache-error.ts +104 -0
  127. package/src/cache/cache-key-utils.ts +29 -13
  128. package/src/cache/cache-policy.ts +108 -34
  129. package/src/cache/cache-runtime.ts +224 -41
  130. package/src/cache/cache-scope.ts +188 -82
  131. package/src/cache/cache-tag.ts +103 -0
  132. package/src/cache/cf/cf-base64.ts +33 -0
  133. package/src/cache/cf/cf-cache-constants.ts +127 -0
  134. package/src/cache/cf/cf-cache-store.ts +1989 -378
  135. package/src/cache/cf/cf-cache-types.ts +349 -0
  136. package/src/cache/cf/cf-kv-utils.ts +46 -0
  137. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  138. package/src/cache/cf/index.ts +6 -16
  139. package/src/cache/document-cache.ts +89 -21
  140. package/src/cache/handle-snapshot.ts +70 -0
  141. package/src/cache/index.ts +10 -20
  142. package/src/cache/memory-segment-store.ts +136 -37
  143. package/src/cache/profile-registry.ts +46 -31
  144. package/src/cache/read-through-swr.ts +56 -12
  145. package/src/cache/segment-codec.ts +9 -17
  146. package/src/cache/tag-invalidation.ts +230 -0
  147. package/src/cache/types.ts +37 -100
  148. package/src/client.rsc.tsx +44 -21
  149. package/src/client.tsx +119 -290
  150. package/src/cloudflare/index.ts +11 -0
  151. package/src/cloudflare/tracing.ts +109 -0
  152. package/src/component-utils.ts +19 -0
  153. package/src/components/DefaultDocument.tsx +8 -2
  154. package/src/context-var.ts +18 -6
  155. package/src/decode-loader-results.ts +52 -0
  156. package/src/defer.ts +196 -0
  157. package/src/deps/ssr.ts +0 -1
  158. package/src/encode-kv.ts +49 -0
  159. package/src/errors.ts +30 -4
  160. package/src/escape-script.ts +52 -0
  161. package/src/handle.ts +70 -22
  162. package/src/handles/MetaTags.tsx +62 -19
  163. package/src/handles/Scripts.tsx +183 -0
  164. package/src/handles/breadcrumbs.ts +37 -8
  165. package/src/handles/is-thenable.ts +19 -0
  166. package/src/handles/meta.ts +51 -40
  167. package/src/handles/script.ts +244 -0
  168. package/src/host/cookie-handler.ts +9 -60
  169. package/src/host/errors.ts +0 -24
  170. package/src/host/index.ts +8 -2
  171. package/src/host/pattern-matcher.ts +23 -52
  172. package/src/host/router.ts +107 -99
  173. package/src/host/testing.ts +40 -27
  174. package/src/host/types.ts +37 -4
  175. package/src/host/utils.ts +1 -1
  176. package/src/href-client.ts +137 -22
  177. package/src/index.rsc.ts +99 -13
  178. package/src/index.ts +139 -19
  179. package/src/internal-debug.ts +11 -10
  180. package/src/loader-store.ts +500 -0
  181. package/src/loader.rsc.ts +20 -13
  182. package/src/loader.ts +12 -11
  183. package/src/missing-id-error.ts +68 -0
  184. package/src/outlet-context.ts +1 -1
  185. package/src/outlet-provider.tsx +1 -5
  186. package/src/prerender/param-hash.ts +16 -16
  187. package/src/prerender/store.ts +37 -41
  188. package/src/prerender.ts +198 -82
  189. package/src/redirect-origin.ts +100 -0
  190. package/src/regex-escape.ts +8 -0
  191. package/src/render-error-thrower.tsx +20 -0
  192. package/src/response-utils.ts +62 -0
  193. package/src/reverse.ts +65 -15
  194. package/src/root-error-boundary.tsx +1 -19
  195. package/src/route-content-wrapper.tsx +19 -77
  196. package/src/route-definition/dsl-helpers.ts +461 -304
  197. package/src/route-definition/helper-factories.ts +28 -140
  198. package/src/route-definition/helpers-types.ts +143 -69
  199. package/src/route-definition/index.ts +4 -2
  200. package/src/route-definition/redirect.ts +51 -10
  201. package/src/route-definition/resolve-handler-use.ts +160 -0
  202. package/src/route-definition/use-item-types.ts +29 -0
  203. package/src/route-map-builder.ts +0 -16
  204. package/src/route-types.ts +37 -46
  205. package/src/router/basename.ts +14 -0
  206. package/src/router/content-negotiation.ts +164 -17
  207. package/src/router/error-handling.ts +45 -18
  208. package/src/router/find-match.ts +44 -23
  209. package/src/router/handler-context.ts +52 -31
  210. package/src/router/instrument.ts +350 -0
  211. package/src/router/intercept-resolution.ts +48 -24
  212. package/src/router/lazy-includes.ts +15 -52
  213. package/src/router/loader-resolution.ts +268 -56
  214. package/src/router/logging.ts +0 -6
  215. package/src/router/manifest.ts +40 -42
  216. package/src/router/match-api.ts +124 -204
  217. package/src/router/match-context.ts +0 -22
  218. package/src/router/match-handlers.ts +58 -58
  219. package/src/router/match-middleware/background-revalidation.ts +40 -24
  220. package/src/router/match-middleware/cache-lookup.ts +170 -276
  221. package/src/router/match-middleware/cache-store.ts +64 -52
  222. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  223. package/src/router/match-middleware/segment-resolution.ts +45 -14
  224. package/src/router/match-pipelines.ts +1 -42
  225. package/src/router/match-result.ts +87 -39
  226. package/src/router/metrics.ts +0 -34
  227. package/src/router/middleware-types.ts +7 -140
  228. package/src/router/middleware.ts +266 -169
  229. package/src/router/navigation-snapshot.ts +131 -0
  230. package/src/router/params-util.ts +23 -0
  231. package/src/router/pattern-matching.ts +132 -90
  232. package/src/router/prefetch-cache-ttl.ts +51 -0
  233. package/src/router/prerender-match.ts +195 -56
  234. package/src/router/preview-match.ts +32 -102
  235. package/src/router/request-classification.ts +276 -0
  236. package/src/router/revalidation.ts +123 -73
  237. package/src/router/route-snapshot.ts +244 -0
  238. package/src/router/router-context.ts +3 -28
  239. package/src/router/router-interfaces.ts +115 -35
  240. package/src/router/router-options.ts +172 -15
  241. package/src/router/router-registry.ts +2 -5
  242. package/src/router/segment-resolution/fresh.ts +162 -84
  243. package/src/router/segment-resolution/helpers.ts +86 -6
  244. package/src/router/segment-resolution/loader-cache.ts +76 -39
  245. package/src/router/segment-resolution/revalidation.ts +351 -321
  246. package/src/router/segment-resolution/static-store.ts +19 -5
  247. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  248. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  249. package/src/router/segment-resolution.ts +5 -1
  250. package/src/router/segment-wrappers.ts +6 -5
  251. package/src/router/state-cookie-name.ts +33 -0
  252. package/src/router/substitute-pattern-params.ts +56 -0
  253. package/src/router/telemetry-otel.ts +161 -199
  254. package/src/router/telemetry.ts +96 -19
  255. package/src/router/timeout.ts +0 -20
  256. package/src/router/tracing.ts +206 -0
  257. package/src/router/trie-matching.ts +163 -59
  258. package/src/router/types.ts +9 -63
  259. package/src/router/url-params.ts +44 -0
  260. package/src/router.ts +157 -54
  261. package/src/rsc/handler-context.ts +3 -2
  262. package/src/rsc/handler.ts +655 -529
  263. package/src/rsc/helpers.ts +168 -46
  264. package/src/rsc/index.ts +2 -5
  265. package/src/rsc/json-route-result.ts +38 -0
  266. package/src/rsc/loader-fetch.ts +122 -31
  267. package/src/rsc/manifest-init.ts +33 -42
  268. package/src/rsc/origin-guard.ts +39 -25
  269. package/src/rsc/progressive-enhancement.ts +131 -14
  270. package/src/rsc/redirect-guard.ts +99 -0
  271. package/src/rsc/response-cache-serve.ts +238 -0
  272. package/src/rsc/response-error.ts +79 -12
  273. package/src/rsc/response-route-handler.ts +99 -189
  274. package/src/rsc/rsc-rendering.ts +109 -74
  275. package/src/rsc/runtime-warnings.ts +23 -10
  276. package/src/rsc/server-action.ts +287 -115
  277. package/src/rsc/ssr-setup.ts +18 -2
  278. package/src/rsc/transition-gate.ts +89 -0
  279. package/src/rsc/types.ts +29 -9
  280. package/src/runtime-env.ts +18 -0
  281. package/src/search-params.ts +35 -30
  282. package/src/segment-content-promise.ts +67 -0
  283. package/src/segment-loader-promise.ts +149 -0
  284. package/src/segment-system.tsx +236 -202
  285. package/src/serialize.ts +243 -0
  286. package/src/server/context.ts +224 -52
  287. package/src/server/cookie-parse.ts +32 -0
  288. package/src/server/cookie-store.ts +80 -5
  289. package/src/server/handle-store.ts +40 -38
  290. package/src/server/loader-registry.ts +38 -46
  291. package/src/server/request-context.ts +401 -173
  292. package/src/ssr/index.tsx +24 -16
  293. package/src/static-handler.ts +27 -18
  294. package/src/testing/cache-status.ts +162 -0
  295. package/src/testing/collect-handle.ts +40 -0
  296. package/src/testing/dispatch.ts +701 -0
  297. package/src/testing/dom.entry.ts +22 -0
  298. package/src/testing/e2e/fixture.ts +188 -0
  299. package/src/testing/e2e/index.ts +128 -0
  300. package/src/testing/e2e/matchers.ts +35 -0
  301. package/src/testing/e2e/page-helpers.ts +272 -0
  302. package/src/testing/e2e/parity.ts +387 -0
  303. package/src/testing/e2e/server.ts +195 -0
  304. package/src/testing/flight-matchers.ts +97 -0
  305. package/src/testing/flight-normalize.ts +11 -0
  306. package/src/testing/flight-runtime.d.ts +57 -0
  307. package/src/testing/flight-tree.ts +682 -0
  308. package/src/testing/flight.entry.ts +52 -0
  309. package/src/testing/flight.ts +257 -0
  310. package/src/testing/generated-routes.ts +183 -0
  311. package/src/testing/index.ts +105 -0
  312. package/src/testing/internal/context.ts +371 -0
  313. package/src/testing/internal/flight-client-globals.ts +30 -0
  314. package/src/testing/internal/seed-vars.ts +54 -0
  315. package/src/testing/render-handler.ts +357 -0
  316. package/src/testing/render-route.tsx +581 -0
  317. package/src/testing/run-loader.ts +385 -0
  318. package/src/testing/run-middleware.ts +205 -0
  319. package/src/testing/run-transition-when.ts +164 -0
  320. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  321. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  322. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  323. package/src/testing/vitest-stubs/version.ts +5 -0
  324. package/src/testing/vitest.ts +305 -0
  325. package/src/theme/ThemeProvider.tsx +20 -58
  326. package/src/theme/ThemeScript.tsx +7 -9
  327. package/src/theme/constants.ts +52 -13
  328. package/src/theme/index.ts +0 -7
  329. package/src/theme/theme-context.ts +1 -5
  330. package/src/theme/theme-script.ts +22 -21
  331. package/src/theme/use-theme.ts +0 -3
  332. package/src/types/boundaries.ts +0 -35
  333. package/src/types/cache-types.ts +17 -8
  334. package/src/types/error-types.ts +30 -90
  335. package/src/types/global-namespace.ts +54 -41
  336. package/src/types/handler-context.ts +125 -71
  337. package/src/types/index.ts +3 -10
  338. package/src/types/loader-types.ts +40 -11
  339. package/src/types/request-scope.ts +112 -0
  340. package/src/types/route-config.ts +6 -50
  341. package/src/types/route-entry.ts +12 -7
  342. package/src/types/segments.ts +136 -15
  343. package/src/urls/include-helper.ts +33 -70
  344. package/src/urls/index.ts +1 -11
  345. package/src/urls/path-helper-types.ts +68 -18
  346. package/src/urls/path-helper.ts +57 -111
  347. package/src/urls/pattern-types.ts +48 -19
  348. package/src/urls/response-types.ts +25 -22
  349. package/src/urls/type-extraction.ts +58 -139
  350. package/src/urls/urls-function.ts +1 -19
  351. package/src/use-loader.tsx +346 -89
  352. package/src/vite/debug.ts +185 -0
  353. package/src/vite/discovery/bundle-postprocess.ts +36 -38
  354. package/src/vite/discovery/discover-routers.ts +130 -85
  355. package/src/vite/discovery/discovery-errors.ts +194 -0
  356. package/src/vite/discovery/gate-state.ts +171 -0
  357. package/src/vite/discovery/prerender-collection.ts +214 -132
  358. package/src/vite/discovery/route-types-writer.ts +40 -84
  359. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  360. package/src/vite/discovery/state.ts +57 -4
  361. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  362. package/src/vite/index.ts +6 -0
  363. package/src/vite/inject-client-debug.ts +36 -0
  364. package/src/vite/plugin-types.ts +178 -5
  365. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  366. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  367. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  368. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  369. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  370. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  371. package/src/vite/plugins/expose-action-id.ts +48 -95
  372. package/src/vite/plugins/expose-id-utils.ts +96 -51
  373. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  374. package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
  375. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  376. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  377. package/src/vite/plugins/expose-internal-ids.ts +553 -317
  378. package/src/vite/plugins/performance-tracks.ts +64 -170
  379. package/src/vite/plugins/refresh-cmd.ts +89 -27
  380. package/src/vite/plugins/use-cache-transform.ts +73 -83
  381. package/src/vite/plugins/version-injector.ts +40 -29
  382. package/src/vite/plugins/version-plugin.ts +37 -40
  383. package/src/vite/plugins/virtual-entries.ts +39 -25
  384. package/src/vite/rango.ts +118 -114
  385. package/src/vite/router-discovery.ts +941 -142
  386. package/src/vite/utils/ast-handler-extract.ts +26 -35
  387. package/src/vite/utils/banner.ts +1 -1
  388. package/src/vite/utils/bundle-analysis.ts +10 -15
  389. package/src/vite/utils/client-chunks.ts +184 -0
  390. package/src/vite/utils/directive-prologue.ts +40 -0
  391. package/src/vite/utils/forward-user-plugins.ts +171 -0
  392. package/src/vite/utils/manifest-utils.ts +4 -59
  393. package/src/vite/utils/package-resolution.ts +20 -52
  394. package/src/vite/utils/prerender-utils.ts +81 -34
  395. package/src/vite/utils/shared-utils.ts +92 -42
  396. package/src/browser/action-response-classifier.ts +0 -99
  397. package/src/browser/debug-channel.ts +0 -93
  398. package/src/browser/react/use-client-cache.ts +0 -58
  399. package/src/browser/shallow.ts +0 -40
  400. package/src/handles/index.ts +0 -7
  401. package/src/network-error-thrower.tsx +0 -23
  402. package/src/router/middleware-cookies.ts +0 -55
package/dist/bin/rango.js CHANGED
@@ -1,8 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  var __defProp = Object.defineProperty;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __esm = (fn, res) => function __init() {
5
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
4
+ var __esm = (fn, res, err) => function __init() {
5
+ if (err) throw err[0];
6
+ try {
7
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ } catch (e) {
9
+ throw err = [e], e;
10
+ }
6
11
  };
7
12
  var __export = (target, all) => {
8
13
  for (var name in all)
@@ -22,10 +27,10 @@ function extractParamsFromPattern(pattern) {
22
27
  function formatRouteEntry(key, pattern, _params, search) {
23
28
  const hasSearch = search && Object.keys(search).length > 0;
24
29
  if (!hasSearch) {
25
- return ` ${key}: "${pattern}",`;
30
+ return ` ${key}: ${JSON.stringify(pattern)},`;
26
31
  }
27
- const searchBody = Object.entries(search).map(([k, v]) => `${k}: "${v}"`).join(", ");
28
- return ` ${key}: { path: "${pattern}", search: { ${searchBody} } },`;
32
+ const searchBody = Object.entries(search).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join(", ");
33
+ return ` ${key}: { path: ${JSON.stringify(pattern)}, search: { ${searchBody} } },`;
29
34
  }
30
35
  var init_param_extraction = __esm({
31
36
  "src/build/route-types/param-extraction.ts"() {
@@ -59,8 +64,8 @@ var init_ast_helpers = __esm({
59
64
 
60
65
  // src/build/route-types/ast-route-extraction.ts
61
66
  import ts2 from "typescript";
62
- function extractRoutesFromSource(code) {
63
- const sourceFile = ts2.createSourceFile(
67
+ function extractRoutesFromSource(code, sourceFileArg) {
68
+ const sourceFile = sourceFileArg ?? ts2.createSourceFile(
64
69
  "input.tsx",
65
70
  code,
66
71
  ts2.ScriptTarget.Latest,
@@ -139,7 +144,7 @@ function generatePerModuleTypesSource(routes) {
139
144
  const valid = routes.filter(({ name }) => {
140
145
  if (!name || /["'\\`\n\r]/.test(name)) {
141
146
  console.warn(
142
- `[rsc-router] Skipping route with invalid name: ${JSON.stringify(name)}`
147
+ `[rango] Skipping route with invalid name: ${JSON.stringify(name)}`
143
148
  );
144
149
  return false;
145
150
  }
@@ -149,7 +154,7 @@ function generatePerModuleTypesSource(routes) {
149
154
  for (const { name, pattern, params, search } of valid) {
150
155
  if (deduped.has(name)) {
151
156
  console.warn(
152
- `[rsc-router] Duplicate route name "${name}" \u2014 keeping first definition`
157
+ `[rango] Duplicate route name "${name}" \u2014 keeping first definition`
153
158
  );
154
159
  continue;
155
160
  }
@@ -185,9 +190,13 @@ export const NamedRoutes = {
185
190
  ${objectBody}
186
191
  } as const;
187
192
 
193
+ // Aliased so the augmentation below does not pay a homomorphic mapped-type
194
+ // instantiation per route; \`as const\` already makes the members readonly.
195
+ type NamedRoutesShape = typeof NamedRoutes;
196
+
188
197
  declare global {
189
- namespace RSCRouter {
190
- interface GeneratedRouteMap extends Readonly<typeof NamedRoutes> {}
198
+ namespace Rango {
199
+ interface GeneratedRouteMap extends NamedRoutesShape {}
191
200
  }
192
201
  }
193
202
  `;
@@ -211,14 +220,15 @@ function findTsFiles(dir, filter) {
211
220
  entries = readdirSync(dir, { withFileTypes: true });
212
221
  } catch (err) {
213
222
  console.warn(
214
- `[rsc-router] Failed to scan directory ${dir}: ${err.message}`
223
+ `[rango] Failed to scan directory ${dir}: ${err.message}`
215
224
  );
216
225
  return results;
217
226
  }
218
227
  for (const entry of entries) {
219
228
  const fullPath = join(dir, entry.name);
220
229
  if (entry.isDirectory()) {
221
- if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
230
+ if (entry.name === "node_modules" || entry.name.startsWith(".") || entry.name === "dist" || entry.name === "build" || entry.name === "coverage")
231
+ continue;
222
232
  results.push(...findTsFiles(fullPath, filter));
223
233
  } else if ((entry.name.endsWith(".ts") || entry.name.endsWith(".tsx") || entry.name.endsWith(".js") || entry.name.endsWith(".jsx")) && !entry.name.includes(".gen.")) {
224
234
  if (filter && !filter(fullPath)) continue;
@@ -237,6 +247,33 @@ var init_scan_filter = __esm({
237
247
  import { readFileSync, existsSync } from "node:fs";
238
248
  import { dirname, resolve } from "node:path";
239
249
  import ts3 from "typescript";
250
+ function createScanMemo() {
251
+ return { files: /* @__PURE__ */ new Map(), blockSourceFiles: /* @__PURE__ */ new Map() };
252
+ }
253
+ function parseBlock(memo, block) {
254
+ if (memo) {
255
+ const cached = memo.blockSourceFiles.get(block);
256
+ if (cached) return cached;
257
+ }
258
+ const sf = ts3.createSourceFile(
259
+ "input.tsx",
260
+ block,
261
+ ts3.ScriptTarget.Latest,
262
+ true,
263
+ ts3.ScriptKind.TSX
264
+ );
265
+ if (memo) memo.blockSourceFiles.set(block, sf);
266
+ return sf;
267
+ }
268
+ function readSourceMemoized(memo, realPath) {
269
+ if (memo) {
270
+ const cached = memo.files.get(realPath);
271
+ if (cached !== void 0) return cached;
272
+ }
273
+ const source = readFileSync(realPath, "utf-8");
274
+ if (memo) memo.files.set(realPath, source);
275
+ return source;
276
+ }
240
277
  function extractNamePrefixFromInclude(node) {
241
278
  if (node.arguments.length >= 3) {
242
279
  const thirdArg = node.arguments[2];
@@ -252,8 +289,8 @@ function extractNamePrefixFromInclude(node) {
252
289
  }
253
290
  return null;
254
291
  }
255
- function extractIncludesWithDiagnostics(code) {
256
- const sourceFile = ts3.createSourceFile(
292
+ function extractIncludesWithDiagnostics(code, sourceFileArg) {
293
+ const sourceFile = sourceFileArg ?? ts3.createSourceFile(
257
294
  "input.tsx",
258
295
  code,
259
296
  ts3.ScriptTarget.Latest,
@@ -307,7 +344,7 @@ function extractIncludesWithDiagnostics(code) {
307
344
  return { resolved, unresolvable };
308
345
  }
309
346
  function resolveImportedVariable(code, localName) {
310
- const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
347
+ const importRegex = /import\s*(?:[\w$]+\s*,\s*)?\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
311
348
  let match;
312
349
  while ((match = importRegex.exec(code)) !== null) {
313
350
  const imports = match[1];
@@ -344,8 +381,8 @@ function resolveImportPath(importSpec, fromFile) {
344
381
  }
345
382
  return null;
346
383
  }
347
- function extractUrlsBlockForVariable(code, varName) {
348
- const sourceFile = ts3.createSourceFile(
384
+ function extractUrlsBlockForVariable(code, varName, sourceFileArg) {
385
+ const sourceFile = sourceFileArg ?? ts3.createSourceFile(
349
386
  "input.tsx",
350
387
  code,
351
388
  ts3.ScriptTarget.Latest,
@@ -367,16 +404,20 @@ function extractUrlsBlockForVariable(code, varName) {
367
404
  visit(sourceFile);
368
405
  return result;
369
406
  }
370
- function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSchemasOut, diagnosticsOut) {
407
+ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSchemasOut, diagnosticsOut, memo) {
371
408
  const routeMap = {};
372
- const localRoutes = extractRoutesFromSource(block);
409
+ const blockSourceFile = parseBlock(memo, block);
410
+ const localRoutes = extractRoutesFromSource(block, blockSourceFile);
373
411
  for (const { name, pattern, search } of localRoutes) {
374
412
  routeMap[name] = pattern;
375
413
  if (search && searchSchemasOut) {
376
414
  searchSchemasOut[name] = search;
377
415
  }
378
416
  }
379
- const { resolved: includes, unresolvable } = extractIncludesWithDiagnostics(block);
417
+ const { resolved: includes, unresolvable } = extractIncludesWithDiagnostics(
418
+ block,
419
+ blockSourceFile
420
+ );
380
421
  if (diagnosticsOut) {
381
422
  for (const entry of unresolvable) {
382
423
  diagnosticsOut.push({ ...entry, sourceFile: filePath });
@@ -403,12 +444,15 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
403
444
  targetFile,
404
445
  imported.exportedName,
405
446
  visited,
406
- diagnosticsOut
447
+ diagnosticsOut,
448
+ void 0,
449
+ memo
407
450
  );
408
451
  } else {
409
452
  const sameFileBlock = extractUrlsBlockForVariable(
410
453
  fullSource,
411
- variableName
454
+ variableName,
455
+ parseBlock(memo, fullSource)
412
456
  );
413
457
  if (!sameFileBlock) {
414
458
  if (diagnosticsOut) {
@@ -426,7 +470,9 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
426
470
  filePath,
427
471
  variableName,
428
472
  visited,
429
- diagnosticsOut
473
+ diagnosticsOut,
474
+ void 0,
475
+ memo
430
476
  );
431
477
  }
432
478
  if (namePrefix === null) {
@@ -450,24 +496,31 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
450
496
  }
451
497
  return routeMap;
452
498
  }
453
- function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut) {
499
+ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut, inlineBlock, memo) {
454
500
  visited = visited ?? /* @__PURE__ */ new Set();
501
+ memo = memo ?? createScanMemo();
455
502
  const realPath = resolve(filePath);
456
503
  const key = variableName ? `${realPath}:${variableName}` : realPath;
457
504
  if (visited.has(key)) {
458
- console.warn(`[rsc-router] Circular include detected, skipping: ${key}`);
505
+ console.warn(`[rango] Circular include detected, skipping: ${key}`);
459
506
  return { routes: {}, searchSchemas: {} };
460
507
  }
461
508
  visited.add(key);
462
509
  let source;
463
510
  try {
464
- source = readFileSync(realPath, "utf-8");
511
+ source = readSourceMemoized(memo, realPath);
465
512
  } catch {
466
513
  return { routes: {}, searchSchemas: {} };
467
514
  }
468
515
  let block;
469
- if (variableName) {
470
- const extracted = extractUrlsBlockForVariable(source, variableName);
516
+ if (inlineBlock) {
517
+ block = inlineBlock;
518
+ } else if (variableName) {
519
+ const extracted = extractUrlsBlockForVariable(
520
+ source,
521
+ variableName,
522
+ parseBlock(memo, source)
523
+ );
471
524
  if (!extracted) return { routes: {}, searchSchemas: {} };
472
525
  block = extracted;
473
526
  } else {
@@ -480,7 +533,8 @@ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagno
480
533
  realPath,
481
534
  visited,
482
535
  searchSchemas,
483
- diagnosticsOut
536
+ diagnosticsOut,
537
+ memo
484
538
  );
485
539
  visited.delete(key);
486
540
  return { routes, searchSchemas };
@@ -525,8 +579,16 @@ function writePerModuleRouteTypesForFile(filePath) {
525
579
  let routes;
526
580
  if (varNames.length > 0) {
527
581
  routes = [];
582
+ const memo = createScanMemo();
528
583
  for (const varName of varNames) {
529
- const { routes: routeMap, searchSchemas } = buildCombinedRouteMapWithSearch(filePath, varName);
584
+ const { routes: routeMap, searchSchemas } = buildCombinedRouteMapWithSearch(
585
+ filePath,
586
+ varName,
587
+ void 0,
588
+ void 0,
589
+ void 0,
590
+ memo
591
+ );
530
592
  for (const [name, pattern] of Object.entries(routeMap)) {
531
593
  const params = extractParamsFromPattern(pattern);
532
594
  routes.push({
@@ -540,12 +602,12 @@ function writePerModuleRouteTypesForFile(filePath) {
540
602
  } else {
541
603
  routes = extractRoutesFromSource(source);
542
604
  }
543
- const genPath = filePath.replace(/\.(tsx?)$/, ".gen.ts");
605
+ const genPath = filePath.replace(/\.(tsx?|jsx?)$/, ".gen.ts");
544
606
  if (routes.length === 0) {
545
607
  if (varNames.length > 0 && !existsSync2(genPath)) {
546
608
  writeFileSync(genPath, generatePerModuleTypesSource([]));
547
609
  console.log(
548
- `[rsc-router] Generated route types (placeholder) -> ${genPath}`
610
+ `[rango] Generated route types (placeholder) -> ${genPath}`
549
611
  );
550
612
  }
551
613
  return;
@@ -554,11 +616,11 @@ function writePerModuleRouteTypesForFile(filePath) {
554
616
  const existing = existsSync2(genPath) ? readFileSync2(genPath, "utf-8") : null;
555
617
  if (existing !== genSource) {
556
618
  writeFileSync(genPath, genSource);
557
- console.log(`[rsc-router] Generated route types -> ${genPath}`);
619
+ console.log(`[rango] Generated route types -> ${genPath}`);
558
620
  }
559
621
  } catch (err) {
560
622
  console.warn(
561
- `[rsc-router] Failed to generate route types for ${filePath}: ${err.message}`
623
+ `[rango] Failed to generate route types for ${filePath}: ${err.message}`
562
624
  );
563
625
  }
564
626
  }
@@ -573,6 +635,131 @@ var init_per_module_writer = __esm({
573
635
  }
574
636
  });
575
637
 
638
+ // src/build/route-types/source-scan.ts
639
+ function isLineTerminator(ch) {
640
+ const c = ch.charCodeAt(0);
641
+ return c === 10 || c === 13 || c === 8232 || c === 8233;
642
+ }
643
+ function isRegexPositionAt(code, slashPos, prevChar) {
644
+ if (prevChar === void 0) return true;
645
+ if (prevChar === ")" || prevChar === "]" || prevChar === "}") return false;
646
+ if (!/[\w$]/.test(prevChar)) return true;
647
+ let k = slashPos - 1;
648
+ while (k >= 0 && /\s/.test(code[k])) k--;
649
+ const wordEnd = k + 1;
650
+ while (k >= 0 && /[\w$]/.test(code[k])) k--;
651
+ return REGEX_PRECEDING_KEYWORDS.has(code.slice(k + 1, wordEnd));
652
+ }
653
+ function makeCodeClassifier(code) {
654
+ const n = code.length;
655
+ let i = 0;
656
+ let skipStart = -1;
657
+ let skipEnd = -1;
658
+ let lastSig;
659
+ return (q) => {
660
+ if (q >= skipStart && q < skipEnd) return false;
661
+ while (i < n && i <= q) {
662
+ const c = code[i];
663
+ const d = i + 1 < n ? code[i + 1] : "";
664
+ let end = -1;
665
+ let transparent = false;
666
+ if (c === "/" && d === "/") {
667
+ let j = i + 2;
668
+ while (j < n && !isLineTerminator(code[j])) j++;
669
+ end = j;
670
+ transparent = true;
671
+ } else if (c === "/" && d === "*") {
672
+ let j = i + 2;
673
+ while (j < n && !(code[j] === "*" && code[j + 1] === "/")) j++;
674
+ end = Math.min(n, j + 2);
675
+ transparent = true;
676
+ } else if (c === '"' || c === "'" || c === "`") {
677
+ let j = i + 1;
678
+ while (j < n) {
679
+ if (code[j] === "\\") {
680
+ j += 2;
681
+ continue;
682
+ }
683
+ if (code[j] === c) {
684
+ j++;
685
+ break;
686
+ }
687
+ j++;
688
+ }
689
+ end = j;
690
+ } else if (c === "/" && d !== "/" && d !== "*" && isRegexPositionAt(code, i, lastSig)) {
691
+ let j = i + 1;
692
+ let inClass = false;
693
+ let closed = false;
694
+ while (j < n && !isLineTerminator(code[j])) {
695
+ const r = code[j];
696
+ if (r === "\\") {
697
+ j += 2;
698
+ continue;
699
+ }
700
+ if (r === "[") inClass = true;
701
+ else if (r === "]") inClass = false;
702
+ else if (r === "/" && !inClass) {
703
+ j++;
704
+ closed = true;
705
+ break;
706
+ }
707
+ j++;
708
+ }
709
+ if (closed) {
710
+ while (j < n && /[a-z]/.test(code[j])) j++;
711
+ end = j;
712
+ }
713
+ }
714
+ if (end >= 0) {
715
+ if (q < end) {
716
+ skipStart = i;
717
+ skipEnd = end;
718
+ return false;
719
+ }
720
+ i = end;
721
+ if (!transparent) lastSig = "x";
722
+ } else {
723
+ if (!/\s/.test(c)) lastSig = c;
724
+ i++;
725
+ }
726
+ }
727
+ return true;
728
+ };
729
+ }
730
+ function firstCodeMatchIndex(code, pattern) {
731
+ const inCode = makeCodeClassifier(code);
732
+ pattern.lastIndex = 0;
733
+ let m;
734
+ while ((m = pattern.exec(code)) !== null) {
735
+ if (inCode(m.index)) return m.index;
736
+ if (pattern.lastIndex <= m.index) pattern.lastIndex = m.index + 1;
737
+ }
738
+ return -1;
739
+ }
740
+ var REGEX_PRECEDING_KEYWORDS;
741
+ var init_source_scan = __esm({
742
+ "src/build/route-types/source-scan.ts"() {
743
+ "use strict";
744
+ REGEX_PRECEDING_KEYWORDS = /* @__PURE__ */ new Set([
745
+ "return",
746
+ "typeof",
747
+ "instanceof",
748
+ "in",
749
+ "of",
750
+ "new",
751
+ "delete",
752
+ "void",
753
+ "do",
754
+ "else",
755
+ "yield",
756
+ "await",
757
+ "case",
758
+ "throw"
759
+ ]);
760
+ }
761
+ });
762
+
576
763
  // src/build/route-types/router-processing.ts
577
764
  import {
578
765
  readFileSync as readFileSync3,
@@ -609,7 +796,7 @@ function findRouterFilesRecursive(dir, filter, results) {
609
796
  entries = readdirSync2(dir, { withFileTypes: true });
610
797
  } catch (err) {
611
798
  console.warn(
612
- `[rsc-router] Failed to scan directory ${dir}: ${err.message}`
799
+ `[rango] Failed to scan directory ${dir}: ${err.message}`
613
800
  );
614
801
  return;
615
802
  }
@@ -627,7 +814,7 @@ function findRouterFilesRecursive(dir, filter, results) {
627
814
  if (filter && !filter(fullPath)) continue;
628
815
  try {
629
816
  const source = readFileSync3(fullPath, "utf-8");
630
- if (ROUTER_CALL_PATTERN.test(source)) {
817
+ if (ROUTER_CALL_PATTERN.test(source) && firstCodeMatchIndex(source, ROUTER_CALL_PATTERN_G) >= 0) {
631
818
  routerFilesInDir.push(fullPath);
632
819
  }
633
820
  } catch {
@@ -665,13 +852,13 @@ function findNestedRouterConflict(routerFiles) {
665
852
  }
666
853
  return null;
667
854
  }
668
- function formatNestedRouterConflictError(conflict, prefix = "[rsc-router]") {
855
+ function formatNestedRouterConflictError(conflict, prefix = "[rango]") {
669
856
  return `${prefix} Nested router roots are not supported.
670
857
  Router root: ${conflict.ancestor}
671
858
  Nested router: ${conflict.nested}
672
859
  Move the nested router into a sibling directory or configure it as a separate app root.`;
673
860
  }
674
- function extractUrlsVariableFromRouter(code) {
861
+ function extractUrlsFromRouter(code) {
675
862
  const sourceFile = ts5.createSourceFile(
676
863
  "router.tsx",
677
864
  code,
@@ -685,24 +872,70 @@ function extractUrlsVariableFromRouter(code) {
685
872
  const callee = node.expression;
686
873
  return ts5.isIdentifier(callee) && callee.text === "createRouter";
687
874
  }
875
+ function isInlineBuilder(node) {
876
+ return ts5.isArrowFunction(node) || ts5.isFunctionExpression(node);
877
+ }
878
+ function isRoutesOnCreateRouter(node) {
879
+ if (!ts5.isPropertyAccessExpression(node.expression) || node.expression.name.text !== "routes")
880
+ return false;
881
+ let inner = node.expression.expression;
882
+ while (ts5.isCallExpression(inner) && ts5.isPropertyAccessExpression(inner.expression)) {
883
+ inner = inner.expression.expression;
884
+ }
885
+ return isCreateRouterCall(inner);
886
+ }
688
887
  function visit(node) {
689
888
  if (result) return;
690
- if (ts5.isCallExpression(node) && ts5.isPropertyAccessExpression(node.expression) && node.expression.name.text === "routes" && node.arguments.length >= 1 && ts5.isIdentifier(node.arguments[0])) {
691
- let inner = node.expression.expression;
692
- while (ts5.isCallExpression(inner) && ts5.isPropertyAccessExpression(inner.expression)) {
693
- inner = inner.expression.expression;
694
- }
695
- if (isCreateRouterCall(inner)) {
696
- result = node.arguments[0].text;
697
- return;
889
+ if (ts5.isCallExpression(node) && node.arguments.length >= 1 && isRoutesOnCreateRouter(node)) {
890
+ const arg = node.arguments[0];
891
+ if (ts5.isIdentifier(arg)) {
892
+ result = { kind: "variable", name: arg.text };
893
+ } else if (isInlineBuilder(arg)) {
894
+ result = { kind: "inline", block: arg.getText(sourceFile) };
698
895
  }
896
+ return;
699
897
  }
700
898
  if (isCreateRouterCall(node)) {
701
899
  const callExpr = node;
702
- for (const arg of callExpr.arguments) {
900
+ for (const callArg of callExpr.arguments) {
901
+ if (ts5.isObjectLiteralExpression(callArg)) {
902
+ for (const prop of callArg.properties) {
903
+ if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "urls") {
904
+ if (ts5.isIdentifier(prop.initializer)) {
905
+ result = { kind: "variable", name: prop.initializer.text };
906
+ } else if (isInlineBuilder(prop.initializer)) {
907
+ result = {
908
+ kind: "inline",
909
+ block: prop.initializer.getText(sourceFile)
910
+ };
911
+ }
912
+ return;
913
+ }
914
+ }
915
+ }
916
+ }
917
+ }
918
+ ts5.forEachChild(node, visit);
919
+ }
920
+ visit(sourceFile);
921
+ return result;
922
+ }
923
+ function extractBasenameFromRouter(code) {
924
+ const sourceFile = ts5.createSourceFile(
925
+ "router.tsx",
926
+ code,
927
+ ts5.ScriptTarget.Latest,
928
+ true,
929
+ ts5.ScriptKind.TSX
930
+ );
931
+ let result;
932
+ function visit(node) {
933
+ if (result !== void 0) return;
934
+ if (ts5.isCallExpression(node) && ts5.isIdentifier(node.expression) && node.expression.text === "createRouter") {
935
+ for (const arg of node.arguments) {
703
936
  if (ts5.isObjectLiteralExpression(arg)) {
704
937
  for (const prop of arg.properties) {
705
- if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "urls" && ts5.isIdentifier(prop.initializer)) {
938
+ if (ts5.isPropertyAssignment(prop) && ts5.isIdentifier(prop.name) && prop.name.text === "basename" && ts5.isStringLiteral(prop.initializer)) {
706
939
  result = prop.initializer.text;
707
940
  return;
708
941
  }
@@ -715,6 +948,38 @@ function extractUrlsVariableFromRouter(code) {
715
948
  visit(sourceFile);
716
949
  return result;
717
950
  }
951
+ function applyBasenameToRoutes(result, basename) {
952
+ const prefixed = {};
953
+ for (const [name, pattern] of Object.entries(result.routes)) {
954
+ if (pattern === "/") {
955
+ prefixed[name] = basename;
956
+ } else if (basename.endsWith("/") && pattern.startsWith("/")) {
957
+ prefixed[name] = basename + pattern.slice(1);
958
+ } else {
959
+ prefixed[name] = basename + pattern;
960
+ }
961
+ }
962
+ return { routes: prefixed, searchSchemas: result.searchSchemas };
963
+ }
964
+ function genFileTsPath(sourceFile) {
965
+ const base = pathBasename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
966
+ return join2(dirname2(sourceFile), `${base}.named-routes.gen.ts`);
967
+ }
968
+ function resolveSearchSchemas(publicRouteNames, runtimeSchemas, sourceFile) {
969
+ if (runtimeSchemas && Object.keys(runtimeSchemas).length > 0) {
970
+ return runtimeSchemas;
971
+ }
972
+ const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
973
+ if (Object.keys(staticParsed.searchSchemas).length === 0) {
974
+ return runtimeSchemas;
975
+ }
976
+ const filtered = {};
977
+ for (const name of publicRouteNames) {
978
+ const schema = staticParsed.searchSchemas[name];
979
+ if (schema) filtered[name] = schema;
980
+ }
981
+ return Object.keys(filtered).length > 0 ? filtered : runtimeSchemas;
982
+ }
718
983
  function buildCombinedRouteMapForRouterFile(routerFilePath) {
719
984
  let routerSource;
720
985
  try {
@@ -722,19 +987,40 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
722
987
  } catch {
723
988
  return { routes: {}, searchSchemas: {} };
724
989
  }
725
- const urlsVarName = extractUrlsVariableFromRouter(routerSource);
726
- if (!urlsVarName) {
990
+ const extraction = extractUrlsFromRouter(routerSource);
991
+ if (!extraction) {
727
992
  return { routes: {}, searchSchemas: {} };
728
993
  }
729
- const imported = resolveImportedVariable(routerSource, urlsVarName);
730
- if (imported) {
731
- const targetFile = resolveImportPath(imported.specifier, routerFilePath);
732
- if (!targetFile) {
733
- return { routes: {}, searchSchemas: {} };
994
+ const rawBasename = extractBasenameFromRouter(routerSource);
995
+ const basename = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
996
+ let result;
997
+ if (extraction.kind === "inline") {
998
+ result = buildCombinedRouteMapWithSearch(
999
+ routerFilePath,
1000
+ void 0,
1001
+ void 0,
1002
+ void 0,
1003
+ extraction.block
1004
+ );
1005
+ } else {
1006
+ const imported = resolveImportedVariable(routerSource, extraction.name);
1007
+ if (imported) {
1008
+ const targetFile = resolveImportPath(imported.specifier, routerFilePath);
1009
+ if (!targetFile) {
1010
+ return { routes: {}, searchSchemas: {} };
1011
+ }
1012
+ result = buildCombinedRouteMapWithSearch(
1013
+ targetFile,
1014
+ imported.exportedName
1015
+ );
1016
+ } else {
1017
+ result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
734
1018
  }
735
- return buildCombinedRouteMapWithSearch(targetFile, imported.exportedName);
736
1019
  }
737
- return buildCombinedRouteMapWithSearch(routerFilePath, urlsVarName);
1020
+ if (basename) {
1021
+ result = applyBasenameToRoutes(result, basename);
1022
+ }
1023
+ return result;
738
1024
  }
739
1025
  function detectUnresolvableIncludes(routerFilePath) {
740
1026
  const realPath = resolve2(routerFilePath);
@@ -744,9 +1030,20 @@ function detectUnresolvableIncludes(routerFilePath) {
744
1030
  } catch {
745
1031
  return [];
746
1032
  }
747
- const urlsVarName = extractUrlsVariableFromRouter(source);
748
- if (!urlsVarName) return [];
749
- const imported = resolveImportedVariable(source, urlsVarName);
1033
+ const extraction = extractUrlsFromRouter(source);
1034
+ if (!extraction) return [];
1035
+ const diagnostics = [];
1036
+ if (extraction.kind === "inline") {
1037
+ buildCombinedRouteMapWithSearch(
1038
+ realPath,
1039
+ void 0,
1040
+ /* @__PURE__ */ new Set(),
1041
+ diagnostics,
1042
+ extraction.block
1043
+ );
1044
+ return diagnostics;
1045
+ }
1046
+ const imported = resolveImportedVariable(source, extraction.name);
750
1047
  let targetFile;
751
1048
  let exportedName;
752
1049
  if (imported) {
@@ -766,9 +1063,8 @@ function detectUnresolvableIncludes(routerFilePath) {
766
1063
  exportedName = imported.exportedName;
767
1064
  } else {
768
1065
  targetFile = realPath;
769
- exportedName = urlsVarName;
1066
+ exportedName = extraction.name;
770
1067
  }
771
- const diagnostics = [];
772
1068
  buildCombinedRouteMapWithSearch(
773
1069
  targetFile,
774
1070
  exportedName,
@@ -804,7 +1100,7 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
804
1100
  if (existsSync3(oldCombinedPath)) {
805
1101
  unlinkSync(oldCombinedPath);
806
1102
  console.log(
807
- `[rsc-router] Removed stale combined route types: ${oldCombinedPath}`
1103
+ `[rango] Removed stale combined route types: ${oldCombinedPath}`
808
1104
  );
809
1105
  }
810
1106
  } catch {
@@ -816,38 +1112,22 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
816
1112
  throw new Error(formatNestedRouterConflictError(nestedRouterConflict));
817
1113
  }
818
1114
  for (const routerFilePath of routerFilePaths) {
819
- let routerSource;
820
- try {
821
- routerSource = readFileSync3(routerFilePath, "utf-8");
822
- } catch {
823
- continue;
824
- }
825
- const urlsVarName = extractUrlsVariableFromRouter(routerSource);
826
- if (!urlsVarName) continue;
827
- let result;
828
- const imported = resolveImportedVariable(routerSource, urlsVarName);
829
- if (imported) {
830
- const targetFile = resolveImportPath(imported.specifier, routerFilePath);
831
- if (!targetFile) continue;
832
- result = buildCombinedRouteMapWithSearch(
833
- targetFile,
834
- imported.exportedName
835
- );
836
- } else {
837
- result = buildCombinedRouteMapWithSearch(routerFilePath, urlsVarName);
1115
+ const result = buildCombinedRouteMapForRouterFile(routerFilePath);
1116
+ if (Object.keys(result.routes).length === 0 && Object.keys(result.searchSchemas).length === 0) {
1117
+ let routerSource;
1118
+ try {
1119
+ routerSource = readFileSync3(routerFilePath, "utf-8");
1120
+ } catch {
1121
+ continue;
1122
+ }
1123
+ if (!extractUrlsFromRouter(routerSource)) continue;
838
1124
  }
839
- const routerBasename = pathBasename(routerFilePath).replace(
840
- /\.(tsx?|jsx?)$/,
841
- ""
842
- );
843
- const outPath = join2(
844
- dirname2(routerFilePath),
845
- `${routerBasename}.named-routes.gen.ts`
846
- );
1125
+ const outPath = genFileTsPath(routerFilePath);
847
1126
  const existing = existsSync3(outPath) ? readFileSync3(outPath, "utf-8") : null;
848
1127
  if (Object.keys(result.routes).length === 0) {
849
1128
  if (!existing) {
850
1129
  const emptySource = generateRouteTypesSource({});
1130
+ opts?.onWrite?.(outPath, emptySource);
851
1131
  writeFileSync2(outPath, emptySource);
852
1132
  }
853
1133
  continue;
@@ -867,22 +1147,25 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
867
1147
  continue;
868
1148
  }
869
1149
  }
1150
+ opts?.onWrite?.(outPath, source);
870
1151
  writeFileSync2(outPath, source);
871
1152
  console.log(
872
- `[rsc-router] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`
1153
+ `[rango] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`
873
1154
  );
874
1155
  }
875
1156
  }
876
1157
  }
877
- var ROUTER_CALL_PATTERN;
1158
+ var ROUTER_CALL_PATTERN, ROUTER_CALL_PATTERN_G;
878
1159
  var init_router_processing = __esm({
879
1160
  "src/build/route-types/router-processing.ts"() {
880
1161
  "use strict";
881
1162
  init_codegen();
1163
+ init_source_scan();
882
1164
  init_include_resolution();
883
1165
  init_per_module_writer();
884
1166
  init_route_name();
885
1167
  ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
1168
+ ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
886
1169
  }
887
1170
  });
888
1171
 
@@ -920,7 +1203,7 @@ import {
920
1203
  import { createElement, StrictMode } from "react";
921
1204
  import { hydrateRoot } from "react-dom/client";
922
1205
  import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
923
- import { initBrowserApp, RSCRouter } from "@rangojs/router/browser";
1206
+ import { initBrowserApp, Rango } from "@rangojs/router/browser";
924
1207
 
925
1208
  async function initializeApp() {
926
1209
  const deps = {
@@ -931,11 +1214,16 @@ async function initializeApp() {
931
1214
  createTemporaryReferenceSet,
932
1215
  };
933
1216
 
934
- await initBrowserApp({ rscStream, deps });
1217
+ // initBrowserApp resolves the initial payload and returns the browser app
1218
+ // context, including strictMode (default true) from createRouter. StrictMode
1219
+ // is the default; createRouter({ strictMode: false }) ships the opt-out in the
1220
+ // payload metadata. StrictMode emits no DOM, so toggling never changes markup.
1221
+ const { strictMode } = await initBrowserApp({ rscStream, deps });
935
1222
 
1223
+ const app = createElement(Rango);
936
1224
  hydrateRoot(
937
1225
  document,
938
- createElement(StrictMode, null, createElement(RSCRouter))
1226
+ strictMode === false ? app : createElement(StrictMode, null, app)
939
1227
  );
940
1228
  }
941
1229
 
@@ -964,12 +1252,37 @@ export const renderHTML = createSSRHandler({
964
1252
  }
965
1253
  });
966
1254
 
1255
+ // src/vite/utils/directive-prologue.ts
1256
+ import { parseAst } from "vite";
1257
+ function hasUseClientDirective(source) {
1258
+ let program;
1259
+ try {
1260
+ program = parseAst(source, { lang: "tsx" });
1261
+ } catch {
1262
+ return false;
1263
+ }
1264
+ for (const node of program.body ?? []) {
1265
+ if (node?.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
1266
+ if (node.expression.value === "use client") return true;
1267
+ continue;
1268
+ }
1269
+ break;
1270
+ }
1271
+ return false;
1272
+ }
1273
+ var init_directive_prologue = __esm({
1274
+ "src/vite/utils/directive-prologue.ts"() {
1275
+ "use strict";
1276
+ }
1277
+ });
1278
+
967
1279
  // src/vite/plugins/version-plugin.ts
968
1280
  var version_plugin_exports = {};
969
1281
  __export(version_plugin_exports, {
970
- createVersionPlugin: () => createVersionPlugin
1282
+ createVersionPlugin: () => createVersionPlugin,
1283
+ isViteDepCachePath: () => isViteDepCachePath
971
1284
  });
972
- import { parseAst } from "vite";
1285
+ import { parseAst as parseAst2 } from "vite";
973
1286
  function isCodeModule(id) {
974
1287
  return /\.(tsx?|jsx?)($|\?)/.test(id);
975
1288
  }
@@ -977,23 +1290,13 @@ function normalizeModuleId(id) {
977
1290
  return id.split("?", 1)[0];
978
1291
  }
979
1292
  function getClientModuleSignature(source) {
1293
+ if (!hasUseClientDirective(source)) return void 0;
980
1294
  let program;
981
1295
  try {
982
- program = parseAst(source, { jsx: true });
1296
+ program = parseAst2(source, { lang: "tsx" });
983
1297
  } catch {
984
1298
  return void 0;
985
1299
  }
986
- let isUseClient = false;
987
- for (const node of program.body ?? []) {
988
- if (node?.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
989
- if (node.expression.value === "use client") {
990
- isUseClient = true;
991
- }
992
- continue;
993
- }
994
- break;
995
- }
996
- if (!isUseClient) return void 0;
997
1300
  const exports = /* @__PURE__ */ new Set();
998
1301
  let hasDefault = false;
999
1302
  let hasExportAll = false;
@@ -1062,11 +1365,12 @@ function createVersionPlugin() {
1062
1365
  let currentVersion = buildVersion;
1063
1366
  let isDev = false;
1064
1367
  let server = null;
1368
+ let resolvedCacheDir;
1065
1369
  const clientModuleSignatures = /* @__PURE__ */ new Map();
1066
1370
  let versionCounter = 0;
1067
1371
  const bumpVersion = (reason) => {
1068
1372
  currentVersion = Date.now().toString(16) + String(++versionCounter);
1069
- console.log(`[rsc-router] ${reason}, version updated: ${currentVersion}`);
1373
+ console.log(`[rango] ${reason}, version updated: ${currentVersion}`);
1070
1374
  const rscEnv = server?.environments?.rsc;
1071
1375
  const versionMod = rscEnv?.moduleGraph?.getModuleById(
1072
1376
  "\0" + VIRTUAL_IDS.version
@@ -1080,6 +1384,7 @@ function createVersionPlugin() {
1080
1384
  enforce: "pre",
1081
1385
  configResolved(config) {
1082
1386
  isDev = config.command === "serve";
1387
+ resolvedCacheDir = config.cacheDir ? String(config.cacheDir).replace(/\\/g, "/") : void 0;
1083
1388
  },
1084
1389
  configureServer(devServer) {
1085
1390
  server = devServer;
@@ -1116,11 +1421,11 @@ function createVersionPlugin() {
1116
1421
  }
1117
1422
  return null;
1118
1423
  },
1119
- // Track RSC module changes and update version
1120
1424
  async hotUpdate(ctx) {
1121
1425
  if (!isDev) return;
1122
1426
  const isRscModule = this.environment?.name === "rsc";
1123
1427
  if (!isRscModule) return;
1428
+ if (isViteDepCachePath(ctx.file, resolvedCacheDir)) return;
1124
1429
  if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
1125
1430
  return;
1126
1431
  }
@@ -1150,10 +1455,22 @@ function createVersionPlugin() {
1150
1455
  }
1151
1456
  };
1152
1457
  }
1458
+ function isViteDepCachePath(filePath, cacheDir) {
1459
+ if (!filePath) return false;
1460
+ const normalized = filePath.replace(/\\/g, "/");
1461
+ if (cacheDir) {
1462
+ const normalizedCacheDir = cacheDir.replace(/\\/g, "/").replace(/\/+$/, "");
1463
+ if (normalized === normalizedCacheDir || normalized.startsWith(normalizedCacheDir + "/")) {
1464
+ return true;
1465
+ }
1466
+ }
1467
+ return /\/node_modules\/\.vite[^/]*\//.test(normalized) || normalized.includes("/.vite-isolated/");
1468
+ }
1153
1469
  var init_version_plugin = __esm({
1154
1470
  "src/vite/plugins/version-plugin.ts"() {
1155
1471
  "use strict";
1156
1472
  init_virtual_entries();
1473
+ init_directive_prologue();
1157
1474
  }
1158
1475
  });
1159
1476
 
@@ -1195,7 +1512,7 @@ var runtime_discovery_exports = {};
1195
1512
  __export(runtime_discovery_exports, {
1196
1513
  discoverAndWriteRouteTypes: () => discoverAndWriteRouteTypes
1197
1514
  });
1198
- import { dirname as dirname3, join as join3, basename, resolve as resolve3 } from "node:path";
1515
+ import { resolve as resolve3 } from "node:path";
1199
1516
  import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
1200
1517
  async function discoverAndWriteRouteTypes(opts) {
1201
1518
  let createViteServer;
@@ -1305,22 +1622,12 @@ This means createRouter() stack trace parsing matched an internal frame.
1305
1622
  Set an explicit \`id\` on createRouter() or check the call site.`
1306
1623
  );
1307
1624
  }
1308
- if (!routeSearchSchemas || Object.keys(routeSearchSchemas).length === 0) {
1309
- const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
1310
- if (Object.keys(staticParsed.searchSchemas).length > 0) {
1311
- const filtered = {};
1312
- for (const name of Object.keys(routeManifest)) {
1313
- const schema = staticParsed.searchSchemas[name];
1314
- if (schema) filtered[name] = schema;
1315
- }
1316
- if (Object.keys(filtered).length > 0) {
1317
- routeSearchSchemas = filtered;
1318
- }
1319
- }
1320
- }
1321
- const routerDir = dirname3(sourceFile);
1322
- const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
1323
- const outPath = join3(routerDir, `${routerBasename}.named-routes.gen.ts`);
1625
+ routeSearchSchemas = resolveSearchSchemas(
1626
+ Object.keys(routeManifest),
1627
+ routeSearchSchemas,
1628
+ sourceFile
1629
+ );
1630
+ const outPath = genFileTsPath(sourceFile);
1324
1631
  const source = generateRouteTypesSource(
1325
1632
  routeManifest,
1326
1633
  routeSearchSchemas && Object.keys(routeSearchSchemas).length > 0 ? routeSearchSchemas : void 0
@@ -1357,7 +1664,7 @@ var init_runtime_discovery = __esm({
1357
1664
 
1358
1665
  // src/bin/rango.ts
1359
1666
  init_generate_route_types();
1360
- import { resolve as resolve4, dirname as dirname4 } from "node:path";
1667
+ import { resolve as resolve4, dirname as dirname3 } from "node:path";
1361
1668
  import { readFileSync as readFileSync5, statSync, existsSync as existsSync5 } from "node:fs";
1362
1669
  var [command, ...rawArgs] = process.argv.slice(2);
1363
1670
  if (command === "generate") {
@@ -1428,12 +1735,12 @@ Examples:
1428
1735
  );
1429
1736
  }
1430
1737
  function findProjectRoot(fromPath) {
1431
- let dir = dirname4(resolve4(fromPath));
1432
- while (dir !== dirname4(dir)) {
1738
+ let dir = dirname3(resolve4(fromPath));
1739
+ while (dir !== dirname3(dir)) {
1433
1740
  if (existsSync5(resolve4(dir, "package.json")) || existsSync5(resolve4(dir, "vite.config.ts")) || existsSync5(resolve4(dir, "vite.config.js"))) {
1434
1741
  return dir;
1435
1742
  }
1436
- dir = dirname4(dir);
1743
+ dir = dirname3(dir);
1437
1744
  }
1438
1745
  return process.cwd();
1439
1746
  }