@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
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,7 +220,7 @@ 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
  }
@@ -238,6 +247,33 @@ var init_scan_filter = __esm({
238
247
  import { readFileSync, existsSync } from "node:fs";
239
248
  import { dirname, resolve } from "node:path";
240
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
+ }
241
277
  function extractNamePrefixFromInclude(node) {
242
278
  if (node.arguments.length >= 3) {
243
279
  const thirdArg = node.arguments[2];
@@ -253,8 +289,8 @@ function extractNamePrefixFromInclude(node) {
253
289
  }
254
290
  return null;
255
291
  }
256
- function extractIncludesWithDiagnostics(code) {
257
- const sourceFile = ts3.createSourceFile(
292
+ function extractIncludesWithDiagnostics(code, sourceFileArg) {
293
+ const sourceFile = sourceFileArg ?? ts3.createSourceFile(
258
294
  "input.tsx",
259
295
  code,
260
296
  ts3.ScriptTarget.Latest,
@@ -308,7 +344,7 @@ function extractIncludesWithDiagnostics(code) {
308
344
  return { resolved, unresolvable };
309
345
  }
310
346
  function resolveImportedVariable(code, localName) {
311
- const importRegex = /import\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
347
+ const importRegex = /import\s*(?:[\w$]+\s*,\s*)?\{([^}]+)\}\s*from\s*["']([^"']+)["']/g;
312
348
  let match;
313
349
  while ((match = importRegex.exec(code)) !== null) {
314
350
  const imports = match[1];
@@ -345,8 +381,8 @@ function resolveImportPath(importSpec, fromFile) {
345
381
  }
346
382
  return null;
347
383
  }
348
- function extractUrlsBlockForVariable(code, varName) {
349
- const sourceFile = ts3.createSourceFile(
384
+ function extractUrlsBlockForVariable(code, varName, sourceFileArg) {
385
+ const sourceFile = sourceFileArg ?? ts3.createSourceFile(
350
386
  "input.tsx",
351
387
  code,
352
388
  ts3.ScriptTarget.Latest,
@@ -368,16 +404,20 @@ function extractUrlsBlockForVariable(code, varName) {
368
404
  visit(sourceFile);
369
405
  return result;
370
406
  }
371
- function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSchemasOut, diagnosticsOut) {
407
+ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSchemasOut, diagnosticsOut, memo) {
372
408
  const routeMap = {};
373
- const localRoutes = extractRoutesFromSource(block);
409
+ const blockSourceFile = parseBlock(memo, block);
410
+ const localRoutes = extractRoutesFromSource(block, blockSourceFile);
374
411
  for (const { name, pattern, search } of localRoutes) {
375
412
  routeMap[name] = pattern;
376
413
  if (search && searchSchemasOut) {
377
414
  searchSchemasOut[name] = search;
378
415
  }
379
416
  }
380
- const { resolved: includes, unresolvable } = extractIncludesWithDiagnostics(block);
417
+ const { resolved: includes, unresolvable } = extractIncludesWithDiagnostics(
418
+ block,
419
+ blockSourceFile
420
+ );
381
421
  if (diagnosticsOut) {
382
422
  for (const entry of unresolvable) {
383
423
  diagnosticsOut.push({ ...entry, sourceFile: filePath });
@@ -404,12 +444,15 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
404
444
  targetFile,
405
445
  imported.exportedName,
406
446
  visited,
407
- diagnosticsOut
447
+ diagnosticsOut,
448
+ void 0,
449
+ memo
408
450
  );
409
451
  } else {
410
452
  const sameFileBlock = extractUrlsBlockForVariable(
411
453
  fullSource,
412
- variableName
454
+ variableName,
455
+ parseBlock(memo, fullSource)
413
456
  );
414
457
  if (!sameFileBlock) {
415
458
  if (diagnosticsOut) {
@@ -427,7 +470,9 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
427
470
  filePath,
428
471
  variableName,
429
472
  visited,
430
- diagnosticsOut
473
+ diagnosticsOut,
474
+ void 0,
475
+ memo
431
476
  );
432
477
  }
433
478
  if (namePrefix === null) {
@@ -451,18 +496,19 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
451
496
  }
452
497
  return routeMap;
453
498
  }
454
- function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut, inlineBlock) {
499
+ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagnosticsOut, inlineBlock, memo) {
455
500
  visited = visited ?? /* @__PURE__ */ new Set();
501
+ memo = memo ?? createScanMemo();
456
502
  const realPath = resolve(filePath);
457
503
  const key = variableName ? `${realPath}:${variableName}` : realPath;
458
504
  if (visited.has(key)) {
459
- console.warn(`[rsc-router] Circular include detected, skipping: ${key}`);
505
+ console.warn(`[rango] Circular include detected, skipping: ${key}`);
460
506
  return { routes: {}, searchSchemas: {} };
461
507
  }
462
508
  visited.add(key);
463
509
  let source;
464
510
  try {
465
- source = readFileSync(realPath, "utf-8");
511
+ source = readSourceMemoized(memo, realPath);
466
512
  } catch {
467
513
  return { routes: {}, searchSchemas: {} };
468
514
  }
@@ -470,7 +516,11 @@ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagno
470
516
  if (inlineBlock) {
471
517
  block = inlineBlock;
472
518
  } else if (variableName) {
473
- const extracted = extractUrlsBlockForVariable(source, variableName);
519
+ const extracted = extractUrlsBlockForVariable(
520
+ source,
521
+ variableName,
522
+ parseBlock(memo, source)
523
+ );
474
524
  if (!extracted) return { routes: {}, searchSchemas: {} };
475
525
  block = extracted;
476
526
  } else {
@@ -483,7 +533,8 @@ function buildCombinedRouteMapWithSearch(filePath, variableName, visited, diagno
483
533
  realPath,
484
534
  visited,
485
535
  searchSchemas,
486
- diagnosticsOut
536
+ diagnosticsOut,
537
+ memo
487
538
  );
488
539
  visited.delete(key);
489
540
  return { routes, searchSchemas };
@@ -528,8 +579,16 @@ function writePerModuleRouteTypesForFile(filePath) {
528
579
  let routes;
529
580
  if (varNames.length > 0) {
530
581
  routes = [];
582
+ const memo = createScanMemo();
531
583
  for (const varName of varNames) {
532
- 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
+ );
533
592
  for (const [name, pattern] of Object.entries(routeMap)) {
534
593
  const params = extractParamsFromPattern(pattern);
535
594
  routes.push({
@@ -543,12 +602,12 @@ function writePerModuleRouteTypesForFile(filePath) {
543
602
  } else {
544
603
  routes = extractRoutesFromSource(source);
545
604
  }
546
- const genPath = filePath.replace(/\.(tsx?)$/, ".gen.ts");
605
+ const genPath = filePath.replace(/\.(tsx?|jsx?)$/, ".gen.ts");
547
606
  if (routes.length === 0) {
548
607
  if (varNames.length > 0 && !existsSync2(genPath)) {
549
608
  writeFileSync(genPath, generatePerModuleTypesSource([]));
550
609
  console.log(
551
- `[rsc-router] Generated route types (placeholder) -> ${genPath}`
610
+ `[rango] Generated route types (placeholder) -> ${genPath}`
552
611
  );
553
612
  }
554
613
  return;
@@ -557,11 +616,11 @@ function writePerModuleRouteTypesForFile(filePath) {
557
616
  const existing = existsSync2(genPath) ? readFileSync2(genPath, "utf-8") : null;
558
617
  if (existing !== genSource) {
559
618
  writeFileSync(genPath, genSource);
560
- console.log(`[rsc-router] Generated route types -> ${genPath}`);
619
+ console.log(`[rango] Generated route types -> ${genPath}`);
561
620
  }
562
621
  } catch (err) {
563
622
  console.warn(
564
- `[rsc-router] Failed to generate route types for ${filePath}: ${err.message}`
623
+ `[rango] Failed to generate route types for ${filePath}: ${err.message}`
565
624
  );
566
625
  }
567
626
  }
@@ -576,6 +635,131 @@ var init_per_module_writer = __esm({
576
635
  }
577
636
  });
578
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
+
579
763
  // src/build/route-types/router-processing.ts
580
764
  import {
581
765
  readFileSync as readFileSync3,
@@ -612,7 +796,7 @@ function findRouterFilesRecursive(dir, filter, results) {
612
796
  entries = readdirSync2(dir, { withFileTypes: true });
613
797
  } catch (err) {
614
798
  console.warn(
615
- `[rsc-router] Failed to scan directory ${dir}: ${err.message}`
799
+ `[rango] Failed to scan directory ${dir}: ${err.message}`
616
800
  );
617
801
  return;
618
802
  }
@@ -630,7 +814,7 @@ function findRouterFilesRecursive(dir, filter, results) {
630
814
  if (filter && !filter(fullPath)) continue;
631
815
  try {
632
816
  const source = readFileSync3(fullPath, "utf-8");
633
- if (ROUTER_CALL_PATTERN.test(source)) {
817
+ if (ROUTER_CALL_PATTERN.test(source) && firstCodeMatchIndex(source, ROUTER_CALL_PATTERN_G) >= 0) {
634
818
  routerFilesInDir.push(fullPath);
635
819
  }
636
820
  } catch {
@@ -668,7 +852,7 @@ function findNestedRouterConflict(routerFiles) {
668
852
  }
669
853
  return null;
670
854
  }
671
- function formatNestedRouterConflictError(conflict, prefix = "[rsc-router]") {
855
+ function formatNestedRouterConflictError(conflict, prefix = "[rango]") {
672
856
  return `${prefix} Nested router roots are not supported.
673
857
  Router root: ${conflict.ancestor}
674
858
  Nested router: ${conflict.nested}
@@ -764,19 +948,38 @@ function extractBasenameFromRouter(code) {
764
948
  visit(sourceFile);
765
949
  return result;
766
950
  }
767
- function applyBasenameToRoutes(result, basename2) {
951
+ function applyBasenameToRoutes(result, basename) {
768
952
  const prefixed = {};
769
953
  for (const [name, pattern] of Object.entries(result.routes)) {
770
954
  if (pattern === "/") {
771
- prefixed[name] = basename2;
772
- } else if (basename2.endsWith("/") && pattern.startsWith("/")) {
773
- prefixed[name] = basename2 + pattern.slice(1);
955
+ prefixed[name] = basename;
956
+ } else if (basename.endsWith("/") && pattern.startsWith("/")) {
957
+ prefixed[name] = basename + pattern.slice(1);
774
958
  } else {
775
- prefixed[name] = basename2 + pattern;
959
+ prefixed[name] = basename + pattern;
776
960
  }
777
961
  }
778
962
  return { routes: prefixed, searchSchemas: result.searchSchemas };
779
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
+ }
780
983
  function buildCombinedRouteMapForRouterFile(routerFilePath) {
781
984
  let routerSource;
782
985
  try {
@@ -789,7 +992,7 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
789
992
  return { routes: {}, searchSchemas: {} };
790
993
  }
791
994
  const rawBasename = extractBasenameFromRouter(routerSource);
792
- const basename2 = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
995
+ const basename = rawBasename ? ("/" + rawBasename.replace(/^\/+|\/+$/g, "")).replace(/^\/$/, "") : void 0;
793
996
  let result;
794
997
  if (extraction.kind === "inline") {
795
998
  result = buildCombinedRouteMapWithSearch(
@@ -814,8 +1017,8 @@ function buildCombinedRouteMapForRouterFile(routerFilePath) {
814
1017
  result = buildCombinedRouteMapWithSearch(routerFilePath, extraction.name);
815
1018
  }
816
1019
  }
817
- if (basename2) {
818
- result = applyBasenameToRoutes(result, basename2);
1020
+ if (basename) {
1021
+ result = applyBasenameToRoutes(result, basename);
819
1022
  }
820
1023
  return result;
821
1024
  }
@@ -897,7 +1100,7 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
897
1100
  if (existsSync3(oldCombinedPath)) {
898
1101
  unlinkSync(oldCombinedPath);
899
1102
  console.log(
900
- `[rsc-router] Removed stale combined route types: ${oldCombinedPath}`
1103
+ `[rango] Removed stale combined route types: ${oldCombinedPath}`
901
1104
  );
902
1105
  }
903
1106
  } catch {
@@ -919,18 +1122,12 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
919
1122
  }
920
1123
  if (!extractUrlsFromRouter(routerSource)) continue;
921
1124
  }
922
- const routerBasename = pathBasename(routerFilePath).replace(
923
- /\.(tsx?|jsx?)$/,
924
- ""
925
- );
926
- const outPath = join2(
927
- dirname2(routerFilePath),
928
- `${routerBasename}.named-routes.gen.ts`
929
- );
1125
+ const outPath = genFileTsPath(routerFilePath);
930
1126
  const existing = existsSync3(outPath) ? readFileSync3(outPath, "utf-8") : null;
931
1127
  if (Object.keys(result.routes).length === 0) {
932
1128
  if (!existing) {
933
1129
  const emptySource = generateRouteTypesSource({});
1130
+ opts?.onWrite?.(outPath, emptySource);
934
1131
  writeFileSync2(outPath, emptySource);
935
1132
  }
936
1133
  continue;
@@ -950,22 +1147,25 @@ function writeCombinedRouteTypes(root, knownRouterFiles, opts) {
950
1147
  continue;
951
1148
  }
952
1149
  }
1150
+ opts?.onWrite?.(outPath, source);
953
1151
  writeFileSync2(outPath, source);
954
1152
  console.log(
955
- `[rsc-router] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`
1153
+ `[rango] Generated route types (${Object.keys(result.routes).length} routes) -> ${outPath}`
956
1154
  );
957
1155
  }
958
1156
  }
959
1157
  }
960
- var ROUTER_CALL_PATTERN;
1158
+ var ROUTER_CALL_PATTERN, ROUTER_CALL_PATTERN_G;
961
1159
  var init_router_processing = __esm({
962
1160
  "src/build/route-types/router-processing.ts"() {
963
1161
  "use strict";
964
1162
  init_codegen();
1163
+ init_source_scan();
965
1164
  init_include_resolution();
966
1165
  init_per_module_writer();
967
1166
  init_route_name();
968
1167
  ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
1168
+ ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
969
1169
  }
970
1170
  });
971
1171
 
@@ -1003,7 +1203,7 @@ import {
1003
1203
  import { createElement, StrictMode } from "react";
1004
1204
  import { hydrateRoot } from "react-dom/client";
1005
1205
  import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
1006
- import { initBrowserApp, RSCRouter } from "@rangojs/router/browser";
1206
+ import { initBrowserApp, Rango } from "@rangojs/router/browser";
1007
1207
 
1008
1208
  async function initializeApp() {
1009
1209
  const deps = {
@@ -1014,11 +1214,16 @@ async function initializeApp() {
1014
1214
  createTemporaryReferenceSet,
1015
1215
  };
1016
1216
 
1017
- 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 });
1018
1222
 
1223
+ const app = createElement(Rango);
1019
1224
  hydrateRoot(
1020
1225
  document,
1021
- createElement(StrictMode, null, createElement(RSCRouter))
1226
+ strictMode === false ? app : createElement(StrictMode, null, app)
1022
1227
  );
1023
1228
  }
1024
1229
 
@@ -1047,12 +1252,37 @@ export const renderHTML = createSSRHandler({
1047
1252
  }
1048
1253
  });
1049
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
+
1050
1279
  // src/vite/plugins/version-plugin.ts
1051
1280
  var version_plugin_exports = {};
1052
1281
  __export(version_plugin_exports, {
1053
- createVersionPlugin: () => createVersionPlugin
1282
+ createVersionPlugin: () => createVersionPlugin,
1283
+ isViteDepCachePath: () => isViteDepCachePath
1054
1284
  });
1055
- import { parseAst } from "vite";
1285
+ import { parseAst as parseAst2 } from "vite";
1056
1286
  function isCodeModule(id) {
1057
1287
  return /\.(tsx?|jsx?)($|\?)/.test(id);
1058
1288
  }
@@ -1060,23 +1290,13 @@ function normalizeModuleId(id) {
1060
1290
  return id.split("?", 1)[0];
1061
1291
  }
1062
1292
  function getClientModuleSignature(source) {
1293
+ if (!hasUseClientDirective(source)) return void 0;
1063
1294
  let program;
1064
1295
  try {
1065
- program = parseAst(source, { jsx: true });
1296
+ program = parseAst2(source, { lang: "tsx" });
1066
1297
  } catch {
1067
1298
  return void 0;
1068
1299
  }
1069
- let isUseClient = false;
1070
- for (const node of program.body ?? []) {
1071
- if (node?.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string") {
1072
- if (node.expression.value === "use client") {
1073
- isUseClient = true;
1074
- }
1075
- continue;
1076
- }
1077
- break;
1078
- }
1079
- if (!isUseClient) return void 0;
1080
1300
  const exports = /* @__PURE__ */ new Set();
1081
1301
  let hasDefault = false;
1082
1302
  let hasExportAll = false;
@@ -1145,11 +1365,12 @@ function createVersionPlugin() {
1145
1365
  let currentVersion = buildVersion;
1146
1366
  let isDev = false;
1147
1367
  let server = null;
1368
+ let resolvedCacheDir;
1148
1369
  const clientModuleSignatures = /* @__PURE__ */ new Map();
1149
1370
  let versionCounter = 0;
1150
1371
  const bumpVersion = (reason) => {
1151
1372
  currentVersion = Date.now().toString(16) + String(++versionCounter);
1152
- console.log(`[rsc-router] ${reason}, version updated: ${currentVersion}`);
1373
+ console.log(`[rango] ${reason}, version updated: ${currentVersion}`);
1153
1374
  const rscEnv = server?.environments?.rsc;
1154
1375
  const versionMod = rscEnv?.moduleGraph?.getModuleById(
1155
1376
  "\0" + VIRTUAL_IDS.version
@@ -1163,6 +1384,7 @@ function createVersionPlugin() {
1163
1384
  enforce: "pre",
1164
1385
  configResolved(config) {
1165
1386
  isDev = config.command === "serve";
1387
+ resolvedCacheDir = config.cacheDir ? String(config.cacheDir).replace(/\\/g, "/") : void 0;
1166
1388
  },
1167
1389
  configureServer(devServer) {
1168
1390
  server = devServer;
@@ -1199,11 +1421,11 @@ function createVersionPlugin() {
1199
1421
  }
1200
1422
  return null;
1201
1423
  },
1202
- // Track RSC module changes and update version
1203
1424
  async hotUpdate(ctx) {
1204
1425
  if (!isDev) return;
1205
1426
  const isRscModule = this.environment?.name === "rsc";
1206
1427
  if (!isRscModule) return;
1428
+ if (isViteDepCachePath(ctx.file, resolvedCacheDir)) return;
1207
1429
  if (ctx.modules.length === 1 && ctx.modules[0].id === "\0" + VIRTUAL_IDS.version) {
1208
1430
  return;
1209
1431
  }
@@ -1233,10 +1455,22 @@ function createVersionPlugin() {
1233
1455
  }
1234
1456
  };
1235
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
+ }
1236
1469
  var init_version_plugin = __esm({
1237
1470
  "src/vite/plugins/version-plugin.ts"() {
1238
1471
  "use strict";
1239
1472
  init_virtual_entries();
1473
+ init_directive_prologue();
1240
1474
  }
1241
1475
  });
1242
1476
 
@@ -1278,7 +1512,7 @@ var runtime_discovery_exports = {};
1278
1512
  __export(runtime_discovery_exports, {
1279
1513
  discoverAndWriteRouteTypes: () => discoverAndWriteRouteTypes
1280
1514
  });
1281
- import { dirname as dirname3, join as join3, basename, resolve as resolve3 } from "node:path";
1515
+ import { resolve as resolve3 } from "node:path";
1282
1516
  import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
1283
1517
  async function discoverAndWriteRouteTypes(opts) {
1284
1518
  let createViteServer;
@@ -1388,22 +1622,12 @@ This means createRouter() stack trace parsing matched an internal frame.
1388
1622
  Set an explicit \`id\` on createRouter() or check the call site.`
1389
1623
  );
1390
1624
  }
1391
- if (!routeSearchSchemas || Object.keys(routeSearchSchemas).length === 0) {
1392
- const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
1393
- if (Object.keys(staticParsed.searchSchemas).length > 0) {
1394
- const filtered = {};
1395
- for (const name of Object.keys(routeManifest)) {
1396
- const schema = staticParsed.searchSchemas[name];
1397
- if (schema) filtered[name] = schema;
1398
- }
1399
- if (Object.keys(filtered).length > 0) {
1400
- routeSearchSchemas = filtered;
1401
- }
1402
- }
1403
- }
1404
- const routerDir = dirname3(sourceFile);
1405
- const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
1406
- 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);
1407
1631
  const source = generateRouteTypesSource(
1408
1632
  routeManifest,
1409
1633
  routeSearchSchemas && Object.keys(routeSearchSchemas).length > 0 ? routeSearchSchemas : void 0
@@ -1440,7 +1664,7 @@ var init_runtime_discovery = __esm({
1440
1664
 
1441
1665
  // src/bin/rango.ts
1442
1666
  init_generate_route_types();
1443
- import { resolve as resolve4, dirname as dirname4 } from "node:path";
1667
+ import { resolve as resolve4, dirname as dirname3 } from "node:path";
1444
1668
  import { readFileSync as readFileSync5, statSync, existsSync as existsSync5 } from "node:fs";
1445
1669
  var [command, ...rawArgs] = process.argv.slice(2);
1446
1670
  if (command === "generate") {
@@ -1511,12 +1735,12 @@ Examples:
1511
1735
  );
1512
1736
  }
1513
1737
  function findProjectRoot(fromPath) {
1514
- let dir = dirname4(resolve4(fromPath));
1515
- while (dir !== dirname4(dir)) {
1738
+ let dir = dirname3(resolve4(fromPath));
1739
+ while (dir !== dirname3(dir)) {
1516
1740
  if (existsSync5(resolve4(dir, "package.json")) || existsSync5(resolve4(dir, "vite.config.ts")) || existsSync5(resolve4(dir, "vite.config.js"))) {
1517
1741
  return dir;
1518
1742
  }
1519
- dir = dirname4(dir);
1743
+ dir = dirname3(dir);
1520
1744
  }
1521
1745
  return process.cwd();
1522
1746
  }