@rangojs/router 0.0.0-experimental.13 → 0.0.0-experimental.135c6902

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 (1098) hide show
  1. package/AGENTS.md +9 -0
  2. package/README.md +884 -4
  3. package/dist/__internal.d.ts +83 -0
  4. package/dist/__internal.d.ts.map +1 -0
  5. package/dist/__internal.js +19 -0
  6. package/dist/__internal.js.map +1 -0
  7. package/dist/__mocks__/version.d.ts +7 -0
  8. package/dist/__mocks__/version.d.ts.map +1 -0
  9. package/dist/__mocks__/version.js +7 -0
  10. package/dist/__mocks__/version.js.map +1 -0
  11. package/dist/__tests__/client-href.test.d.ts +2 -0
  12. package/dist/__tests__/client-href.test.d.ts.map +1 -0
  13. package/dist/__tests__/client-href.test.js +74 -0
  14. package/dist/__tests__/client-href.test.js.map +1 -0
  15. package/dist/__tests__/component-utils.test.d.ts +2 -0
  16. package/dist/__tests__/component-utils.test.d.ts.map +1 -0
  17. package/dist/__tests__/component-utils.test.js +51 -0
  18. package/dist/__tests__/component-utils.test.js.map +1 -0
  19. package/dist/__tests__/event-controller.test.d.ts +2 -0
  20. package/dist/__tests__/event-controller.test.d.ts.map +1 -0
  21. package/dist/__tests__/event-controller.test.js +538 -0
  22. package/dist/__tests__/event-controller.test.js.map +1 -0
  23. package/dist/__tests__/helpers/route-tree.d.ts +118 -0
  24. package/dist/__tests__/helpers/route-tree.d.ts.map +1 -0
  25. package/dist/__tests__/helpers/route-tree.js +374 -0
  26. package/dist/__tests__/helpers/route-tree.js.map +1 -0
  27. package/dist/__tests__/match-result.test.d.ts +2 -0
  28. package/dist/__tests__/match-result.test.d.ts.map +1 -0
  29. package/dist/__tests__/match-result.test.js +154 -0
  30. package/dist/__tests__/match-result.test.js.map +1 -0
  31. package/dist/__tests__/navigation-store.test.d.ts +2 -0
  32. package/dist/__tests__/navigation-store.test.d.ts.map +1 -0
  33. package/dist/__tests__/navigation-store.test.js +440 -0
  34. package/dist/__tests__/navigation-store.test.js.map +1 -0
  35. package/dist/__tests__/partial-update.test.d.ts +2 -0
  36. package/dist/__tests__/partial-update.test.d.ts.map +1 -0
  37. package/dist/__tests__/partial-update.test.js +1009 -0
  38. package/dist/__tests__/partial-update.test.js.map +1 -0
  39. package/dist/__tests__/reverse-types.test.d.ts +8 -0
  40. package/dist/__tests__/reverse-types.test.d.ts.map +1 -0
  41. package/dist/__tests__/reverse-types.test.js +656 -0
  42. package/dist/__tests__/reverse-types.test.js.map +1 -0
  43. package/dist/__tests__/route-definition.test.d.ts +2 -0
  44. package/dist/__tests__/route-definition.test.d.ts.map +1 -0
  45. package/dist/__tests__/route-definition.test.js +55 -0
  46. package/dist/__tests__/route-definition.test.js.map +1 -0
  47. package/dist/__tests__/router-helpers.test.d.ts +2 -0
  48. package/dist/__tests__/router-helpers.test.d.ts.map +1 -0
  49. package/dist/__tests__/router-helpers.test.js +377 -0
  50. package/dist/__tests__/router-helpers.test.js.map +1 -0
  51. package/dist/__tests__/router-integration-2.test.d.ts +2 -0
  52. package/dist/__tests__/router-integration-2.test.d.ts.map +1 -0
  53. package/dist/__tests__/router-integration-2.test.js +426 -0
  54. package/dist/__tests__/router-integration-2.test.js.map +1 -0
  55. package/dist/__tests__/router-integration.test.d.ts +2 -0
  56. package/dist/__tests__/router-integration.test.d.ts.map +1 -0
  57. package/dist/__tests__/router-integration.test.js +1051 -0
  58. package/dist/__tests__/router-integration.test.js.map +1 -0
  59. package/dist/__tests__/search-params.test.d.ts +5 -0
  60. package/dist/__tests__/search-params.test.d.ts.map +1 -0
  61. package/dist/__tests__/search-params.test.js +306 -0
  62. package/dist/__tests__/search-params.test.js.map +1 -0
  63. package/dist/__tests__/segment-system.test.d.ts +2 -0
  64. package/dist/__tests__/segment-system.test.d.ts.map +1 -0
  65. package/dist/__tests__/segment-system.test.js +627 -0
  66. package/dist/__tests__/segment-system.test.js.map +1 -0
  67. package/dist/__tests__/static-handler-types.test.d.ts +8 -0
  68. package/dist/__tests__/static-handler-types.test.d.ts.map +1 -0
  69. package/dist/__tests__/static-handler-types.test.js +63 -0
  70. package/dist/__tests__/static-handler-types.test.js.map +1 -0
  71. package/dist/__tests__/urls.test.d.ts +2 -0
  72. package/dist/__tests__/urls.test.d.ts.map +1 -0
  73. package/dist/__tests__/urls.test.js +421 -0
  74. package/dist/__tests__/urls.test.js.map +1 -0
  75. package/dist/__tests__/use-mount.test.d.ts +2 -0
  76. package/dist/__tests__/use-mount.test.d.ts.map +1 -0
  77. package/dist/__tests__/use-mount.test.js +35 -0
  78. package/dist/__tests__/use-mount.test.js.map +1 -0
  79. package/dist/bin/rango.d.ts +2 -0
  80. package/dist/bin/rango.d.ts.map +1 -0
  81. package/dist/bin/rango.js +1531 -212
  82. package/dist/bin/rango.js.map +1 -0
  83. package/dist/browser/event-controller.d.ts +191 -0
  84. package/dist/browser/event-controller.d.ts.map +1 -0
  85. package/dist/browser/event-controller.js +559 -0
  86. package/dist/browser/event-controller.js.map +1 -0
  87. package/dist/browser/index.d.ts +2 -0
  88. package/dist/browser/index.d.ts.map +1 -0
  89. package/dist/browser/index.js +14 -0
  90. package/dist/browser/index.js.map +1 -0
  91. package/dist/browser/link-interceptor.d.ts +38 -0
  92. package/dist/browser/link-interceptor.d.ts.map +1 -0
  93. package/dist/browser/link-interceptor.js +99 -0
  94. package/dist/browser/link-interceptor.js.map +1 -0
  95. package/dist/browser/logging.d.ts +10 -0
  96. package/dist/browser/logging.d.ts.map +1 -0
  97. package/dist/browser/logging.js +29 -0
  98. package/dist/browser/logging.js.map +1 -0
  99. package/dist/browser/lru-cache.d.ts +17 -0
  100. package/dist/browser/lru-cache.d.ts.map +1 -0
  101. package/dist/browser/lru-cache.js +50 -0
  102. package/dist/browser/lru-cache.js.map +1 -0
  103. package/dist/browser/merge-segment-loaders.d.ts +39 -0
  104. package/dist/browser/merge-segment-loaders.d.ts.map +1 -0
  105. package/dist/browser/merge-segment-loaders.js +102 -0
  106. package/dist/browser/merge-segment-loaders.js.map +1 -0
  107. package/dist/browser/navigation-bridge.d.ts +102 -0
  108. package/dist/browser/navigation-bridge.d.ts.map +1 -0
  109. package/dist/browser/navigation-bridge.js +708 -0
  110. package/dist/browser/navigation-bridge.js.map +1 -0
  111. package/dist/browser/navigation-client.d.ts +25 -0
  112. package/dist/browser/navigation-client.d.ts.map +1 -0
  113. package/dist/browser/navigation-client.js +157 -0
  114. package/dist/browser/navigation-client.js.map +1 -0
  115. package/dist/browser/navigation-store.d.ts +101 -0
  116. package/dist/browser/navigation-store.d.ts.map +1 -0
  117. package/dist/browser/navigation-store.js +625 -0
  118. package/dist/browser/navigation-store.js.map +1 -0
  119. package/dist/browser/partial-update.d.ts +75 -0
  120. package/dist/browser/partial-update.d.ts.map +1 -0
  121. package/dist/browser/partial-update.js +426 -0
  122. package/dist/browser/partial-update.js.map +1 -0
  123. package/dist/browser/react/Link.d.ts +86 -0
  124. package/dist/browser/react/Link.d.ts.map +1 -0
  125. package/dist/browser/react/Link.js +128 -0
  126. package/dist/browser/react/Link.js.map +1 -0
  127. package/dist/browser/react/NavigationProvider.d.ts +63 -0
  128. package/dist/browser/react/NavigationProvider.d.ts.map +1 -0
  129. package/dist/browser/react/NavigationProvider.js +216 -0
  130. package/dist/browser/react/NavigationProvider.js.map +1 -0
  131. package/dist/browser/react/ScrollRestoration.d.ts +75 -0
  132. package/dist/browser/react/ScrollRestoration.d.ts.map +1 -0
  133. package/dist/browser/react/ScrollRestoration.js +57 -0
  134. package/dist/browser/react/ScrollRestoration.js.map +1 -0
  135. package/dist/browser/react/context.d.ts +46 -0
  136. package/dist/browser/react/context.d.ts.map +1 -0
  137. package/dist/browser/react/context.js +10 -0
  138. package/dist/browser/react/context.js.map +1 -0
  139. package/dist/browser/react/index.d.ts +11 -0
  140. package/dist/browser/react/index.d.ts.map +1 -0
  141. package/dist/browser/react/index.js +22 -0
  142. package/dist/browser/react/index.js.map +1 -0
  143. package/dist/browser/react/location-state-shared.d.ts +63 -0
  144. package/dist/browser/react/location-state-shared.d.ts.map +1 -0
  145. package/dist/browser/react/location-state-shared.js +81 -0
  146. package/dist/browser/react/location-state-shared.js.map +1 -0
  147. package/dist/browser/react/location-state.d.ts +23 -0
  148. package/dist/browser/react/location-state.d.ts.map +1 -0
  149. package/dist/browser/react/location-state.js +29 -0
  150. package/dist/browser/react/location-state.js.map +1 -0
  151. package/dist/browser/react/mount-context.d.ts +24 -0
  152. package/dist/browser/react/mount-context.d.ts.map +1 -0
  153. package/dist/browser/react/mount-context.js +24 -0
  154. package/dist/browser/react/mount-context.js.map +1 -0
  155. package/dist/browser/react/use-action.d.ts +64 -0
  156. package/dist/browser/react/use-action.d.ts.map +1 -0
  157. package/dist/browser/react/use-action.js +134 -0
  158. package/dist/browser/react/use-action.js.map +1 -0
  159. package/dist/browser/react/use-client-cache.d.ts +41 -0
  160. package/dist/browser/react/use-client-cache.d.ts.map +1 -0
  161. package/dist/browser/react/use-client-cache.js +39 -0
  162. package/dist/browser/react/use-client-cache.js.map +1 -0
  163. package/dist/browser/react/use-handle.d.ts +31 -0
  164. package/dist/browser/react/use-handle.d.ts.map +1 -0
  165. package/dist/browser/react/use-handle.js +144 -0
  166. package/dist/browser/react/use-handle.js.map +1 -0
  167. package/dist/browser/react/use-href.d.ts +33 -0
  168. package/dist/browser/react/use-href.d.ts.map +1 -0
  169. package/dist/browser/react/use-href.js +39 -0
  170. package/dist/browser/react/use-href.js.map +1 -0
  171. package/dist/browser/react/use-link-status.d.ts +37 -0
  172. package/dist/browser/react/use-link-status.d.ts.map +1 -0
  173. package/dist/browser/react/use-link-status.js +99 -0
  174. package/dist/browser/react/use-link-status.js.map +1 -0
  175. package/dist/browser/react/use-mount.d.ts +25 -0
  176. package/dist/browser/react/use-mount.d.ts.map +1 -0
  177. package/dist/browser/react/use-mount.js +30 -0
  178. package/dist/browser/react/use-mount.js.map +1 -0
  179. package/dist/browser/react/use-navigation.d.ts +27 -0
  180. package/dist/browser/react/use-navigation.d.ts.map +1 -0
  181. package/dist/browser/react/use-navigation.js +87 -0
  182. package/dist/browser/react/use-navigation.js.map +1 -0
  183. package/dist/browser/react/use-segments.d.ts +38 -0
  184. package/dist/browser/react/use-segments.d.ts.map +1 -0
  185. package/dist/browser/react/use-segments.js +130 -0
  186. package/dist/browser/react/use-segments.js.map +1 -0
  187. package/dist/browser/request-controller.d.ts +26 -0
  188. package/dist/browser/request-controller.d.ts.map +1 -0
  189. package/dist/browser/request-controller.js +147 -0
  190. package/dist/browser/request-controller.js.map +1 -0
  191. package/dist/browser/rsc-router.d.ts +129 -0
  192. package/dist/browser/rsc-router.d.ts.map +1 -0
  193. package/dist/browser/rsc-router.js +195 -0
  194. package/dist/browser/rsc-router.js.map +1 -0
  195. package/dist/browser/scroll-restoration.d.ts +93 -0
  196. package/dist/browser/scroll-restoration.d.ts.map +1 -0
  197. package/dist/browser/scroll-restoration.js +321 -0
  198. package/dist/browser/scroll-restoration.js.map +1 -0
  199. package/dist/browser/segment-structure-assert.d.ts +17 -0
  200. package/dist/browser/segment-structure-assert.d.ts.map +1 -0
  201. package/dist/browser/segment-structure-assert.js +59 -0
  202. package/dist/browser/segment-structure-assert.js.map +1 -0
  203. package/dist/browser/server-action-bridge.d.ts +26 -0
  204. package/dist/browser/server-action-bridge.d.ts.map +1 -0
  205. package/dist/browser/server-action-bridge.js +668 -0
  206. package/dist/browser/server-action-bridge.js.map +1 -0
  207. package/dist/browser/shallow.d.ts +12 -0
  208. package/dist/browser/shallow.d.ts.map +1 -0
  209. package/dist/browser/shallow.js +34 -0
  210. package/dist/browser/shallow.js.map +1 -0
  211. package/dist/browser/types.d.ts +369 -0
  212. package/dist/browser/types.d.ts.map +1 -0
  213. package/dist/browser/types.js +2 -0
  214. package/dist/browser/types.js.map +1 -0
  215. package/dist/build/__tests__/generate-cli.test.d.ts +2 -0
  216. package/dist/build/__tests__/generate-cli.test.d.ts.map +1 -0
  217. package/dist/build/__tests__/generate-cli.test.js +237 -0
  218. package/dist/build/__tests__/generate-cli.test.js.map +1 -0
  219. package/dist/build/__tests__/generate-manifest.test.d.ts +2 -0
  220. package/dist/build/__tests__/generate-manifest.test.d.ts.map +1 -0
  221. package/dist/build/__tests__/generate-manifest.test.js +119 -0
  222. package/dist/build/__tests__/generate-manifest.test.js.map +1 -0
  223. package/dist/build/__tests__/generate-route-types.test.d.ts +2 -0
  224. package/dist/build/__tests__/generate-route-types.test.d.ts.map +1 -0
  225. package/dist/build/__tests__/generate-route-types.test.js +620 -0
  226. package/dist/build/__tests__/generate-route-types.test.js.map +1 -0
  227. package/dist/build/__tests__/per-router-manifest.test.d.ts +2 -0
  228. package/dist/build/__tests__/per-router-manifest.test.d.ts.map +1 -0
  229. package/dist/build/__tests__/per-router-manifest.test.js +308 -0
  230. package/dist/build/__tests__/per-router-manifest.test.js.map +1 -0
  231. package/dist/build/generate-manifest.d.ts +81 -0
  232. package/dist/build/generate-manifest.d.ts.map +1 -0
  233. package/dist/build/generate-manifest.js +276 -0
  234. package/dist/build/generate-manifest.js.map +1 -0
  235. package/dist/build/generate-route-types.d.ts +115 -0
  236. package/dist/build/generate-route-types.d.ts.map +1 -0
  237. package/dist/build/generate-route-types.js +740 -0
  238. package/dist/build/generate-route-types.js.map +1 -0
  239. package/dist/build/index.d.ts +21 -0
  240. package/dist/build/index.d.ts.map +1 -0
  241. package/dist/build/index.js +21 -0
  242. package/dist/build/index.js.map +1 -0
  243. package/dist/build/route-trie.d.ts +71 -0
  244. package/dist/build/route-trie.d.ts.map +1 -0
  245. package/dist/build/route-trie.js +175 -0
  246. package/dist/build/route-trie.js.map +1 -0
  247. package/dist/cache/__tests__/cache-scope.test.d.ts +2 -0
  248. package/dist/cache/__tests__/cache-scope.test.d.ts.map +1 -0
  249. package/dist/cache/__tests__/cache-scope.test.js +208 -0
  250. package/dist/cache/__tests__/cache-scope.test.js.map +1 -0
  251. package/dist/cache/__tests__/document-cache.test.d.ts +2 -0
  252. package/dist/cache/__tests__/document-cache.test.d.ts.map +1 -0
  253. package/dist/cache/__tests__/document-cache.test.js +345 -0
  254. package/dist/cache/__tests__/document-cache.test.js.map +1 -0
  255. package/dist/cache/__tests__/memory-segment-store.test.d.ts +2 -0
  256. package/dist/cache/__tests__/memory-segment-store.test.d.ts.map +1 -0
  257. package/dist/cache/__tests__/memory-segment-store.test.js +425 -0
  258. package/dist/cache/__tests__/memory-segment-store.test.js.map +1 -0
  259. package/dist/cache/__tests__/memory-store.test.d.ts +2 -0
  260. package/dist/cache/__tests__/memory-store.test.d.ts.map +1 -0
  261. package/dist/cache/__tests__/memory-store.test.js +367 -0
  262. package/dist/cache/__tests__/memory-store.test.js.map +1 -0
  263. package/dist/cache/cache-scope.d.ts +102 -0
  264. package/dist/cache/cache-scope.d.ts.map +1 -0
  265. package/dist/cache/cache-scope.js +440 -0
  266. package/dist/cache/cache-scope.js.map +1 -0
  267. package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts +2 -0
  268. package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts.map +1 -0
  269. package/dist/cache/cf/__tests__/cf-cache-store.test.js +330 -0
  270. package/dist/cache/cf/__tests__/cf-cache-store.test.js.map +1 -0
  271. package/dist/cache/cf/cf-cache-store.d.ts +165 -0
  272. package/dist/cache/cf/cf-cache-store.d.ts.map +1 -0
  273. package/dist/cache/cf/cf-cache-store.js +242 -0
  274. package/dist/cache/cf/cf-cache-store.js.map +1 -0
  275. package/dist/cache/cf/index.d.ts +14 -0
  276. package/dist/cache/cf/index.d.ts.map +1 -0
  277. package/dist/cache/cf/index.js +17 -0
  278. package/dist/cache/cf/index.js.map +1 -0
  279. package/dist/cache/document-cache.d.ts +64 -0
  280. package/dist/cache/document-cache.d.ts.map +1 -0
  281. package/dist/cache/document-cache.js +228 -0
  282. package/dist/cache/document-cache.js.map +1 -0
  283. package/dist/cache/index.d.ts +19 -0
  284. package/dist/cache/index.d.ts.map +1 -0
  285. package/dist/cache/index.js +21 -0
  286. package/dist/cache/index.js.map +1 -0
  287. package/dist/cache/memory-segment-store.d.ts +110 -0
  288. package/dist/cache/memory-segment-store.d.ts.map +1 -0
  289. package/dist/cache/memory-segment-store.js +117 -0
  290. package/dist/cache/memory-segment-store.js.map +1 -0
  291. package/dist/cache/memory-store.d.ts +41 -0
  292. package/dist/cache/memory-store.d.ts.map +1 -0
  293. package/dist/cache/memory-store.js +191 -0
  294. package/dist/cache/memory-store.js.map +1 -0
  295. package/dist/cache/types.d.ts +317 -0
  296. package/dist/cache/types.d.ts.map +1 -0
  297. package/dist/cache/types.js +12 -0
  298. package/dist/cache/types.js.map +1 -0
  299. package/dist/client.d.ts +248 -0
  300. package/dist/client.d.ts.map +1 -0
  301. package/dist/client.js +367 -0
  302. package/dist/client.js.map +1 -0
  303. package/dist/client.rsc.d.ts +26 -0
  304. package/dist/client.rsc.d.ts.map +1 -0
  305. package/dist/client.rsc.js +46 -0
  306. package/dist/client.rsc.js.map +1 -0
  307. package/dist/component-utils.d.ts +36 -0
  308. package/dist/component-utils.d.ts.map +1 -0
  309. package/dist/component-utils.js +61 -0
  310. package/dist/component-utils.js.map +1 -0
  311. package/dist/components/DefaultDocument.d.ts +13 -0
  312. package/dist/components/DefaultDocument.d.ts.map +1 -0
  313. package/dist/components/DefaultDocument.js +15 -0
  314. package/dist/components/DefaultDocument.js.map +1 -0
  315. package/dist/debug.d.ts +58 -0
  316. package/dist/debug.d.ts.map +1 -0
  317. package/dist/debug.js +157 -0
  318. package/dist/debug.js.map +1 -0
  319. package/dist/default-error-boundary.d.ts +11 -0
  320. package/dist/default-error-boundary.d.ts.map +1 -0
  321. package/dist/default-error-boundary.js +45 -0
  322. package/dist/default-error-boundary.js.map +1 -0
  323. package/dist/deps/browser.d.ts +2 -0
  324. package/dist/deps/browser.d.ts.map +1 -0
  325. package/dist/deps/browser.js +3 -0
  326. package/dist/deps/browser.js.map +1 -0
  327. package/dist/deps/html-stream-client.d.ts +2 -0
  328. package/dist/deps/html-stream-client.d.ts.map +1 -0
  329. package/dist/deps/html-stream-client.js +3 -0
  330. package/dist/deps/html-stream-client.js.map +1 -0
  331. package/dist/deps/html-stream-server.d.ts +2 -0
  332. package/dist/deps/html-stream-server.d.ts.map +1 -0
  333. package/dist/deps/html-stream-server.js +3 -0
  334. package/dist/deps/html-stream-server.js.map +1 -0
  335. package/dist/deps/rsc.d.ts +2 -0
  336. package/dist/deps/rsc.d.ts.map +1 -0
  337. package/dist/deps/rsc.js +4 -0
  338. package/dist/deps/rsc.js.map +1 -0
  339. package/dist/deps/ssr.d.ts +2 -0
  340. package/dist/deps/ssr.d.ts.map +1 -0
  341. package/dist/deps/ssr.js +3 -0
  342. package/dist/deps/ssr.js.map +1 -0
  343. package/dist/errors.d.ts +174 -0
  344. package/dist/errors.d.ts.map +1 -0
  345. package/dist/errors.js +241 -0
  346. package/dist/errors.js.map +1 -0
  347. package/dist/handle.d.ts +78 -0
  348. package/dist/handle.d.ts.map +1 -0
  349. package/dist/handle.js +82 -0
  350. package/dist/handle.js.map +1 -0
  351. package/dist/handles/MetaTags.d.ts +14 -0
  352. package/dist/handles/MetaTags.d.ts.map +1 -0
  353. package/dist/handles/MetaTags.js +136 -0
  354. package/dist/handles/MetaTags.js.map +1 -0
  355. package/dist/handles/index.d.ts +6 -0
  356. package/dist/handles/index.d.ts.map +1 -0
  357. package/dist/handles/index.js +6 -0
  358. package/dist/handles/index.js.map +1 -0
  359. package/dist/handles/meta.d.ts +39 -0
  360. package/dist/handles/meta.d.ts.map +1 -0
  361. package/dist/handles/meta.js +202 -0
  362. package/dist/handles/meta.js.map +1 -0
  363. package/dist/host/__tests__/errors.test.d.ts +2 -0
  364. package/dist/host/__tests__/errors.test.d.ts.map +1 -0
  365. package/dist/host/__tests__/errors.test.js +76 -0
  366. package/dist/host/__tests__/errors.test.js.map +1 -0
  367. package/dist/host/__tests__/pattern-comprehensive.test.d.ts +2 -0
  368. package/dist/host/__tests__/pattern-comprehensive.test.d.ts.map +1 -0
  369. package/dist/host/__tests__/pattern-comprehensive.test.js +732 -0
  370. package/dist/host/__tests__/pattern-comprehensive.test.js.map +1 -0
  371. package/dist/host/__tests__/pattern-matcher.test.d.ts +2 -0
  372. package/dist/host/__tests__/pattern-matcher.test.d.ts.map +1 -0
  373. package/dist/host/__tests__/pattern-matcher.test.js +251 -0
  374. package/dist/host/__tests__/pattern-matcher.test.js.map +1 -0
  375. package/dist/host/__tests__/router.test.d.ts +2 -0
  376. package/dist/host/__tests__/router.test.d.ts.map +1 -0
  377. package/dist/host/__tests__/router.test.js +241 -0
  378. package/dist/host/__tests__/router.test.js.map +1 -0
  379. package/dist/host/__tests__/testing.test.d.ts +2 -0
  380. package/dist/host/__tests__/testing.test.d.ts.map +1 -0
  381. package/dist/host/__tests__/testing.test.js +64 -0
  382. package/dist/host/__tests__/testing.test.js.map +1 -0
  383. package/dist/host/__tests__/utils.test.d.ts +2 -0
  384. package/dist/host/__tests__/utils.test.d.ts.map +1 -0
  385. package/dist/host/__tests__/utils.test.js +29 -0
  386. package/dist/host/__tests__/utils.test.js.map +1 -0
  387. package/dist/host/cookie-handler.d.ts +34 -0
  388. package/dist/host/cookie-handler.d.ts.map +1 -0
  389. package/dist/host/cookie-handler.js +124 -0
  390. package/dist/host/cookie-handler.js.map +1 -0
  391. package/dist/host/errors.d.ts +56 -0
  392. package/dist/host/errors.d.ts.map +1 -0
  393. package/dist/host/errors.js +79 -0
  394. package/dist/host/errors.js.map +1 -0
  395. package/dist/host/index.d.ts +29 -0
  396. package/dist/host/index.d.ts.map +1 -0
  397. package/dist/host/index.js +32 -0
  398. package/dist/host/index.js.map +1 -0
  399. package/dist/host/pattern-matcher.d.ts +36 -0
  400. package/dist/host/pattern-matcher.d.ts.map +1 -0
  401. package/dist/host/pattern-matcher.js +172 -0
  402. package/dist/host/pattern-matcher.js.map +1 -0
  403. package/dist/host/router.d.ts +26 -0
  404. package/dist/host/router.d.ts.map +1 -0
  405. package/dist/host/router.js +218 -0
  406. package/dist/host/router.js.map +1 -0
  407. package/dist/host/testing.d.ts +36 -0
  408. package/dist/host/testing.d.ts.map +1 -0
  409. package/dist/host/testing.js +55 -0
  410. package/dist/host/testing.js.map +1 -0
  411. package/dist/host/types.d.ts +115 -0
  412. package/dist/host/types.d.ts.map +1 -0
  413. package/dist/host/types.js +7 -0
  414. package/dist/host/types.js.map +1 -0
  415. package/dist/host/utils.d.ts +21 -0
  416. package/dist/host/utils.d.ts.map +1 -0
  417. package/dist/host/utils.js +23 -0
  418. package/dist/host/utils.js.map +1 -0
  419. package/dist/href-client.d.ts +131 -0
  420. package/dist/href-client.d.ts.map +1 -0
  421. package/dist/href-client.js +64 -0
  422. package/dist/href-client.js.map +1 -0
  423. package/{src/href-context.ts → dist/href-context.d.ts} +7 -11
  424. package/dist/href-context.d.ts.map +1 -0
  425. package/dist/href-context.js +21 -0
  426. package/dist/href-context.js.map +1 -0
  427. package/dist/index.d.ts +73 -0
  428. package/dist/index.d.ts.map +1 -0
  429. package/dist/index.js +91 -0
  430. package/dist/index.js.map +1 -0
  431. package/dist/index.rsc.d.ts +32 -0
  432. package/dist/index.rsc.d.ts.map +1 -0
  433. package/dist/index.rsc.js +40 -0
  434. package/dist/index.rsc.js.map +1 -0
  435. package/dist/internal-debug.d.ts +2 -0
  436. package/dist/internal-debug.d.ts.map +1 -0
  437. package/dist/internal-debug.js +5 -0
  438. package/dist/internal-debug.js.map +1 -0
  439. package/dist/loader.d.ts +14 -0
  440. package/dist/loader.d.ts.map +1 -0
  441. package/dist/loader.js +20 -0
  442. package/dist/loader.js.map +1 -0
  443. package/dist/loader.rsc.d.ts +19 -0
  444. package/dist/loader.rsc.d.ts.map +1 -0
  445. package/dist/loader.rsc.js +99 -0
  446. package/dist/loader.rsc.js.map +1 -0
  447. package/dist/network-error-thrower.d.ts +17 -0
  448. package/dist/network-error-thrower.d.ts.map +1 -0
  449. package/dist/network-error-thrower.js +14 -0
  450. package/dist/network-error-thrower.js.map +1 -0
  451. package/dist/outlet-context.d.ts +13 -0
  452. package/dist/outlet-context.d.ts.map +1 -0
  453. package/dist/outlet-context.js +3 -0
  454. package/dist/outlet-context.js.map +1 -0
  455. package/dist/prerender/__tests__/param-hash.test.d.ts +2 -0
  456. package/dist/prerender/__tests__/param-hash.test.d.ts.map +1 -0
  457. package/dist/prerender/__tests__/param-hash.test.js +148 -0
  458. package/dist/prerender/__tests__/param-hash.test.js.map +1 -0
  459. package/dist/prerender/param-hash.d.ts +16 -0
  460. package/dist/prerender/param-hash.d.ts.map +1 -0
  461. package/dist/prerender/param-hash.js +36 -0
  462. package/dist/prerender/param-hash.js.map +1 -0
  463. package/dist/prerender/store.d.ts +38 -0
  464. package/dist/prerender/store.d.ts.map +1 -0
  465. package/dist/prerender/store.js +61 -0
  466. package/dist/prerender/store.js.map +1 -0
  467. package/dist/prerender.d.ts +66 -0
  468. package/dist/prerender.d.ts.map +1 -0
  469. package/dist/prerender.js +57 -0
  470. package/dist/prerender.js.map +1 -0
  471. package/dist/reverse.d.ts +196 -0
  472. package/dist/reverse.d.ts.map +1 -0
  473. package/dist/reverse.js +78 -0
  474. package/dist/reverse.js.map +1 -0
  475. package/dist/root-error-boundary.d.ts +33 -0
  476. package/dist/root-error-boundary.d.ts.map +1 -0
  477. package/dist/root-error-boundary.js +165 -0
  478. package/dist/root-error-boundary.js.map +1 -0
  479. package/dist/route-content-wrapper.d.ts +46 -0
  480. package/dist/route-content-wrapper.d.ts.map +1 -0
  481. package/dist/route-content-wrapper.js +77 -0
  482. package/dist/route-content-wrapper.js.map +1 -0
  483. package/dist/route-definition.d.ts +421 -0
  484. package/dist/route-definition.d.ts.map +1 -0
  485. package/dist/route-definition.js +868 -0
  486. package/dist/route-definition.js.map +1 -0
  487. package/dist/route-map-builder.d.ts +155 -0
  488. package/dist/route-map-builder.d.ts.map +1 -0
  489. package/dist/route-map-builder.js +237 -0
  490. package/dist/route-map-builder.js.map +1 -0
  491. package/dist/route-types.d.ts +165 -0
  492. package/dist/route-types.d.ts.map +1 -0
  493. package/dist/route-types.js +7 -0
  494. package/dist/route-types.js.map +1 -0
  495. package/dist/router/__tests__/handler-context.test.d.ts +2 -0
  496. package/dist/router/__tests__/handler-context.test.d.ts.map +1 -0
  497. package/dist/router/__tests__/handler-context.test.js +65 -0
  498. package/dist/router/__tests__/handler-context.test.js.map +1 -0
  499. package/dist/router/__tests__/loader-cycle-detection.test.d.ts +2 -0
  500. package/dist/router/__tests__/loader-cycle-detection.test.d.ts.map +1 -0
  501. package/dist/router/__tests__/loader-cycle-detection.test.js +221 -0
  502. package/dist/router/__tests__/loader-cycle-detection.test.js.map +1 -0
  503. package/dist/router/__tests__/match-context.test.d.ts +2 -0
  504. package/dist/router/__tests__/match-context.test.d.ts.map +1 -0
  505. package/dist/router/__tests__/match-context.test.js +92 -0
  506. package/dist/router/__tests__/match-context.test.js.map +1 -0
  507. package/dist/router/__tests__/match-pipelines.test.d.ts +2 -0
  508. package/dist/router/__tests__/match-pipelines.test.d.ts.map +1 -0
  509. package/dist/router/__tests__/match-pipelines.test.js +417 -0
  510. package/dist/router/__tests__/match-pipelines.test.js.map +1 -0
  511. package/dist/router/__tests__/match-result.test.d.ts +2 -0
  512. package/dist/router/__tests__/match-result.test.d.ts.map +1 -0
  513. package/dist/router/__tests__/match-result.test.js +457 -0
  514. package/dist/router/__tests__/match-result.test.js.map +1 -0
  515. package/dist/router/__tests__/on-error.test.d.ts +2 -0
  516. package/dist/router/__tests__/on-error.test.d.ts.map +1 -0
  517. package/dist/router/__tests__/on-error.test.js +678 -0
  518. package/dist/router/__tests__/on-error.test.js.map +1 -0
  519. package/dist/router/__tests__/pattern-matching.test.d.ts +2 -0
  520. package/dist/router/__tests__/pattern-matching.test.d.ts.map +1 -0
  521. package/dist/router/__tests__/pattern-matching.test.js +629 -0
  522. package/dist/router/__tests__/pattern-matching.test.js.map +1 -0
  523. package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts +2 -0
  524. package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts.map +1 -0
  525. package/dist/router/__tests__/segment-resolution-parallel-loading.test.js +155 -0
  526. package/dist/router/__tests__/segment-resolution-parallel-loading.test.js.map +1 -0
  527. package/dist/router/error-handling.d.ts +77 -0
  528. package/dist/router/error-handling.d.ts.map +1 -0
  529. package/dist/router/error-handling.js +202 -0
  530. package/dist/router/error-handling.js.map +1 -0
  531. package/dist/router/handler-context.d.ts +20 -0
  532. package/dist/router/handler-context.d.ts.map +1 -0
  533. package/dist/router/handler-context.js +198 -0
  534. package/dist/router/handler-context.js.map +1 -0
  535. package/dist/router/intercept-resolution.d.ts +66 -0
  536. package/dist/router/intercept-resolution.d.ts.map +1 -0
  537. package/dist/router/intercept-resolution.js +246 -0
  538. package/dist/router/intercept-resolution.js.map +1 -0
  539. package/dist/router/loader-resolution.d.ts +64 -0
  540. package/dist/router/loader-resolution.d.ts.map +1 -0
  541. package/dist/router/loader-resolution.js +284 -0
  542. package/dist/router/loader-resolution.js.map +1 -0
  543. package/dist/router/logging.d.ts +15 -0
  544. package/dist/router/logging.d.ts.map +1 -0
  545. package/dist/router/logging.js +99 -0
  546. package/dist/router/logging.js.map +1 -0
  547. package/dist/router/manifest.d.ts +22 -0
  548. package/dist/router/manifest.d.ts.map +1 -0
  549. package/dist/router/manifest.js +181 -0
  550. package/dist/router/manifest.js.map +1 -0
  551. package/dist/router/match-api.d.ts +35 -0
  552. package/dist/router/match-api.d.ts.map +1 -0
  553. package/dist/router/match-api.js +406 -0
  554. package/dist/router/match-api.js.map +1 -0
  555. package/dist/router/match-context.d.ts +206 -0
  556. package/dist/router/match-context.d.ts.map +1 -0
  557. package/dist/router/match-context.js +17 -0
  558. package/dist/router/match-context.js.map +1 -0
  559. package/dist/router/match-middleware/background-revalidation.d.ts +127 -0
  560. package/dist/router/match-middleware/background-revalidation.d.ts.map +1 -0
  561. package/dist/router/match-middleware/background-revalidation.js +75 -0
  562. package/dist/router/match-middleware/background-revalidation.js.map +1 -0
  563. package/dist/router/match-middleware/cache-lookup.d.ts +112 -0
  564. package/dist/router/match-middleware/cache-lookup.d.ts.map +1 -0
  565. package/dist/router/match-middleware/cache-lookup.js +257 -0
  566. package/dist/router/match-middleware/cache-lookup.js.map +1 -0
  567. package/dist/router/match-middleware/cache-store.d.ts +113 -0
  568. package/dist/router/match-middleware/cache-store.d.ts.map +1 -0
  569. package/dist/router/match-middleware/cache-store.js +108 -0
  570. package/dist/router/match-middleware/cache-store.js.map +1 -0
  571. package/dist/router/match-middleware/index.d.ts +81 -0
  572. package/dist/router/match-middleware/index.d.ts.map +1 -0
  573. package/dist/router/match-middleware/index.js +80 -0
  574. package/dist/router/match-middleware/index.js.map +1 -0
  575. package/dist/router/match-middleware/intercept-resolution.d.ts +117 -0
  576. package/dist/router/match-middleware/intercept-resolution.d.ts.map +1 -0
  577. package/dist/router/match-middleware/intercept-resolution.js +134 -0
  578. package/dist/router/match-middleware/intercept-resolution.js.map +1 -0
  579. package/dist/router/match-middleware/segment-resolution.d.ts +99 -0
  580. package/dist/router/match-middleware/segment-resolution.d.ts.map +1 -0
  581. package/dist/router/match-middleware/segment-resolution.js +53 -0
  582. package/dist/router/match-middleware/segment-resolution.js.map +1 -0
  583. package/dist/router/match-pipelines.d.ts +147 -0
  584. package/dist/router/match-pipelines.d.ts.map +1 -0
  585. package/dist/router/match-pipelines.js +82 -0
  586. package/dist/router/match-pipelines.js.map +1 -0
  587. package/dist/router/match-result.d.ts +126 -0
  588. package/dist/router/match-result.d.ts.map +1 -0
  589. package/dist/router/match-result.js +93 -0
  590. package/dist/router/match-result.js.map +1 -0
  591. package/dist/router/metrics.d.ts +20 -0
  592. package/dist/router/metrics.d.ts.map +1 -0
  593. package/dist/router/metrics.js +47 -0
  594. package/dist/router/metrics.js.map +1 -0
  595. package/dist/router/middleware.d.ts +249 -0
  596. package/dist/router/middleware.d.ts.map +1 -0
  597. package/dist/router/middleware.js +434 -0
  598. package/dist/router/middleware.js.map +1 -0
  599. package/dist/router/middleware.test.d.ts +2 -0
  600. package/dist/router/middleware.test.d.ts.map +1 -0
  601. package/dist/router/middleware.test.js +816 -0
  602. package/dist/router/middleware.test.js.map +1 -0
  603. package/dist/router/pattern-matching.d.ts +149 -0
  604. package/dist/router/pattern-matching.d.ts.map +1 -0
  605. package/dist/router/pattern-matching.js +349 -0
  606. package/dist/router/pattern-matching.js.map +1 -0
  607. package/dist/router/revalidation.d.ts +44 -0
  608. package/dist/router/revalidation.d.ts.map +1 -0
  609. package/dist/router/revalidation.js +147 -0
  610. package/dist/router/revalidation.js.map +1 -0
  611. package/dist/router/router-context.d.ts +135 -0
  612. package/dist/router/router-context.d.ts.map +1 -0
  613. package/dist/router/router-context.js +36 -0
  614. package/dist/router/router-context.js.map +1 -0
  615. package/dist/router/segment-resolution.d.ts +127 -0
  616. package/dist/router/segment-resolution.d.ts.map +1 -0
  617. package/dist/router/segment-resolution.js +919 -0
  618. package/dist/router/segment-resolution.js.map +1 -0
  619. package/dist/router/trie-matching.d.ts +40 -0
  620. package/dist/router/trie-matching.d.ts.map +1 -0
  621. package/dist/router/trie-matching.js +127 -0
  622. package/dist/router/trie-matching.js.map +1 -0
  623. package/dist/router/types.d.ts +136 -0
  624. package/dist/router/types.d.ts.map +1 -0
  625. package/dist/router/types.js +7 -0
  626. package/dist/router/types.js.map +1 -0
  627. package/dist/router.d.ts +753 -0
  628. package/dist/router.d.ts.map +1 -0
  629. package/dist/router.gen.d.ts +6 -0
  630. package/dist/router.gen.d.ts.map +1 -0
  631. package/dist/router.gen.js +6 -0
  632. package/dist/router.gen.js.map +1 -0
  633. package/dist/router.js +1304 -0
  634. package/dist/router.js.map +1 -0
  635. package/dist/rsc/__tests__/helpers.test.d.ts +2 -0
  636. package/dist/rsc/__tests__/helpers.test.d.ts.map +1 -0
  637. package/dist/rsc/__tests__/helpers.test.js +140 -0
  638. package/dist/rsc/__tests__/helpers.test.js.map +1 -0
  639. package/dist/rsc/handler.d.ts +45 -0
  640. package/dist/rsc/handler.d.ts.map +1 -0
  641. package/dist/rsc/handler.js +1172 -0
  642. package/dist/rsc/handler.js.map +1 -0
  643. package/dist/rsc/helpers.d.ts +16 -0
  644. package/dist/rsc/helpers.d.ts.map +1 -0
  645. package/dist/rsc/helpers.js +55 -0
  646. package/dist/rsc/helpers.js.map +1 -0
  647. package/dist/rsc/index.d.ts +22 -0
  648. package/dist/rsc/index.d.ts.map +1 -0
  649. package/dist/rsc/index.js +23 -0
  650. package/dist/rsc/index.js.map +1 -0
  651. package/dist/rsc/nonce.d.ts +9 -0
  652. package/dist/rsc/nonce.d.ts.map +1 -0
  653. package/dist/rsc/nonce.js +18 -0
  654. package/dist/rsc/nonce.js.map +1 -0
  655. package/dist/rsc/types.d.ts +206 -0
  656. package/dist/rsc/types.d.ts.map +1 -0
  657. package/dist/rsc/types.js +8 -0
  658. package/dist/rsc/types.js.map +1 -0
  659. package/dist/search-params.d.ts +103 -0
  660. package/dist/search-params.d.ts.map +1 -0
  661. package/dist/search-params.js +74 -0
  662. package/dist/search-params.js.map +1 -0
  663. package/dist/segment-system.d.ts +75 -0
  664. package/dist/segment-system.d.ts.map +1 -0
  665. package/dist/segment-system.js +336 -0
  666. package/dist/segment-system.js.map +1 -0
  667. package/dist/server/context.d.ts +245 -0
  668. package/dist/server/context.d.ts.map +1 -0
  669. package/dist/server/context.js +197 -0
  670. package/dist/server/context.js.map +1 -0
  671. package/dist/server/fetchable-loader-store.d.ts +18 -0
  672. package/dist/server/fetchable-loader-store.d.ts.map +1 -0
  673. package/dist/server/fetchable-loader-store.js +18 -0
  674. package/dist/server/fetchable-loader-store.js.map +1 -0
  675. package/dist/server/handle-store.d.ts +85 -0
  676. package/dist/server/handle-store.d.ts.map +1 -0
  677. package/dist/server/handle-store.js +142 -0
  678. package/dist/server/handle-store.js.map +1 -0
  679. package/dist/server/loader-registry.d.ts +55 -0
  680. package/dist/server/loader-registry.d.ts.map +1 -0
  681. package/dist/server/loader-registry.js +132 -0
  682. package/dist/server/loader-registry.js.map +1 -0
  683. package/dist/server/request-context.d.ts +226 -0
  684. package/dist/server/request-context.d.ts.map +1 -0
  685. package/dist/server/request-context.js +290 -0
  686. package/dist/server/request-context.js.map +1 -0
  687. package/dist/server/root-layout.d.ts +4 -0
  688. package/dist/server/root-layout.d.ts.map +1 -0
  689. package/dist/server/root-layout.js +5 -0
  690. package/dist/server/root-layout.js.map +1 -0
  691. package/dist/server.d.ts +15 -0
  692. package/dist/server.d.ts.map +1 -0
  693. package/dist/server.js +20 -0
  694. package/dist/server.js.map +1 -0
  695. package/dist/ssr/__tests__/ssr-handler.test.d.ts +2 -0
  696. package/dist/ssr/__tests__/ssr-handler.test.d.ts.map +1 -0
  697. package/dist/ssr/__tests__/ssr-handler.test.js +132 -0
  698. package/dist/ssr/__tests__/ssr-handler.test.js.map +1 -0
  699. package/dist/ssr/index.d.ts +98 -0
  700. package/dist/ssr/index.d.ts.map +1 -0
  701. package/dist/ssr/index.js +158 -0
  702. package/dist/ssr/index.js.map +1 -0
  703. package/dist/static-handler.d.ts +50 -0
  704. package/dist/static-handler.d.ts.map +1 -0
  705. package/dist/static-handler.gen.d.ts +5 -0
  706. package/dist/static-handler.gen.d.ts.map +1 -0
  707. package/dist/static-handler.gen.js +5 -0
  708. package/dist/static-handler.gen.js.map +1 -0
  709. package/dist/static-handler.js +29 -0
  710. package/dist/static-handler.js.map +1 -0
  711. package/dist/theme/ThemeProvider.d.ts +20 -0
  712. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  713. package/dist/theme/ThemeProvider.js +240 -0
  714. package/dist/theme/ThemeProvider.js.map +1 -0
  715. package/dist/theme/ThemeScript.d.ts +48 -0
  716. package/dist/theme/ThemeScript.d.ts.map +1 -0
  717. package/dist/theme/ThemeScript.js +13 -0
  718. package/dist/theme/ThemeScript.js.map +1 -0
  719. package/dist/theme/__tests__/theme.test.d.ts +2 -0
  720. package/dist/theme/__tests__/theme.test.d.ts.map +1 -0
  721. package/dist/theme/__tests__/theme.test.js +103 -0
  722. package/dist/theme/__tests__/theme.test.js.map +1 -0
  723. package/dist/theme/constants.d.ts +29 -0
  724. package/dist/theme/constants.d.ts.map +1 -0
  725. package/dist/theme/constants.js +48 -0
  726. package/dist/theme/constants.js.map +1 -0
  727. package/dist/theme/index.d.ts +31 -0
  728. package/dist/theme/index.d.ts.map +1 -0
  729. package/dist/theme/index.js +36 -0
  730. package/dist/theme/index.js.map +1 -0
  731. package/dist/theme/theme-context.d.ts +40 -0
  732. package/dist/theme/theme-context.d.ts.map +1 -0
  733. package/dist/theme/theme-context.js +60 -0
  734. package/dist/theme/theme-context.js.map +1 -0
  735. package/dist/theme/theme-script.d.ts +27 -0
  736. package/dist/theme/theme-script.d.ts.map +1 -0
  737. package/dist/theme/theme-script.js +147 -0
  738. package/dist/theme/theme-script.js.map +1 -0
  739. package/dist/theme/types.d.ts +163 -0
  740. package/dist/theme/types.d.ts.map +1 -0
  741. package/dist/theme/types.js +11 -0
  742. package/dist/theme/types.js.map +1 -0
  743. package/dist/theme/use-theme.d.ts +12 -0
  744. package/dist/theme/use-theme.d.ts.map +1 -0
  745. package/dist/theme/use-theme.js +40 -0
  746. package/dist/theme/use-theme.js.map +1 -0
  747. package/dist/types.d.ts +1479 -0
  748. package/dist/types.d.ts.map +1 -0
  749. package/dist/types.js +10 -0
  750. package/dist/types.js.map +1 -0
  751. package/dist/urls.d.ts +441 -0
  752. package/dist/urls.d.ts.map +1 -0
  753. package/dist/urls.gen.d.ts +8 -0
  754. package/dist/urls.gen.d.ts.map +1 -0
  755. package/dist/urls.gen.js +8 -0
  756. package/dist/urls.gen.js.map +1 -0
  757. package/dist/urls.js +443 -0
  758. package/dist/urls.js.map +1 -0
  759. package/dist/use-loader.d.ts +127 -0
  760. package/dist/use-loader.d.ts.map +1 -0
  761. package/dist/use-loader.js +237 -0
  762. package/dist/use-loader.js.map +1 -0
  763. package/dist/vite/__tests__/ast-handler-extract.test.d.ts +2 -0
  764. package/dist/vite/__tests__/ast-handler-extract.test.d.ts.map +1 -0
  765. package/dist/vite/__tests__/ast-handler-extract.test.js +294 -0
  766. package/dist/vite/__tests__/ast-handler-extract.test.js.map +1 -0
  767. package/dist/vite/__tests__/expose-id-utils.test.d.ts +2 -0
  768. package/dist/vite/__tests__/expose-id-utils.test.d.ts.map +1 -0
  769. package/dist/vite/__tests__/expose-id-utils.test.js +224 -0
  770. package/dist/vite/__tests__/expose-id-utils.test.js.map +1 -0
  771. package/dist/vite/__tests__/expose-internal-ids.test.d.ts +2 -0
  772. package/dist/vite/__tests__/expose-internal-ids.test.d.ts.map +1 -0
  773. package/dist/vite/__tests__/expose-internal-ids.test.js +647 -0
  774. package/dist/vite/__tests__/expose-internal-ids.test.js.map +1 -0
  775. package/dist/vite/__tests__/expose-router-id.test.d.ts +2 -0
  776. package/dist/vite/__tests__/expose-router-id.test.d.ts.map +1 -0
  777. package/dist/vite/__tests__/expose-router-id.test.js +39 -0
  778. package/dist/vite/__tests__/expose-router-id.test.js.map +1 -0
  779. package/dist/vite/ast-handler-extract.d.ts +49 -0
  780. package/dist/vite/ast-handler-extract.d.ts.map +1 -0
  781. package/dist/vite/ast-handler-extract.js +249 -0
  782. package/dist/vite/ast-handler-extract.js.map +1 -0
  783. package/dist/vite/expose-action-id.d.ts +19 -0
  784. package/dist/vite/expose-action-id.d.ts.map +1 -0
  785. package/dist/vite/expose-action-id.js +250 -0
  786. package/dist/vite/expose-action-id.js.map +1 -0
  787. package/dist/vite/expose-id-utils.d.ts +69 -0
  788. package/dist/vite/expose-id-utils.d.ts.map +1 -0
  789. package/dist/vite/expose-id-utils.js +289 -0
  790. package/dist/vite/expose-id-utils.js.map +1 -0
  791. package/dist/vite/expose-internal-ids.d.ts +22 -0
  792. package/dist/vite/expose-internal-ids.d.ts.map +1 -0
  793. package/dist/vite/expose-internal-ids.js +886 -0
  794. package/dist/vite/expose-internal-ids.js.map +1 -0
  795. package/dist/vite/index.d.ts +149 -0
  796. package/dist/vite/index.d.ts.map +1 -0
  797. package/dist/vite/index.js +3995 -2489
  798. package/dist/vite/index.js.map +1 -0
  799. package/dist/vite/package-resolution.d.ts +43 -0
  800. package/dist/vite/package-resolution.d.ts.map +1 -0
  801. package/dist/vite/package-resolution.js +112 -0
  802. package/dist/vite/package-resolution.js.map +1 -0
  803. package/dist/vite/virtual-entries.d.ts +25 -0
  804. package/dist/vite/virtual-entries.d.ts.map +1 -0
  805. package/{src/vite/virtual-entries.ts → dist/vite/virtual-entries.js} +12 -16
  806. package/dist/vite/virtual-entries.js.map +1 -0
  807. package/package.json +57 -52
  808. package/skills/breadcrumbs/SKILL.md +250 -0
  809. package/skills/cache-guide/SKILL.md +262 -0
  810. package/skills/caching/SKILL.md +85 -23
  811. package/skills/composability/SKILL.md +172 -0
  812. package/skills/debug-manifest/SKILL.md +12 -8
  813. package/skills/document-cache/SKILL.md +18 -16
  814. package/skills/fonts/SKILL.md +6 -4
  815. package/skills/hooks/SKILL.md +328 -70
  816. package/skills/host-router/SKILL.md +218 -0
  817. package/skills/intercept/SKILL.md +131 -8
  818. package/skills/layout/SKILL.md +100 -3
  819. package/skills/links/SKILL.md +62 -15
  820. package/skills/loader/SKILL.md +368 -42
  821. package/skills/middleware/SKILL.md +171 -34
  822. package/skills/mime-routes/SKILL.md +14 -10
  823. package/skills/parallel/SKILL.md +137 -1
  824. package/skills/prerender/SKILL.md +366 -28
  825. package/skills/rango/SKILL.md +85 -21
  826. package/skills/response-routes/SKILL.md +136 -83
  827. package/skills/route/SKILL.md +195 -21
  828. package/skills/router-setup/SKILL.md +123 -30
  829. package/skills/theme/SKILL.md +9 -8
  830. package/skills/typesafety/SKILL.md +240 -102
  831. package/skills/use-cache/SKILL.md +324 -0
  832. package/src/__internal.ts +102 -4
  833. package/src/bin/rango.ts +312 -15
  834. package/src/browser/action-coordinator.ts +97 -0
  835. package/src/browser/action-response-classifier.ts +99 -0
  836. package/src/browser/event-controller.ts +92 -64
  837. package/src/browser/history-state.ts +80 -0
  838. package/src/browser/intercept-utils.ts +52 -0
  839. package/src/browser/link-interceptor.ts +24 -4
  840. package/src/browser/logging.ts +11 -0
  841. package/src/browser/merge-segment-loaders.ts +20 -12
  842. package/src/browser/navigation-bridge.ts +266 -558
  843. package/src/browser/navigation-client.ts +132 -75
  844. package/src/browser/navigation-store.ts +33 -50
  845. package/src/browser/navigation-transaction.ts +297 -0
  846. package/src/browser/network-error-handler.ts +61 -0
  847. package/src/browser/partial-update.ts +292 -309
  848. package/src/browser/prefetch/cache.ts +206 -0
  849. package/src/browser/prefetch/fetch.ts +144 -0
  850. package/src/browser/prefetch/observer.ts +65 -0
  851. package/src/browser/prefetch/policy.ts +48 -0
  852. package/src/browser/prefetch/queue.ts +128 -0
  853. package/src/browser/rango-state.ts +112 -0
  854. package/src/browser/react/Link.tsx +190 -70
  855. package/src/browser/react/NavigationProvider.tsx +78 -11
  856. package/src/browser/react/context.ts +6 -0
  857. package/src/browser/react/filter-segment-order.ts +11 -0
  858. package/src/browser/react/index.ts +12 -12
  859. package/src/browser/react/location-state-shared.ts +95 -53
  860. package/src/browser/react/location-state.ts +60 -15
  861. package/src/browser/react/mount-context.ts +6 -1
  862. package/src/browser/react/nonce-context.ts +23 -0
  863. package/src/browser/react/shallow-equal.ts +27 -0
  864. package/src/browser/react/use-action.ts +29 -51
  865. package/src/browser/react/use-client-cache.ts +5 -3
  866. package/src/browser/react/use-handle.ts +29 -70
  867. package/src/browser/react/use-link-status.ts +6 -5
  868. package/src/browser/react/use-navigation.ts +22 -63
  869. package/src/browser/react/use-params.ts +65 -0
  870. package/src/browser/react/use-pathname.ts +47 -0
  871. package/src/browser/react/use-router.ts +63 -0
  872. package/src/browser/react/use-search-params.ts +56 -0
  873. package/src/browser/react/use-segments.ts +80 -97
  874. package/src/browser/response-adapter.ts +73 -0
  875. package/src/browser/rsc-router.tsx +188 -57
  876. package/src/browser/scroll-restoration.ts +117 -44
  877. package/src/browser/segment-reconciler.ts +221 -0
  878. package/src/browser/segment-structure-assert.ts +16 -0
  879. package/src/browser/server-action-bridge.ts +488 -606
  880. package/src/browser/shallow.ts +6 -1
  881. package/src/browser/types.ts +116 -47
  882. package/src/browser/validate-redirect-origin.ts +29 -0
  883. package/src/build/generate-manifest.ts +63 -21
  884. package/src/build/generate-route-types.ts +36 -1038
  885. package/src/build/index.ts +2 -5
  886. package/src/build/route-trie.ts +38 -12
  887. package/src/build/route-types/ast-helpers.ts +25 -0
  888. package/src/build/route-types/ast-route-extraction.ts +98 -0
  889. package/src/build/route-types/codegen.ts +102 -0
  890. package/src/build/route-types/include-resolution.ts +411 -0
  891. package/src/build/route-types/param-extraction.ts +48 -0
  892. package/src/build/route-types/per-module-writer.ts +128 -0
  893. package/src/build/route-types/router-processing.ts +479 -0
  894. package/src/build/route-types/scan-filter.ts +78 -0
  895. package/src/build/runtime-discovery.ts +231 -0
  896. package/src/cache/background-task.ts +34 -0
  897. package/src/cache/cache-key-utils.ts +44 -0
  898. package/src/cache/cache-policy.ts +125 -0
  899. package/src/cache/cache-runtime.ts +338 -0
  900. package/src/cache/cache-scope.ts +122 -303
  901. package/src/cache/cf/cf-cache-store.ts +571 -17
  902. package/src/cache/cf/index.ts +13 -3
  903. package/src/cache/document-cache.ts +116 -77
  904. package/src/cache/handle-capture.ts +81 -0
  905. package/src/cache/handle-snapshot.ts +41 -0
  906. package/src/cache/index.ts +1 -15
  907. package/src/cache/memory-segment-store.ts +191 -13
  908. package/src/cache/profile-registry.ts +73 -0
  909. package/src/cache/read-through-swr.ts +134 -0
  910. package/src/cache/segment-codec.ts +256 -0
  911. package/src/cache/taint.ts +98 -0
  912. package/src/cache/types.ts +72 -122
  913. package/src/client.rsc.tsx +3 -1
  914. package/src/client.tsx +84 -126
  915. package/src/component-utils.ts +4 -4
  916. package/src/components/DefaultDocument.tsx +5 -1
  917. package/src/context-var.ts +86 -0
  918. package/src/debug.ts +19 -9
  919. package/src/errors.ts +77 -7
  920. package/src/handle.ts +12 -7
  921. package/src/handles/MetaTags.tsx +73 -20
  922. package/src/handles/breadcrumbs.ts +66 -0
  923. package/src/handles/index.ts +1 -0
  924. package/src/handles/meta.ts +30 -13
  925. package/src/host/cookie-handler.ts +21 -15
  926. package/src/host/errors.ts +8 -8
  927. package/src/host/index.ts +4 -7
  928. package/src/host/pattern-matcher.ts +27 -27
  929. package/src/host/router.ts +61 -39
  930. package/src/host/testing.ts +8 -8
  931. package/src/host/types.ts +15 -7
  932. package/src/host/utils.ts +1 -1
  933. package/src/href-client.ts +65 -45
  934. package/src/index.rsc.ts +104 -40
  935. package/src/index.ts +122 -67
  936. package/src/internal-debug.ts +9 -3
  937. package/src/loader.rsc.ts +18 -93
  938. package/src/loader.ts +26 -9
  939. package/src/network-error-thrower.tsx +3 -1
  940. package/src/outlet-provider.tsx +45 -0
  941. package/src/prerender/param-hash.ts +4 -2
  942. package/src/prerender/store.ts +121 -17
  943. package/src/prerender.ts +325 -20
  944. package/src/reverse.ts +144 -124
  945. package/src/root-error-boundary.tsx +41 -29
  946. package/src/route-content-wrapper.tsx +7 -4
  947. package/src/route-definition/dsl-helpers.ts +959 -0
  948. package/src/route-definition/helper-factories.ts +200 -0
  949. package/src/route-definition/helpers-types.ts +430 -0
  950. package/src/route-definition/index.ts +52 -0
  951. package/src/route-definition/redirect.ts +93 -0
  952. package/src/route-definition.ts +1 -1450
  953. package/src/route-map-builder.ts +87 -133
  954. package/src/route-name.ts +53 -0
  955. package/src/route-types.ts +41 -6
  956. package/src/router/content-negotiation.ts +116 -0
  957. package/src/router/debug-manifest.ts +72 -0
  958. package/src/router/error-handling.ts +9 -9
  959. package/src/router/find-match.ts +160 -0
  960. package/src/router/handler-context.ts +324 -116
  961. package/src/router/intercept-resolution.ts +11 -4
  962. package/src/router/lazy-includes.ts +237 -0
  963. package/src/router/loader-resolution.ts +179 -133
  964. package/src/router/logging.ts +112 -6
  965. package/src/router/manifest.ts +58 -19
  966. package/src/router/match-api.ts +89 -88
  967. package/src/router/match-context.ts +4 -2
  968. package/src/router/match-handlers.ts +440 -0
  969. package/src/router/match-middleware/background-revalidation.ts +84 -89
  970. package/src/router/match-middleware/cache-lookup.ts +261 -48
  971. package/src/router/match-middleware/cache-store.ts +54 -13
  972. package/src/router/match-middleware/intercept-resolution.ts +45 -22
  973. package/src/router/match-middleware/segment-resolution.ts +20 -9
  974. package/src/router/match-pipelines.ts +10 -45
  975. package/src/router/match-result.ts +34 -17
  976. package/src/router/metrics.ts +235 -15
  977. package/src/router/middleware-cookies.ts +55 -0
  978. package/src/router/middleware-types.ts +222 -0
  979. package/src/router/middleware.ts +327 -369
  980. package/src/router/pattern-matching.ts +169 -31
  981. package/src/router/prerender-match.ts +402 -0
  982. package/src/router/preview-match.ts +170 -0
  983. package/src/router/revalidation.ts +105 -14
  984. package/src/router/router-context.ts +40 -21
  985. package/src/router/router-interfaces.ts +452 -0
  986. package/src/router/router-options.ts +592 -0
  987. package/src/router/router-registry.ts +24 -0
  988. package/src/router/segment-resolution/fresh.ts +656 -0
  989. package/src/router/segment-resolution/helpers.ts +263 -0
  990. package/src/router/segment-resolution/loader-cache.ts +199 -0
  991. package/src/router/segment-resolution/revalidation.ts +1277 -0
  992. package/src/router/segment-resolution/static-store.ts +67 -0
  993. package/src/router/segment-resolution.ts +21 -1354
  994. package/src/router/segment-wrappers.ts +291 -0
  995. package/src/router/telemetry-otel.ts +299 -0
  996. package/src/router/telemetry.ts +300 -0
  997. package/src/router/timeout.ts +148 -0
  998. package/src/router/trie-matching.ts +96 -29
  999. package/src/router/types.ts +15 -9
  1000. package/src/router.ts +642 -2366
  1001. package/src/rsc/handler-context.ts +45 -0
  1002. package/src/rsc/handler.ts +646 -1027
  1003. package/src/rsc/helpers.ts +140 -6
  1004. package/src/rsc/index.ts +0 -20
  1005. package/src/rsc/loader-fetch.ts +209 -0
  1006. package/src/rsc/manifest-init.ts +86 -0
  1007. package/src/rsc/nonce.ts +14 -0
  1008. package/src/rsc/origin-guard.ts +141 -0
  1009. package/src/rsc/progressive-enhancement.ts +379 -0
  1010. package/src/rsc/response-error.ts +37 -0
  1011. package/src/rsc/response-route-handler.ts +347 -0
  1012. package/src/rsc/rsc-rendering.ts +237 -0
  1013. package/src/rsc/runtime-warnings.ts +42 -0
  1014. package/src/rsc/server-action.ts +348 -0
  1015. package/src/rsc/ssr-setup.ts +128 -0
  1016. package/src/rsc/types.ts +38 -11
  1017. package/src/search-params.ts +66 -54
  1018. package/src/segment-system.tsx +165 -17
  1019. package/src/server/context.ts +237 -54
  1020. package/src/server/cookie-store.ts +190 -0
  1021. package/src/server/fetchable-loader-store.ts +11 -6
  1022. package/src/server/handle-store.ts +94 -15
  1023. package/src/server/loader-registry.ts +15 -56
  1024. package/src/server/request-context.ts +438 -71
  1025. package/src/server.ts +26 -164
  1026. package/src/ssr/index.tsx +101 -31
  1027. package/src/static-handler.ts +22 -4
  1028. package/src/theme/ThemeProvider.tsx +21 -15
  1029. package/src/theme/ThemeScript.tsx +5 -5
  1030. package/src/theme/constants.ts +5 -2
  1031. package/src/theme/index.ts +4 -14
  1032. package/src/theme/theme-context.ts +4 -30
  1033. package/src/theme/theme-script.ts +21 -18
  1034. package/src/types/boundaries.ts +158 -0
  1035. package/src/types/cache-types.ts +198 -0
  1036. package/src/types/error-types.ts +192 -0
  1037. package/src/types/global-namespace.ts +100 -0
  1038. package/src/types/handler-context.ts +687 -0
  1039. package/src/types/index.ts +88 -0
  1040. package/src/types/loader-types.ts +183 -0
  1041. package/src/types/route-config.ts +170 -0
  1042. package/src/types/route-entry.ts +109 -0
  1043. package/src/types/segments.ts +150 -0
  1044. package/src/types.ts +1 -1795
  1045. package/src/urls/include-helper.ts +197 -0
  1046. package/src/urls/index.ts +53 -0
  1047. package/src/urls/path-helper-types.ts +339 -0
  1048. package/src/urls/path-helper.ts +329 -0
  1049. package/src/urls/pattern-types.ts +95 -0
  1050. package/src/urls/response-types.ts +106 -0
  1051. package/src/urls/type-extraction.ts +372 -0
  1052. package/src/urls/urls-function.ts +98 -0
  1053. package/src/urls.ts +1 -1323
  1054. package/src/use-loader.tsx +85 -77
  1055. package/src/vite/discovery/bundle-postprocess.ts +184 -0
  1056. package/src/vite/discovery/discover-routers.ts +344 -0
  1057. package/src/vite/discovery/prerender-collection.ts +385 -0
  1058. package/src/vite/discovery/route-types-writer.ts +258 -0
  1059. package/src/vite/discovery/self-gen-tracking.ts +47 -0
  1060. package/src/vite/discovery/state.ts +108 -0
  1061. package/src/vite/discovery/virtual-module-codegen.ts +203 -0
  1062. package/src/vite/index.ts +11 -2259
  1063. package/src/vite/plugin-types.ts +48 -0
  1064. package/src/vite/plugins/cjs-to-esm.ts +93 -0
  1065. package/src/vite/plugins/client-ref-dedup.ts +115 -0
  1066. package/src/vite/plugins/client-ref-hashing.ts +105 -0
  1067. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +72 -47
  1068. package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +8 -43
  1069. package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
  1070. package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
  1071. package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
  1072. package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
  1073. package/src/vite/plugins/expose-ids/types.ts +45 -0
  1074. package/src/vite/plugins/expose-internal-ids.ts +569 -0
  1075. package/src/vite/plugins/refresh-cmd.ts +65 -0
  1076. package/src/vite/plugins/use-cache-transform.ts +323 -0
  1077. package/src/vite/plugins/version-injector.ts +83 -0
  1078. package/src/vite/plugins/version-plugin.ts +266 -0
  1079. package/src/vite/plugins/virtual-entries.ts +123 -0
  1080. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  1081. package/src/vite/rango.ts +445 -0
  1082. package/src/vite/router-discovery.ts +777 -0
  1083. package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +181 -9
  1084. package/src/vite/utils/banner.ts +36 -0
  1085. package/src/vite/utils/bundle-analysis.ts +137 -0
  1086. package/src/vite/utils/manifest-utils.ts +70 -0
  1087. package/src/vite/{package-resolution.ts → utils/package-resolution.ts} +25 -29
  1088. package/src/vite/utils/prerender-utils.ts +189 -0
  1089. package/src/vite/utils/shared-utils.ts +169 -0
  1090. package/CLAUDE.md +0 -43
  1091. package/src/browser/lru-cache.ts +0 -69
  1092. package/src/browser/request-controller.ts +0 -164
  1093. package/src/cache/memory-store.ts +0 -253
  1094. package/src/router.gen.ts +0 -6
  1095. package/src/static-handler.gen.ts +0 -5
  1096. package/src/urls.gen.ts +0 -8
  1097. package/src/vite/expose-internal-ids.ts +0 -1167
  1098. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
package/src/vite/index.ts CHANGED
@@ -1,2264 +1,16 @@
1
- import type { Plugin, PluginOption } from "vite";
2
- import { createServer as createViteServer } from "vite";
3
- import * as Vite from "vite";
4
- import { resolve, join, dirname, basename, relative } from "node:path";
5
- import { createHash } from "node:crypto";
6
- import { createRequire } from "node:module";
7
- import { mkdirSync, writeFileSync, readFileSync, existsSync, unlinkSync } from "node:fs";
8
- import {
9
- generateRouteTypesSource,
10
- writePerModuleRouteTypes,
11
- writePerModuleRouteTypesForFile,
12
- writeCombinedRouteTypes,
13
- findRouterFiles,
14
- createScanFilter,
15
- buildCombinedRouteMapForRouterFile,
16
- type ScanFilter,
17
- } from "../build/generate-route-types.ts";
18
- import { exposeActionId } from "./expose-action-id.ts";
19
- import { exposeInternalIds, exposeRouterId } from "./expose-internal-ids.ts";
20
- import {
21
- VIRTUAL_ENTRY_BROWSER,
22
- VIRTUAL_ENTRY_SSR,
23
- getVirtualEntryRSC,
24
- getVirtualVersionContent,
25
- VIRTUAL_IDS,
26
- } from "./virtual-entries.ts";
27
- import {
28
- getExcludeDeps,
29
- getPackageAliases,
30
- getPublishedPackageName,
31
- } from "./package-resolution.ts";
32
-
33
- // Re-export plugins
34
- export { exposeActionId } from "./expose-action-id.ts";
35
- export { exposeInternalIds, exposeRouterId } from "./expose-internal-ids.ts";
36
- export type { ExposeInternalIdsApi } from "./expose-internal-ids.ts";
37
-
38
- // Virtual module type declarations in ./version.d.ts
39
-
40
- /**
41
- * esbuild plugin to provide rsc-router:version virtual module during optimization.
42
- * This is needed because esbuild runs during Vite's dependency optimization phase,
43
- * before Vite's plugin system can handle virtual modules.
44
- */
45
- const versionEsbuildPlugin = {
46
- name: "@rangojs/router-version",
47
- setup(build: any) {
48
- build.onResolve({ filter: /^rsc-router:version$/ }, (args: any) => ({
49
- path: args.path,
50
- namespace: "@rangojs/router-virtual",
51
- }));
52
- build.onLoad({ filter: /.*/, namespace: "@rangojs/router-virtual" }, () => ({
53
- contents: `export const VERSION = "dev";`,
54
- loader: "js",
55
- }));
56
- },
57
- };
58
-
59
- /**
60
- * Shared esbuild options for dependency optimization.
61
- * Includes the version stub plugin for all environments.
62
- */
63
- const sharedEsbuildOptions = {
64
- plugins: [versionEsbuildPlugin],
65
- };
66
-
67
- /**
68
- * RSC plugin entry points configuration.
69
- * All entries use virtual modules by default. Specify a path to use a custom entry file.
70
- */
71
- export interface RscEntries {
72
- /**
73
- * Path to a custom browser/client entry file.
74
- * If not specified, a default virtual entry is used.
75
- */
76
- client?: string;
77
-
78
- /**
79
- * Path to a custom SSR entry file.
80
- * If not specified, a default virtual entry is used.
81
- */
82
- ssr?: string;
83
-
84
- /**
85
- * Path to a custom RSC entry file.
86
- * If not specified, a default virtual entry is used that imports the router from the `entry` option.
87
- */
88
- rsc?: string;
89
- }
90
-
91
- /**
92
- * Options for @vitejs/plugin-rsc integration
93
- */
94
- export interface RscPluginOptions {
95
- /**
96
- * Entry points for client, ssr, and rsc environments.
97
- * All entries use virtual modules by default.
98
- * Specify paths only when you need custom entry files.
99
- */
100
- entries?: RscEntries;
101
- }
102
-
103
- /**
104
- * Base options shared by all presets
105
- */
106
- interface RangoBaseOptions {
107
- /**
108
- * Show startup banner. Set to false to disable.
109
- * @default true
110
- */
111
- banner?: boolean;
112
-
113
- /**
114
- * Generate static route type files (.gen.ts) by parsing url modules at startup.
115
- * Creates per-module route maps and per-router named-routes.gen.ts for type-safe
116
- * Handler<"name", routes> and href() without executing router code.
117
- * Set to `false` to disable (run `npx rango extract-names` manually instead).
118
- * @default true
119
- */
120
- staticRouteTypesGeneration?: boolean;
121
-
122
- /**
123
- * Glob patterns for files to include in route type scanning.
124
- * Only files matching at least one pattern will be scanned.
125
- * Patterns are relative to the project root.
126
- * When unset, all .ts/.tsx files are scanned.
127
- */
128
- include?: string[];
129
-
130
- /**
131
- * Glob patterns for files to exclude from route type scanning.
132
- * Takes precedence over `include`. Patterns are relative to the project root.
133
- * Defaults to common test/build directories.
134
- */
135
- exclude?: string[];
136
- }
137
-
138
- /**
139
- * Options for Node.js deployment (default)
140
- */
141
- export interface RangoNodeOptions extends RangoBaseOptions {
142
- /**
143
- * Deployment preset. Defaults to 'node' when not specified.
144
- */
145
- preset?: "node";
146
-
147
- /**
148
- * Path to your router configuration file that exports the route tree.
149
- * This file must export a `router` object created with `createRouter()`.
150
- *
151
- * When omitted, auto-discovers the router by scanning for files containing
152
- * `createRouter`. If exactly one is found, it is used automatically.
153
- * If multiple are found, an error is thrown with the list of candidates.
154
- *
155
- * @example
156
- * ```ts
157
- * rango({ router: './src/router.tsx' })
158
- * // or simply:
159
- * rango()
160
- * ```
161
- */
162
- router?: string;
163
-
164
- /**
165
- * RSC plugin configuration. By default, rsc-router includes @vitejs/plugin-rsc
166
- * with sensible defaults.
167
- *
168
- * Entry files (browser, ssr, rsc) are optional - if they don't exist,
169
- * virtual defaults are used.
170
- *
171
- * - Omit or pass `true`/`{}` to use defaults (recommended)
172
- * - Pass `{ entries: {...} }` to customize entry paths
173
- * - Pass `false` to disable (for manual @vitejs/plugin-rsc configuration)
174
- *
175
- * @default true
176
- */
177
- rsc?: boolean | RscPluginOptions;
178
- }
179
-
180
- /**
181
- * Options for Cloudflare Workers deployment
182
- */
183
- export interface RangoCloudflareOptions extends RangoBaseOptions {
184
- /**
185
- * Deployment preset for Cloudflare Workers.
186
- * When using cloudflare preset:
187
- * - @vitejs/plugin-rsc is NOT added (cloudflare plugin adds it)
188
- * - Your worker entry (e.g., worker.rsc.tsx) imports the router directly
189
- * - Browser and SSR use virtual entries
190
- * - Build-time manifest generation is auto-detected from wrangler.json main entry
191
- */
192
- preset: "cloudflare";
193
- }
194
-
195
- /**
196
- * Options for rango() Vite plugin
197
- */
198
- export type RangoOptions = RangoNodeOptions | RangoCloudflareOptions;
199
-
200
- /**
201
- * Create a virtual modules plugin for default entry files.
202
- * Provides virtual module content when entries use VIRTUAL_IDS (no custom entry configured).
203
- */
204
- function createVirtualEntriesPlugin(
205
- entries: { client: string; ssr: string; rsc?: string },
206
- routerPath?: string
207
- ): Plugin {
208
-
209
- // Build virtual modules map based on which entries use virtual IDs
210
- const virtualModules: Record<string, string> = {};
211
-
212
- if (entries.client === VIRTUAL_IDS.browser) {
213
- virtualModules[VIRTUAL_IDS.browser] = VIRTUAL_ENTRY_BROWSER;
214
- }
215
- if (entries.ssr === VIRTUAL_IDS.ssr) {
216
- virtualModules[VIRTUAL_IDS.ssr] = VIRTUAL_ENTRY_SSR;
217
- }
218
- if (entries.rsc === VIRTUAL_IDS.rsc && routerPath) {
219
- // Convert relative path to absolute for virtual module imports
220
- const absoluteRouterPath = routerPath.startsWith(".")
221
- ? "/" + routerPath.slice(2) // ./src/router.tsx -> /src/router.tsx
222
- : routerPath;
223
- virtualModules[VIRTUAL_IDS.rsc] = getVirtualEntryRSC(absoluteRouterPath);
224
- }
225
-
226
- return {
227
- name: "@rangojs/router:virtual-entries",
228
- enforce: "pre",
229
-
230
- resolveId(id) {
231
- if (id in virtualModules) {
232
- return "\0" + id;
233
- }
234
- // Handle if the id already has the null prefix (RSC plugin wrapper imports)
235
- if (id.startsWith("\0") && id.slice(1) in virtualModules) {
236
- return id;
237
- }
238
- return null;
239
- },
240
-
241
- load(id) {
242
- if (id.startsWith("\0virtual:rsc-router/")) {
243
- const virtualId = id.slice(1);
244
- if (virtualId in virtualModules) {
245
- return virtualModules[virtualId];
246
- }
247
- }
248
- return null;
249
- },
250
- };
251
- }
252
-
253
- /**
254
- * Rollup onwarn handler that suppresses known harmless warnings:
255
- * - "use client" directives: handled by the RSC plugin, not relevant to Rollup
256
- * - sourcemap errors: caused by "use client" directive at line 1:0 confusing sourcemap resolution
257
- * - sourcemap incomplete: plugins that transform without generating sourcemaps (router + RSC plugin)
258
- * - dynamic/static mixed imports: expected for router internals (e.g. request-context, cache-scope)
259
- */
260
- function onwarn(warning: Vite.Rollup.RollupLog, defaultHandler: (warning: Vite.Rollup.RollupLog) => void): void {
261
- if (warning.code === "MODULE_LEVEL_DIRECTIVE" || warning.code === "SOURCEMAP_ERROR") {
262
- return;
263
- }
264
- // @vitejs/plugin-rsc@0.5.14: rsc:virtual:vite-rsc/assets-manifest renderChunk
265
- // returns { code } without map, causing Rollup to warn about incorrect sourcemaps.
266
- // This is harmless (simple string replacement). Remove this suppression if a
267
- // future version of @vitejs/plugin-rsc fixes the missing sourcemap.
268
- if (warning.message?.includes("Sourcemap is likely to be incorrect")) {
269
- return;
270
- }
271
- if (
272
- warning.plugin === "vite:reporter" &&
273
- warning.message?.includes("dynamic import will not move module into another chunk")
274
- ) {
275
- return;
276
- }
277
- defaultHandler(warning);
278
- }
279
-
280
- /**
281
- * Manual chunks configuration for client build.
282
- * Splits React and router packages into separate chunks for better caching.
283
- */
284
- function getManualChunks(id: string): string | undefined {
285
- const normalized = Vite.normalizePath(id);
286
-
287
- if (
288
- normalized.includes("node_modules/react/") ||
289
- normalized.includes("node_modules/react-dom/") ||
290
- normalized.includes("node_modules/react-server-dom-webpack/") ||
291
- normalized.includes("node_modules/@vitejs/plugin-rsc/")
292
- ) {
293
- return "react";
294
- }
295
- // Use dynamic package name from package.json
296
- // Check both npm install path and workspace symlink resolved path
297
- const packageName = getPublishedPackageName();
298
- if (
299
- normalized.includes(`node_modules/${packageName}/`) ||
300
- normalized.includes("packages/rsc-router/") ||
301
- normalized.includes("packages/rangojs-router/")
302
- ) {
303
- return "router";
304
- }
305
- return undefined;
306
- }
307
-
308
1
  /**
309
- * Plugin providing rsc-router:version virtual module.
310
- * Exports VERSION that changes when RSC modules change (dev) or at build time (production).
2
+ * Public API for @rangojs/router/vite
311
3
  *
312
- * The version is used for:
313
- * 1. Cache invalidation - CFCacheStore uses VERSION to invalidate stale cache
314
- * 2. Version mismatch detection - client sends version, server reloads on mismatch
315
- *
316
- * In dev mode, the version updates when:
317
- * - Server starts (initial version)
318
- * - RSC modules change via HMR (triggers version module invalidation)
319
- *
320
- * Client-only HMR changes don't update the version since they don't affect
321
- * server-rendered content or cached RSC payloads.
322
- * @internal
4
+ * Exports: rango() plugin factory, poke() dev utility plugin,
5
+ * and related option types. All other utilities are internal implementation
6
+ * details consumed via direct imports within the package.
323
7
  */
324
- function createVersionPlugin(): Plugin {
325
- // Generate version at plugin creation time (build/server start)
326
- const buildVersion = Date.now().toString(16);
327
- let currentVersion = buildVersion;
328
- let isDev = false;
329
- let server: any = null;
330
-
331
- return {
332
- name: "@rangojs/router:version",
333
- enforce: "pre",
334
-
335
- configResolved(config) {
336
- isDev = config.command === "serve";
337
- },
338
-
339
- configureServer(devServer) {
340
- server = devServer;
341
- },
342
-
343
- resolveId(id) {
344
- if (id === VIRTUAL_IDS.version) {
345
- return "\0" + id;
346
- }
347
- return null;
348
- },
349
-
350
- load(id) {
351
- if (id === "\0" + VIRTUAL_IDS.version) {
352
- return getVirtualVersionContent(currentVersion);
353
- }
354
- return null;
355
- },
356
-
357
- // Track RSC module changes and update version
358
- hotUpdate(ctx) {
359
- if (!isDev) return;
360
-
361
- // Check if this is an RSC environment update (not client/ssr)
362
- // RSC modules affect server-rendered content and cached payloads
363
- // In Vite 6, environment is accessed via `this.environment`
364
- const isRscModule = this.environment?.name === "rsc";
365
-
366
- if (isRscModule && ctx.modules.length > 0) {
367
- // Update version when RSC modules change
368
- currentVersion = Date.now().toString(16);
369
- console.log(
370
- `[rsc-router] RSC module changed, version updated: ${currentVersion}`
371
- );
372
-
373
- // Invalidate the version module so it gets reloaded with new version
374
- if (server) {
375
- const rscEnv = server.environments?.rsc;
376
- if (rscEnv?.moduleGraph) {
377
- const versionMod = rscEnv.moduleGraph.getModuleById(
378
- "\0" + VIRTUAL_IDS.version
379
- );
380
- if (versionMod) {
381
- rscEnv.moduleGraph.invalidateModule(versionMod);
382
- }
383
- }
384
- }
385
- }
386
- },
387
- };
388
- }
389
-
390
- /**
391
- * Flatten prefix tree leaf nodes into precomputed route entries.
392
- * Leaf nodes have no children (no nested includes), so their routes can be
393
- * used directly by evaluateLazyEntry() without running the handler.
394
- * Non-leaf nodes are skipped because they have nested lazy includes that
395
- * require the handler to run for discovery.
396
- */
397
- function flattenLeafEntries(
398
- prefixTree: Record<string, any>,
399
- routeManifest: Record<string, string>,
400
- result: Array<{ staticPrefix: string; routes: Record<string, string> }>,
401
- ): void {
402
- function visit(node: any): void {
403
- const children = node.children || {};
404
- if (Object.keys(children).length === 0 && node.routes && node.routes.length > 0) {
405
- // Leaf node: collect its routes from the manifest
406
- const routes: Record<string, string> = {};
407
- for (const name of node.routes) {
408
- if (name in routeManifest) {
409
- routes[name] = routeManifest[name];
410
- }
411
- }
412
- result.push({ staticPrefix: node.staticPrefix, routes });
413
- } else {
414
- // Non-leaf: recurse into children
415
- for (const child of Object.values(children)) {
416
- visit(child);
417
- }
418
- }
419
- }
420
- for (const node of Object.values(prefixTree)) {
421
- visit(node);
422
- }
423
- }
424
-
425
- /**
426
- * Walk prefix tree to map each route name to its scope's staticPrefix.
427
- */
428
- function buildRouteToStaticPrefix(
429
- prefixTree: Record<string, any>,
430
- result: Record<string, string>,
431
- ): void {
432
- function visit(node: any): void {
433
- const sp = node.staticPrefix || "";
434
- for (const name of (node.routes || [])) {
435
- result[name] = sp;
436
- }
437
- for (const child of Object.values(node.children || {})) {
438
- visit(child);
439
- }
440
- }
441
- for (const node of Object.values(prefixTree)) {
442
- visit(node);
443
- }
444
- }
445
-
446
- /**
447
- * Encode route param values for path interpolation while preserving path
448
- * separators for wildcard params (splat-style values can include `/`).
449
- */
450
- function encodePathParam(value: unknown): string {
451
- return String(value)
452
- .split("/")
453
- .map((segment) => encodeURIComponent(segment))
454
- .join("/");
455
- }
456
-
457
- /**
458
- * Plugin that discovers router instances at dev/build time via the RSC environment.
459
- *
460
- * Uses `server.environments.rsc.runner.import()` to load the user's router file
461
- * with full TS/TSX compilation. This triggers `createRouter()` which populates
462
- * the `RouterRegistry`. The plugin then generates manifests for each router.
463
- *
464
- * In dev mode, this runs in `configureServer` (post-middleware setup).
465
- * In build mode, this will run in `buildStart` (future).
466
- *
467
- * @internal
468
- */
469
- function createRouterDiscoveryPlugin(
470
- entryPath: string,
471
- opts?: { enableBuildPrerender?: boolean; staticRouteTypesGeneration?: boolean; include?: string[]; exclude?: string[] },
472
- ): Plugin {
473
- let projectRoot = "";
474
- let isBuildMode = false;
475
- let userResolveAlias: any = undefined;
476
-
477
- // Scan filter compiled from include/exclude patterns (created in configResolved)
478
- let scanFilter: ScanFilter | undefined;
479
-
480
- // Cached router file paths (files containing createRouter) from initial scan.
481
- // Reused by the file watcher to avoid re-scanning the entire directory tree.
482
- let cachedRouterFiles: string[] | undefined;
483
-
484
- // Merged route manifest from all discovered routers.
485
- // Populated during discovery (dev: configureServer, build: buildStart).
486
- // Read by the virtual module's load hook to emit setCachedManifest() call.
487
- let mergedRouteManifest: Record<string, string> | null = null;
488
-
489
- // Per-router route manifests for generating typed route files.
490
- let perRouterManifests: Array<{
491
- id: string;
492
- routeManifest: Record<string, string>;
493
- routeSearchSchemas?: Record<string, Record<string, string>>;
494
- sourceFile?: string;
495
- }> = [];
496
-
497
-
498
- // Collected prerender data from in-process collection during discoverRouters().
499
- // Consumed by closeBundle to inject into the RSC entry bundle.
500
- let prerenderCollectedData: Record<string, any> | null = null;
501
-
502
- // Handler chunk metadata recorded during generateBundle for post-build eviction.
503
- let handlerChunkInfo: {
504
- fileName: string;
505
- exports: Array<{ name: string; handlerId: string; passthrough: boolean }>;
506
- } | null = null;
507
-
508
- // RSC entry chunk filename recorded during generateBundle for closeBundle injection.
509
- let rscEntryFileName: string | null = null;
510
-
511
- // Resolved prerender handler modules from the expose-internal-ids plugin.
512
- let resolvedPrerenderModules: Map<string, string[]> | undefined;
513
-
514
- // Resolved static handler modules from the expose-internal-ids plugin.
515
- let resolvedStaticModules: Map<string, string[]> | undefined;
516
-
517
- // Promise that resolves when dev-mode discovery completes.
518
- // The virtual module's load hook awaits this to ensure data is available.
519
- let discoveryDone: Promise<void> | null = null;
520
-
521
- // Pre-computed route entries from prefix tree leaf nodes.
522
- // Leaf nodes have no nested includes, so their routes can be used directly
523
- // by evaluateLazyEntry() without running the handler.
524
- let mergedPrecomputedEntries: Array<{
525
- staticPrefix: string;
526
- routes: Record<string, string>;
527
- }> | null = null;
528
-
529
- // Route trie for O(path_length) matching at runtime.
530
- let mergedRouteTrie: any = null;
531
-
532
- // Per-router isolated data for multi-router manifest splitting.
533
- // Each router gets its own manifest, trie, and precomputed entries so that
534
- // virtual:rsc-router/routes-manifest/<routerId> modules can be emitted.
535
- let perRouterTrieMap: Map<string, any> = new Map();
536
- let perRouterPrecomputedMap: Map<string, Array<{ staticPrefix: string; routes: Record<string, string> }>> = new Map();
537
- let perRouterManifestDataMap: Map<string, Record<string, string>> = new Map();
538
-
539
- // Dev-mode state for on-demand prerender endpoint.
540
- let devServerOrigin: string | null = null;
541
- let devServer: any = null;
542
-
543
- // Shared discovery logic: import entry via RSC runner, generate manifests,
544
- // write static files, and populate mergedRouteManifest.
545
- async function discoverRouters(rscEnv: any) {
546
- // Import the entry file via RSC environment.
547
- // For node preset: this is the router file (createRouter() registers in RouterRegistry).
548
- // For cloudflare preset: this is the worker entry (which imports the router).
549
- await rscEnv.runner.import(entryPath);
550
-
551
- // Import the router package to access the registry
552
- const serverMod = await rscEnv.runner.import("@rangojs/router/server");
553
- let registry: Map<string, any> = serverMod.RouterRegistry;
554
-
555
- if (!registry || registry.size === 0) {
556
- // No RSC routers found directly. Check for host routers with lazy handlers
557
- // that need to be resolved to trigger sub-app createRouter() calls.
558
- try {
559
- const hostMod = await rscEnv.runner.import("@rangojs/router/host");
560
- const hostRegistry: Map<string, any> | undefined = hostMod.HostRouterRegistry;
561
-
562
- if (hostRegistry && hostRegistry.size > 0) {
563
- console.log(
564
- `[rsc-router] Found ${hostRegistry.size} host router(s), resolving lazy handlers...`
565
- );
566
-
567
- for (const [, entry] of hostRegistry) {
568
- for (const route of entry.routes) {
569
- if (typeof route.handler === 'function') {
570
- try {
571
- await route.handler();
572
- } catch {
573
- // Lazy handler may fail in temp server context, that's OK
574
- }
575
- }
576
- }
577
- if (entry.fallback && typeof entry.fallback.handler === 'function') {
578
- try {
579
- await entry.fallback.handler();
580
- } catch {
581
- // Fallback handler may fail in temp server context
582
- }
583
- }
584
- }
585
-
586
- // Re-read RouterRegistry - sub-app createRouter() calls should have populated it
587
- const freshServerMod = await rscEnv.runner.import("@rangojs/router/server");
588
- const freshRegistry: Map<string, any> = freshServerMod.RouterRegistry;
589
-
590
- if (freshRegistry && freshRegistry.size > 0) {
591
- // Update references so the manifest generation below uses the fresh data
592
- Object.assign(serverMod, freshServerMod);
593
- registry = freshRegistry;
594
- }
595
- }
596
- } catch {
597
- // @rangojs/router/host not available or import failed, skip
598
- }
599
-
600
- // If still no routers after host router resolution, fail
601
- if (!registry || registry.size === 0) {
602
- throw new Error(
603
- `[rsc-router] No routers found in registry after importing ${entryPath}`
604
- );
605
- }
606
- }
607
-
608
- // Import build utilities for manifest generation
609
- const buildMod = await rscEnv.runner.import("@rangojs/router/build");
610
- const generateManifest = buildMod.generateManifest;
611
-
612
- mergedRouteManifest = {};
613
- mergedPrecomputedEntries = [];
614
- perRouterManifests = [];
615
- perRouterManifestDataMap = new Map();
616
- perRouterPrecomputedMap = new Map();
617
- perRouterTrieMap = new Map();
618
- let mergedRouteAncestry: Record<string, string[]> = {};
619
- let mergedRouteTrailingSlash: Record<string, string> = {};
620
-
621
- let routerMountIndex = 0;
622
- // Collect all manifests for trie building (avoid re-running generateManifest)
623
- const allManifests: Array<{ id: string; manifest: any }> = [];
624
-
625
- for (const [id, router] of registry) {
626
- if (!router.urlpatterns || !generateManifest) {
627
- continue;
628
- }
629
-
630
- const manifest = generateManifest(router.urlpatterns, routerMountIndex);
631
- routerMountIndex++;
632
- allManifests.push({ id, manifest });
633
- const routeCount = Object.keys(manifest.routeManifest).length;
634
- const staticRoutes = Object.values(manifest.routeManifest).filter(
635
- (p: any) => !p.includes(":") && !p.includes("*")
636
- ).length;
637
- const dynamicRoutes = routeCount - staticRoutes;
638
-
639
- // Merge into the combined manifest
640
- Object.assign(mergedRouteManifest, manifest.routeManifest);
641
- perRouterManifests.push({
642
- id,
643
- routeManifest: manifest.routeManifest,
644
- routeSearchSchemas: manifest.routeSearchSchemas,
645
- sourceFile: router.__sourceFile,
646
- });
647
-
648
- // Merge ancestry (internal field, used only for trie building)
649
- if (manifest._routeAncestry) {
650
- Object.assign(mergedRouteAncestry, manifest._routeAncestry);
651
- }
652
- // Merge trailing slash config
653
- if (manifest.routeTrailingSlash) {
654
- Object.assign(mergedRouteTrailingSlash, manifest.routeTrailingSlash);
655
- }
656
-
657
- // Flatten prefix tree leaf nodes into precomputed entries.
658
- // Leaf nodes (no children) can have their routes used directly by
659
- // evaluateLazyEntry() without running the handler at runtime.
660
- flattenLeafEntries(manifest.prefixTree, manifest.routeManifest, mergedPrecomputedEntries);
661
-
662
- // Store per-router manifest and precomputed entries for isolated virtual modules.
663
- perRouterManifestDataMap.set(id, manifest.routeManifest);
664
- const routerPrecomputed: Array<{ staticPrefix: string; routes: Record<string, string> }> = [];
665
- flattenLeafEntries(manifest.prefixTree, manifest.routeManifest, routerPrecomputed);
666
- perRouterPrecomputedMap.set(id, routerPrecomputed);
667
-
668
- console.log(
669
- `[rsc-router] Router "${id}" -> ${routeCount} routes ` +
670
- `(${staticRoutes} static, ${dynamicRoutes} dynamic)`
671
- );
672
- }
673
-
674
- // Warn if multiple routers use auto-generated IDs (router_0, router_1, ...).
675
- // Auto-IDs are assigned by counter and depend on module evaluation order,
676
- // which can differ between build time and runtime (especially with dynamic
677
- // imports in host routers). This causes per-router data to be loaded into
678
- // the wrong router at runtime.
679
- if (registry.size > 1) {
680
- const autoIds = [...registry.keys()].filter((id) => /^router_\d+$/.test(id));
681
- if (autoIds.length > 1) {
682
- console.warn(
683
- `[rsc-router] WARNING: ${autoIds.length} routers use auto-generated IDs (${autoIds.join(", ")}). ` +
684
- `In multi-router setups, each createRouter() must have an explicit \`id\` option ` +
685
- `to ensure per-router manifest data is matched correctly at runtime. ` +
686
- `Example: createRouter({ id: "site", ... })`
687
- );
688
- }
689
- }
690
-
691
- // Build route trie from merged manifest + ancestry
692
- if (mergedRouteManifest && Object.keys(mergedRouteManifest).length > 0) {
693
- const buildRouteTrie = buildMod.buildRouteTrie;
694
- if (buildRouteTrie && mergedRouteAncestry) {
695
- // Build routeToStaticPrefix from saved manifests
696
- const routeToStaticPrefix: Record<string, string> = {};
697
- for (const { manifest } of allManifests) {
698
- // Root-level routes have empty static prefix
699
- for (const name of Object.keys(manifest.routeManifest)) {
700
- if (!(name in routeToStaticPrefix)) {
701
- routeToStaticPrefix[name] = "";
702
- }
703
- }
704
- buildRouteToStaticPrefix(manifest.prefixTree, routeToStaticPrefix);
705
- }
706
-
707
- // Collect prerender route names and response type routes from all manifests
708
- const prerenderRouteNames = new Set<string>();
709
- const passthroughRouteNames = new Set<string>();
710
- const mergedResponseTypeRoutes: Record<string, string> = {};
711
- for (const { manifest } of allManifests) {
712
- if (manifest.prerenderRoutes) {
713
- for (const name of manifest.prerenderRoutes) {
714
- prerenderRouteNames.add(name);
715
- }
716
- }
717
- if (manifest.passthroughRoutes) {
718
- for (const name of manifest.passthroughRoutes) {
719
- passthroughRouteNames.add(name);
720
- }
721
- }
722
- if (manifest.responseTypeRoutes) {
723
- Object.assign(mergedResponseTypeRoutes, manifest.responseTypeRoutes);
724
- }
725
- }
726
-
727
- mergedRouteTrie = buildRouteTrie(
728
- mergedRouteManifest,
729
- mergedRouteAncestry,
730
- routeToStaticPrefix,
731
- Object.keys(mergedRouteTrailingSlash).length > 0 ? mergedRouteTrailingSlash : undefined,
732
- prerenderRouteNames.size > 0 ? prerenderRouteNames : undefined,
733
- passthroughRouteNames.size > 0 ? passthroughRouteNames : undefined,
734
- Object.keys(mergedResponseTypeRoutes).length > 0 ? mergedResponseTypeRoutes : undefined,
735
- );
736
-
737
- // Build per-router tries for multi-router isolation.
738
- for (const { id, manifest } of allManifests) {
739
- if (!manifest._routeAncestry || Object.keys(manifest._routeAncestry).length === 0) continue;
740
- const perRouterStaticPrefix: Record<string, string> = {};
741
- for (const name of Object.keys(manifest.routeManifest)) {
742
- perRouterStaticPrefix[name] = "";
743
- }
744
- buildRouteToStaticPrefix(manifest.prefixTree, perRouterStaticPrefix);
745
-
746
- const perRouterPrerenderNames = manifest.prerenderRoutes
747
- ? new Set<string>(manifest.prerenderRoutes)
748
- : undefined;
749
- const perRouterPassthroughNames = manifest.passthroughRoutes
750
- ? new Set<string>(manifest.passthroughRoutes)
751
- : undefined;
752
-
753
- const perRouterTrie = buildRouteTrie(
754
- manifest.routeManifest,
755
- manifest._routeAncestry,
756
- perRouterStaticPrefix,
757
- manifest.routeTrailingSlash && Object.keys(manifest.routeTrailingSlash).length > 0
758
- ? manifest.routeTrailingSlash : undefined,
759
- perRouterPrerenderNames && perRouterPrerenderNames.size > 0 ? perRouterPrerenderNames : undefined,
760
- perRouterPassthroughNames && perRouterPassthroughNames.size > 0 ? perRouterPassthroughNames : undefined,
761
- manifest.responseTypeRoutes && Object.keys(manifest.responseTypeRoutes).length > 0
762
- ? manifest.responseTypeRoutes : undefined,
763
- );
764
- perRouterTrieMap.set(id, perRouterTrie);
765
- }
766
- }
767
- }
768
-
769
- // Expand prerender routes into concrete URLs for build-time rendering.
770
- // Static routes use pattern as-is; dynamic routes call getParams() to enumerate.
771
- if (opts?.enableBuildPrerender && isBuildMode) {
772
- const urls: string[] = [];
773
- for (const { manifest } of allManifests) {
774
- if (!manifest.prerenderRoutes) continue;
775
- const defs = manifest._prerenderDefs || {};
776
- for (const routeName of manifest.prerenderRoutes) {
777
- const pattern = manifest.routeManifest[routeName];
778
- if (!pattern) continue;
779
- const hasDynamic = pattern.includes(":") || pattern.includes("*");
780
- if (!hasDynamic) {
781
- // Static route: use pattern directly (strip trailing slash for URL)
782
- urls.push(pattern.replace(/\/$/, "") || "/");
783
- } else {
784
- // Dynamic route: call getParams() to enumerate param combinations
785
- const def = defs[routeName];
786
- if (def?.getParams) {
787
- try {
788
- const paramsList = await def.getParams();
789
- for (const params of paramsList) {
790
- let url = pattern;
791
- for (const [key, value] of Object.entries(params as Record<string, string>)) {
792
- const encoded = encodePathParam(value);
793
- url = url.replace(`:${key}`, encoded);
794
- url = url.replace(`*${key}`, encoded);
795
- }
796
- // Anonymous wildcard fallback: use conventional keys if provided
797
- if (url.includes("*")) {
798
- const wildcardValue =
799
- (params as Record<string, string>)["*"]
800
- ?? (params as Record<string, string>).splat;
801
- if (wildcardValue !== undefined) {
802
- url = url.replace(/\*[^/]*$/, encodePathParam(wildcardValue));
803
- }
804
- }
805
- urls.push(url.replace(/\/$/, "") || "/");
806
- }
807
- } catch (err: any) {
808
- console.warn(
809
- `[rsc-router] Failed to get params for prerender route "${routeName}": ${err.message}`
810
- );
811
- }
812
- } else {
813
- console.warn(
814
- `[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
815
- );
816
- }
817
- }
818
- }
819
- }
820
- if (urls.length > 0) {
821
- console.log(
822
- `[rsc-router] Pre-render URLs: ${urls.join(", ")}`
823
- );
824
-
825
- const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
826
-
827
- const collectedData: Record<string, any> = {};
828
- let rendered = 0;
829
-
830
- for (const urlPath of urls) {
831
- // Try all routers since the URL->router mapping isn't direct
832
- for (const [, routerInstance] of registry) {
833
- if (!routerInstance.matchForPrerender) continue;
834
- try {
835
- const result = await routerInstance.matchForPrerender(urlPath, {});
836
- if (!result) continue;
837
- const paramHash = hashParams(result.params || {});
838
- collectedData[`${result.routeName}/${paramHash}`] = {
839
- segments: result.segments,
840
- handles: result.handles,
841
- };
842
- rendered++;
843
- break;
844
- } catch (err: any) {
845
- console.warn(`[rsc-router] Pre-render failed for ${urlPath}: ${err.message}`);
846
- }
847
- }
848
- }
849
-
850
- if (rendered > 0) {
851
- prerenderCollectedData = collectedData;
852
- console.log(`[rsc-router] Pre-rendered ${rendered}/${urls.length} route(s)`);
853
- }
854
- }
855
- }
856
-
857
- return serverMod;
858
- }
859
-
860
- // Write per-router named-routes type files next to each router's source file.
861
- // Each router gets its own {basename}.named-routes.gen.ts with only its routes.
862
- // Only writes when content has changed to avoid triggering HMR loops.
863
- function writeRouteTypesFiles() {
864
- if (perRouterManifests.length === 0) return;
865
-
866
- // Delete old combined named-routes.gen.ts if it exists
867
- try {
868
- const entryDir = dirname(resolve(projectRoot, entryPath));
869
- const oldCombinedPath = join(entryDir, "named-routes.gen.ts");
870
- if (existsSync(oldCombinedPath)) {
871
- unlinkSync(oldCombinedPath);
872
- console.log(`[rsc-router] Removed stale combined route types: ${oldCombinedPath}`);
873
- }
874
- } catch {}
875
-
876
- for (const { id, routeManifest, routeSearchSchemas, sourceFile } of perRouterManifests) {
877
- if (!sourceFile) continue;
878
-
879
- // Validate sourceFile points to a real project file, not node_modules or
880
- // a Vite internal path. A bad sourceFile leads to route types written to
881
- // the wrong location, causing non-deterministic type resolution.
882
- if (sourceFile.includes("node_modules")) {
883
- throw new Error(
884
- `[rsc-router] Router "${id}" has sourceFile inside node_modules: ${sourceFile}\n` +
885
- `This means createRouter() stack trace parsing matched a Vite internal frame.\n` +
886
- `Set an explicit \`id\` on createRouter() or check the call site.`,
887
- );
888
- }
889
-
890
- const routerDir = dirname(sourceFile);
891
- const routerBasename = basename(sourceFile).replace(/\.(tsx?|jsx?)$/, "");
892
- const outPath = join(routerDir, `${routerBasename}.named-routes.gen.ts`);
893
- let effectiveSearchSchemas = routeSearchSchemas;
894
-
895
- // Runtime manifest may omit search schema metadata in some module-runner
896
- // flows. Fall back to static source parsing from the router file.
897
- if (
898
- (!effectiveSearchSchemas || Object.keys(effectiveSearchSchemas).length === 0) &&
899
- sourceFile
900
- ) {
901
- const staticParsed = buildCombinedRouteMapForRouterFile(sourceFile);
902
- if (Object.keys(staticParsed.searchSchemas).length > 0) {
903
- const filtered: Record<string, Record<string, string>> = {};
904
- for (const name of Object.keys(routeManifest)) {
905
- const schema = staticParsed.searchSchemas[name];
906
- if (schema) filtered[name] = schema;
907
- }
908
- if (Object.keys(filtered).length > 0) {
909
- effectiveSearchSchemas = filtered;
910
- }
911
- }
912
- }
913
-
914
- const source = generateRouteTypesSource(
915
- routeManifest,
916
- effectiveSearchSchemas && Object.keys(effectiveSearchSchemas).length > 0
917
- ? effectiveSearchSchemas
918
- : undefined,
919
- );
920
- const existing = existsSync(outPath) ? readFileSync(outPath, "utf-8") : null;
921
- if (existing !== source) {
922
- writeFileSync(outPath, source);
923
- console.log(`[rsc-router] Generated route types -> ${outPath}`);
924
- }
925
- }
926
- }
927
-
928
- return {
929
- name: "@rangojs/router:discovery",
930
-
931
- config() {
932
- if (!opts?.enableBuildPrerender) return {};
933
- return {
934
- environments: {
935
- rsc: {
936
- build: {
937
- rollupOptions: {
938
- output: {
939
- manualChunks(id: string) {
940
- if (resolvedPrerenderModules?.has(id)) {
941
- return "__prerender-handlers";
942
- }
943
- if (resolvedStaticModules?.has(id)) {
944
- return "__static-handlers";
945
- }
946
- },
947
- },
948
- },
949
- },
950
- },
951
- },
952
- };
953
- },
954
-
955
- configResolved(config) {
956
- projectRoot = config.root;
957
- isBuildMode = config.command === "build";
958
- // Capture user's resolve aliases for the temp server
959
- userResolveAlias = config.resolve.alias;
960
- // Compile include/exclude patterns into a scan filter
961
- if (opts?.include || opts?.exclude) {
962
- scanFilter = createScanFilter(projectRoot, {
963
- include: opts.include,
964
- exclude: opts.exclude,
965
- });
966
- }
967
- // Generate per-module route types from static source parsing.
968
- // Runs before the dev server starts so .gen.ts files exist immediately for IDE.
969
- // In build mode, the runtime discovery in buildStart produces the definitive
970
- // named-routes.gen.ts (including dynamically generated routes). However, we
971
- // still need to write initial gen files here so discovery can import router
972
- // modules that reference them. preserveIfLarger prevents overwriting a
973
- // previously generated complete file with a partial one.
974
- if (opts?.staticRouteTypesGeneration !== false) {
975
- writePerModuleRouteTypes(projectRoot, scanFilter);
976
- cachedRouterFiles = findRouterFiles(projectRoot, scanFilter);
977
- writeCombinedRouteTypes(projectRoot, cachedRouterFiles, { preserveIfLarger: true });
978
- }
979
- // Resolve prerenderHandlerModules and staticHandlerModules from the consolidated IDs plugin's API.
980
- if (opts?.enableBuildPrerender) {
981
- const idsPlugin = config.plugins.find(
982
- (p: any) => p.name === "@rangojs/router:expose-internal-ids",
983
- );
984
- resolvedPrerenderModules =
985
- (idsPlugin?.api as any)?.prerenderHandlerModules;
986
- resolvedStaticModules =
987
- (idsPlugin?.api as any)?.staticHandlerModules;
988
- }
989
- },
990
-
991
- // Dev mode: discover routers and populate manifest in memory.
992
- // Skipped in build mode (buildStart handles it).
993
- configureServer(server) {
994
- if (isBuildMode) return;
995
- // Skip if this is a temp server created by buildStart
996
- if ((globalThis as any).__rscRouterDiscoveryActive) return;
997
- devServer = server;
998
-
999
- // Discovery promise that the handler can await if requests arrive
1000
- // before discovery completes
1001
- let resolveDiscovery: () => void;
1002
- const discoveryPromise = new Promise<void>((resolve) => {
1003
- resolveDiscovery = resolve;
1004
- });
1005
-
1006
- // Compute dev server origin from resolved URLs (preferred) or config port (fallback).
1007
- // Called after discovery (or in the load hook) when the server may be listening.
1008
- const getDevServerOrigin = () =>
1009
- server.resolvedUrls?.local?.[0]?.replace(/\/$/, '')
1010
- || `http://localhost:${server.config.server.port || 5173}`;
1011
-
1012
- const discover = async () => {
1013
- const rscEnv = (server.environments as any)?.rsc;
1014
- if (!rscEnv?.runner) {
1015
- // Cloudflare dev: no module runner available (workerd-based RSC env).
1016
- // Set devServerOrigin so the virtual module can inject __PRERENDER_DEV_URL
1017
- // for on-demand prerender via the /__rsc_prerender endpoint.
1018
- devServerOrigin = getDevServerOrigin();
1019
- resolveDiscovery!();
1020
- return;
1021
- }
1022
-
1023
- try {
1024
- // Set the readiness gate BEFORE discovery so early requests
1025
- // block until manifest is populated
1026
- const serverMod = await rscEnv.runner.import("@rangojs/router/server");
1027
- if (serverMod?.setManifestReadyPromise) {
1028
- serverMod.setManifestReadyPromise(discoveryPromise);
1029
- }
1030
-
1031
- const serverModAfterDiscovery = await discoverRouters(rscEnv);
1032
-
1033
- // Save registry for the /__rsc_prerender endpoint (avoids creating a temp server)
1034
- mainRegistry = serverModAfterDiscovery?.RouterRegistry ?? null;
1035
-
1036
- // Store server origin for dev prerender endpoint (virtual module injection)
1037
- devServerOrigin = getDevServerOrigin();
1038
-
1039
- // Update named-routes.gen.ts from runtime discovery.
1040
- // The runtime manifest is the source of truth: it evaluates dynamic
1041
- // routes (e.g. Array.from loops) that the static parser cannot see.
1042
- // writeRouteTypesFiles() only writes when content changes, so this
1043
- // won't cause unnecessary HMR triggers.
1044
- writeRouteTypesFiles();
1045
-
1046
- // Populate the route map in the RSC env
1047
- if (mergedRouteManifest && serverMod?.setCachedManifest) {
1048
- serverMod.setCachedManifest(mergedRouteManifest);
1049
- }
1050
- if (mergedPrecomputedEntries && mergedPrecomputedEntries.length > 0 && serverMod?.setPrecomputedEntries) {
1051
- serverMod.setPrecomputedEntries(mergedPrecomputedEntries);
1052
- }
1053
- if (mergedRouteTrie && serverMod?.setRouteTrie) {
1054
- serverMod.setRouteTrie(mergedRouteTrie);
1055
- }
1056
- // Populate per-router isolated data eagerly in dev (HMR).
1057
- // In production builds, per-router data is loaded lazily via import().
1058
- if (serverMod?.setRouterManifest) {
1059
- for (const [routerId, manifest] of perRouterManifestDataMap) {
1060
- serverMod.setRouterManifest(routerId, manifest);
1061
- }
1062
- }
1063
- if (serverMod?.setRouterTrie) {
1064
- for (const [routerId, trie] of perRouterTrieMap) {
1065
- serverMod.setRouterTrie(routerId, trie);
1066
- }
1067
- }
1068
- if (serverMod?.setRouterPrecomputedEntries) {
1069
- for (const [routerId, entries] of perRouterPrecomputedMap) {
1070
- serverMod.setRouterPrecomputedEntries(routerId, entries);
1071
- }
1072
- }
1073
- } catch (err: any) {
1074
- console.warn(
1075
- `[rsc-router] Router discovery failed: ${err.message}\n${err.stack}`
1076
- );
1077
- } finally {
1078
- resolveDiscovery!();
1079
- }
1080
- };
1081
-
1082
- // Schedule after all plugins have finished configureServer.
1083
- // Store the promise so the virtual module's load hook can await it.
1084
- discoveryDone = new Promise<void>((resolve) => {
1085
- setTimeout(() => discover().then(resolve, resolve), 0);
1086
- });
1087
-
1088
- // Dev-mode on-demand prerender endpoint.
1089
- // When workerd hits a prerender route, it fetches this endpoint instead of
1090
- // trying to run node:fs-dependent handlers in the Cloudflare environment.
1091
- //
1092
- // Node.js preset: uses the main server's RSC environment directly (router
1093
- // instances are already discovered and have matchForPrerender).
1094
- // Cloudflare preset: lazily creates a Node.js temp server because the main
1095
- // RSC environment uses workerd where node:fs can't access the host filesystem.
1096
- let prerenderTempServer: any = null;
1097
- let prerenderNodeRegistry: Map<string, any> | null = null;
1098
- // Registry from the main server's RSC environment (populated by discoverRouters)
1099
- let mainRegistry: Map<string, any> | null = null;
1100
-
1101
- server.middlewares.use("/__rsc_prerender", async (req: any, res: any) => {
1102
- if (discoveryDone) await discoveryDone;
1103
-
1104
- const url = new URL(req.url || "/", "http://localhost");
1105
- const pathname = url.searchParams.get("pathname");
1106
- if (!pathname) {
1107
- res.statusCode = 400;
1108
- res.end("Missing pathname");
1109
- return;
1110
- }
1111
-
1112
- // Prefer the main server's registry (Node.js preset: module runner available).
1113
- // Fall back to a temp server for Cloudflare where the main RSC env uses workerd.
1114
- let registry = mainRegistry;
1115
-
1116
- if (!registry) {
1117
- // No main registry: the RSC env has no module runner (Cloudflare dev).
1118
- // Lazily create a Node.js temp server for prerender evaluation.
1119
- if (!prerenderNodeRegistry) {
1120
- try {
1121
- const { default: rsc } = await import("@vitejs/plugin-rsc");
1122
- prerenderTempServer = await createViteServer({
1123
- root: projectRoot,
1124
- configFile: false,
1125
- server: { middlewareMode: true },
1126
- appType: "custom",
1127
- logLevel: "silent",
1128
- cacheDir: "node_modules/.vite_prerender",
1129
- resolve: { alias: userResolveAlias },
1130
- esbuild: { jsx: "automatic", jsxImportSource: "react" },
1131
- plugins: [
1132
- rsc({ entries: { client: "virtual:entry-client", ssr: "virtual:entry-ssr", rsc: entryPath } }),
1133
- createVersionPlugin(),
1134
- createVirtualStubPlugin(),
1135
- exposeInternalIds({ forceBuild: true }),
1136
- exposeRouterId(),
1137
- ],
1138
- });
1139
-
1140
- const tempRscEnv = (prerenderTempServer.environments as any)?.rsc;
1141
- if (tempRscEnv?.runner) {
1142
- await tempRscEnv.runner.import(entryPath);
1143
- const serverMod = await tempRscEnv.runner.import("@rangojs/router/server");
1144
- prerenderNodeRegistry = serverMod.RouterRegistry;
1145
- }
1146
- } catch (err: any) {
1147
- console.warn(`[rsc-router] Failed to create prerender runner: ${err.message}`);
1148
- }
1149
- }
1150
- registry = prerenderNodeRegistry;
1151
- }
1152
-
1153
- if (!registry || registry.size === 0) {
1154
- res.statusCode = 503;
1155
- res.end("Prerender runner not available");
1156
- return;
1157
- }
1158
-
1159
- for (const [, routerInstance] of registry) {
1160
- if (!routerInstance.matchForPrerender) continue;
1161
- try {
1162
- const result = await routerInstance.matchForPrerender(pathname, {});
1163
- if (!result) continue;
1164
- res.setHeader("content-type", "application/json");
1165
- res.end(JSON.stringify({ segments: result.segments, handles: result.handles }));
1166
- return;
1167
- } catch (err: any) {
1168
- console.warn(`[rsc-router] Dev prerender failed for ${pathname}: ${err.message}`);
1169
- }
1170
- }
1171
-
1172
- res.statusCode = 404;
1173
- res.end("No prerender match");
1174
- });
1175
-
1176
- // Watch url module and router files for changes and regenerate route types.
1177
- // Process files containing urls( (per-module types) or createRouter( (per-router types).
1178
- if (opts?.staticRouteTypesGeneration !== false) {
1179
- server.watcher.on("change", (filePath) => {
1180
- if (filePath.endsWith(".gen.ts")) return;
1181
- if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) return;
1182
- // Apply scan filter as early-exit before reading file
1183
- if (scanFilter && !scanFilter(filePath)) return;
1184
- try {
1185
- const source = readFileSync(filePath, "utf-8");
1186
- const trimmed = source.trimStart();
1187
- if (trimmed.startsWith('"use client"') || trimmed.startsWith("'use client'")) return;
1188
- const hasUrls = source.includes("urls(");
1189
- const hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
1190
- if (!hasUrls && !hasCreateRouter) return;
1191
- if (hasUrls) {
1192
- writePerModuleRouteTypesForFile(filePath);
1193
- }
1194
- // Invalidate cache when a router file changes (new router added/removed)
1195
- if (hasCreateRouter) {
1196
- cachedRouterFiles = undefined;
1197
- }
1198
- writeCombinedRouteTypes(projectRoot, cachedRouterFiles);
1199
- } catch {
1200
- // Ignore read errors for deleted/moved files
1201
- }
1202
- });
1203
- }
1204
- },
1205
-
1206
- // Build mode: create a temporary Vite dev server to access the RSC
1207
- // environment's module runner, then discover routers and generate manifests.
1208
- // The manifest data is stored for the virtual module's load hook.
1209
- async buildStart() {
1210
- if (!isBuildMode) return;
1211
- // Only run once across environment builds
1212
- if (mergedRouteManifest !== null) return;
1213
-
1214
- let tempServer: any = null;
1215
- try {
1216
- // Prevent the temp server's plugin instances from running discovery
1217
- (globalThis as any).__rscRouterDiscoveryActive = true;
1218
-
1219
- // Create a minimal Vite server with just the RSC plugin.
1220
- // We bypass the user's config file because:
1221
- // - Custom environments (e.g., CloudflareDevEnvironment) may not expose
1222
- // a module runner compatible with runner.import()
1223
- // - The temp server only needs RSC conditions to import the router
1224
- const { default: rsc } = await import("@vitejs/plugin-rsc");
1225
- tempServer = await createViteServer({
1226
- root: projectRoot,
1227
- configFile: false,
1228
- server: { middlewareMode: true },
1229
- appType: "custom",
1230
- logLevel: "silent",
1231
- // Use the resolved aliases from the real config (includes user's path aliases
1232
- // like @/ -> src/ AND package aliases from rsc-router)
1233
- resolve: { alias: userResolveAlias },
1234
- // Enable automatic JSX runtime so .tsx files don't need `import React`.
1235
- // Without this, esbuild defaults to classic mode (React.createElement)
1236
- // which fails when lazy host-router handlers load sub-app modules with JSX.
1237
- esbuild: { jsx: "automatic", jsxImportSource: "react" },
1238
- plugins: [
1239
- rsc({ entries: { client: "virtual:entry-client", ssr: "virtual:entry-ssr", rsc: entryPath } }),
1240
- createVersionPlugin(),
1241
- // Stub virtual modules that the RSC entry may import
1242
- // (e.g., virtual:rsc-router/routes-manifest, virtual:rsc-router/loader-manifest)
1243
- createVirtualStubPlugin(),
1244
- // Inject handle + router IDs so prerender-collected handle data uses
1245
- // the same hashed keys as the production client/SSR bundles, and
1246
- // build-time router IDs match runtime IDs across environments.
1247
- exposeInternalIds({ forceBuild: true }),
1248
- exposeRouterId(),
1249
- ],
1250
- });
1251
-
1252
- const rscEnv = (tempServer.environments as any)?.rsc;
1253
- if (!rscEnv?.runner) {
1254
- console.warn(
1255
- "[rsc-router] RSC environment runner not available during build, skipping manifest generation"
1256
- );
1257
- return;
1258
- }
1259
-
1260
- await discoverRouters(rscEnv);
1261
- // Update named-routes.gen.ts from runtime discovery.
1262
- // The runtime manifest includes dynamically generated routes
1263
- // that the static parser cannot extract from source code.
1264
- writeRouteTypesFiles();
1265
- } catch (err: any) {
1266
- // Clean up before re-throwing so the temp server doesn't leak
1267
- delete (globalThis as any).__rscRouterDiscoveryActive;
1268
- if (tempServer) {
1269
- await tempServer.close();
1270
- }
1271
- // Extract the user source file from the stack trace (skip internal frames)
1272
- const sourceFile = err.stack
1273
- ?.split("\n")
1274
- .find((line: string) => line.includes(projectRoot) && !line.includes("node_modules"))
1275
- ?.match(/\(([^)]+)\)/)?.[1];
1276
- // Extract the route name from "Unknown route: <name>" errors
1277
- const routeName = err.message?.match(/Unknown route: (.+)/)?.[1];
1278
- const details = [
1279
- routeName ? ` Route name: ${routeName}` : null,
1280
- sourceFile ? ` File: ${sourceFile}` : null,
1281
- err.stack ? ` Stack:\n${err.stack}` : null,
1282
- ].filter(Boolean).join("\n");
1283
- throw new Error(
1284
- `[rsc-router] Build-time router discovery failed:\n${details}`
1285
- );
1286
- } finally {
1287
- delete (globalThis as any).__rscRouterDiscoveryActive;
1288
- if (tempServer) {
1289
- await tempServer.close();
1290
- }
1291
- }
1292
- },
1293
-
1294
- // Virtual module: provides the pre-generated route manifest as a JS module
1295
- // that calls setCachedManifest() at import time.
1296
- resolveId(id) {
1297
- if (id === VIRTUAL_ROUTES_MANIFEST_ID) {
1298
- return "\0" + VIRTUAL_ROUTES_MANIFEST_ID;
1299
- }
1300
- // Per-router virtual modules: virtual:rsc-router/routes-manifest/<routerId>
1301
- if (id.startsWith(VIRTUAL_ROUTES_MANIFEST_ID + "/")) {
1302
- return "\0" + id;
1303
- }
1304
- // virtual:rsc-router/prerender-paths removed: prerender data is served through the worker
1305
- return null;
1306
- },
1307
-
1308
- async load(id) {
1309
- if (id === "\0" + VIRTUAL_ROUTES_MANIFEST_ID) {
1310
- // In dev mode, wait for discovery to complete before emitting module content.
1311
- // This is critical for Cloudflare dev where the worker runs in a separate
1312
- // Miniflare process and can only receive manifest data via the virtual module.
1313
- if (discoveryDone) {
1314
- await discoveryDone;
1315
- }
1316
- const hasManifest = mergedRouteManifest && Object.keys(mergedRouteManifest).length > 0;
1317
- if (hasManifest) {
1318
- const lines = [
1319
- `import { setCachedManifest, setPrecomputedEntries, setRouteTrie, registerRouterManifestLoader } from "@rangojs/router/server";`,
1320
- `setCachedManifest(${jsonParseExpression(mergedRouteManifest)});`,
1321
- ];
1322
- if (mergedPrecomputedEntries && mergedPrecomputedEntries.length > 0) {
1323
- lines.push(`setPrecomputedEntries(${jsonParseExpression(mergedPrecomputedEntries)});`);
1324
- }
1325
- if (mergedRouteTrie) {
1326
- lines.push(`setRouteTrie(${jsonParseExpression(mergedRouteTrie)});`);
1327
- }
1328
- // Register lazy loaders for per-router manifest modules.
1329
- // Each import() uses a static string literal so Rollup creates separate chunks.
1330
- for (const routerId of perRouterManifestDataMap.keys()) {
1331
- lines.push(
1332
- `registerRouterManifestLoader(${JSON.stringify(routerId)}, () => import(${JSON.stringify(VIRTUAL_ROUTES_MANIFEST_ID + "/" + routerId)}));`,
1333
- );
1334
- }
1335
- if (!isBuildMode && devServerOrigin) {
1336
- lines.push(`globalThis.__PRERENDER_DEV_URL = ${JSON.stringify(devServerOrigin)};`);
1337
- }
1338
- return lines.join("\n");
1339
- }
1340
- // No manifest: either discovery hasn't completed or no runner (Cloudflare dev).
1341
- // Still inject __PRERENDER_DEV_URL so the prerender store can fetch on-demand.
1342
- // Re-resolve origin now since the server is listening by module load time.
1343
- if (!isBuildMode) {
1344
- const origin = devServerOrigin
1345
- || devServer?.resolvedUrls?.local?.[0]?.replace(/\/$/, '')
1346
- || (devServer && `http://localhost:${devServer.config.server.port || 5173}`);
1347
- if (origin) {
1348
- devServerOrigin = origin;
1349
- return `globalThis.__PRERENDER_DEV_URL = ${JSON.stringify(origin)};`;
1350
- }
1351
- }
1352
- return `// Route manifest will be populated at runtime`;
1353
- }
1354
- // Per-router virtual modules: pure data exports (no side effects).
1355
- // ensureRouterManifest() imports the module and stores the data.
1356
- const perRouterPrefix = "\0" + VIRTUAL_ROUTES_MANIFEST_ID + "/";
1357
- if (id.startsWith(perRouterPrefix)) {
1358
- if (discoveryDone) {
1359
- await discoveryDone;
1360
- }
1361
- const routerId = id.slice(perRouterPrefix.length);
1362
- const manifest = perRouterManifestDataMap.get(routerId);
1363
- const trie = perRouterTrieMap.get(routerId);
1364
- const entries = perRouterPrecomputedMap.get(routerId);
1365
- const lines: string[] = [];
1366
- if (manifest) {
1367
- lines.push(`export const manifest = ${jsonParseExpression(manifest)};`);
1368
- }
1369
- if (trie) {
1370
- lines.push(`export const trie = ${jsonParseExpression(trie)};`);
1371
- }
1372
- if (entries && entries.length > 0) {
1373
- lines.push(`export const precomputedEntries = ${jsonParseExpression(entries)};`);
1374
- }
1375
- return lines.join("\n") || "// empty router manifest";
1376
- }
1377
- // virtual:rsc-router/prerender-paths load handler removed
1378
- return null;
1379
- },
1380
-
1381
- // Record handler chunk metadata and RSC entry filename during RSC build.
1382
- // Used by closeBundle for handler code eviction and prerender data injection.
1383
- generateBundle(_options: any, bundle: any) {
1384
- if (this.environment?.name !== "rsc") return;
1385
-
1386
- // Record RSC entry chunk filename for closeBundle injection
1387
- for (const [fileName, chunk] of Object.entries(bundle) as [string, any][]) {
1388
- if (chunk.type === "chunk" && chunk.isEntry) {
1389
- rscEntryFileName = fileName;
1390
- break;
1391
- }
1392
- }
1393
-
1394
- if (!resolvedPrerenderModules?.size) return;
1395
-
1396
- for (const [fileName, chunk] of Object.entries(bundle) as [string, any][]) {
1397
- if (chunk.type !== "chunk") continue;
1398
- if (!fileName.includes("__prerender-handlers")) continue;
1399
-
1400
- const handlers: Array<{ name: string; handlerId: string; passthrough: boolean }> = [];
1401
- for (const [, handlerNames] of resolvedPrerenderModules) {
1402
- for (const name of handlerNames) {
1403
- const idPattern = new RegExp(
1404
- `\\b${name}\\.\\$\\$id\\s*=\\s*"([^"]+)"`,
1405
- );
1406
- const match = chunk.code.match(idPattern);
1407
- if (match) {
1408
- // Detect passthrough option in the Prerender call.
1409
- const callStartRe = new RegExp(
1410
- `const\\s+${name}\\s*=\\s*Prerender\\s*(?:<[^>]*>)?\\s*\\(`,
1411
- );
1412
- const callStart = callStartRe.exec(chunk.code);
1413
- let isPassthrough = false;
1414
- if (callStart) {
1415
- const openPos = callStart.index + callStart[0].length;
1416
- let depth = 1;
1417
- let p = openPos;
1418
- while (p < chunk.code.length && depth > 0) {
1419
- const ch = chunk.code[p];
1420
- if (ch === '"' || ch === "'" || ch === "`") {
1421
- p++;
1422
- while (p < chunk.code.length && chunk.code[p] !== ch) {
1423
- if (chunk.code[p] === "\\") p++;
1424
- p++;
1425
- }
1426
- } else if (ch === "(") {
1427
- depth++;
1428
- } else if (ch === ")") {
1429
- depth--;
1430
- }
1431
- p++;
1432
- }
1433
- if (depth === 0) {
1434
- const callBody = chunk.code.slice(callStart.index, p);
1435
- isPassthrough = /passthrough\s*:\s*(!0|true)/.test(callBody);
1436
- }
1437
- }
1438
- handlers.push({ name, handlerId: match[1], passthrough: isPassthrough });
1439
- }
1440
- }
1441
- }
1442
-
1443
- if (handlers.length > 0) {
1444
- handlerChunkInfo = { fileName, exports: handlers };
1445
- }
1446
- break;
1447
- }
1448
-
1449
- },
1450
-
1451
- // Build-time pre-rendering: evict handler code and inject collected prerender data.
1452
- // Collection now happens in-process during discoverRouters() via RSC runner.
1453
- // closeBundle only needs to evict handlers and inject the in-memory data.
1454
- closeBundle: {
1455
- order: "post" as const,
1456
- sequential: true,
1457
- async handler() {
1458
- if (!isBuildMode) return;
1459
- if (!prerenderCollectedData || Object.keys(prerenderCollectedData).length === 0) return;
1460
-
1461
- // Find RSC entry (recorded in generateBundle, fallback to dist/rsc/index.js)
1462
- const rscEntryPath = resolve(projectRoot, "dist/rsc", rscEntryFileName ?? "index.js");
1463
-
1464
- // 1. Evict handler code from __prerender-handlers chunk.
1465
- // handlerChunkInfo is populated by generateBundle after the production RSC
1466
- // build completes. In Vite 6 multi-environment builds, the RSC build runs
1467
- // twice (analysis pass + production pass). handlerChunkInfo is only available
1468
- // after the production pass, so we run eviction whenever it becomes available.
1469
- if (handlerChunkInfo) {
1470
- const chunkPath = resolve(projectRoot, "dist/rsc", handlerChunkInfo.fileName);
1471
- try {
1472
- let code = readFileSync(chunkPath, "utf-8");
1473
- const originalSize = Buffer.byteLength(code);
1474
-
1475
- for (const { name, handlerId, passthrough } of handlerChunkInfo.exports) {
1476
- // Passthrough handlers stay in the bundle for live fallback
1477
- if (passthrough) continue;
1478
- const callStartRe = new RegExp(
1479
- `const\\s+${name}\\s*=\\s*Prerender\\s*(?:<[^>]*>)?\\s*\\(`,
1480
- );
1481
- const startMatch = callStartRe.exec(code);
1482
- if (!startMatch) continue;
1483
-
1484
- // Use paren-depth counting to find the matching close paren
1485
- const openParenPos = startMatch.index + startMatch[0].length;
1486
- let depth = 1;
1487
- let pos = openParenPos;
1488
- while (pos < code.length && depth > 0) {
1489
- const ch = code[pos];
1490
- if (ch === '"' || ch === "'" || ch === "`") {
1491
- pos++;
1492
- while (pos < code.length && code[pos] !== ch) {
1493
- if (code[pos] === "\\") pos++;
1494
- pos++;
1495
- }
1496
- } else if (ch === "(") {
1497
- depth++;
1498
- } else if (ch === ")") {
1499
- depth--;
1500
- }
1501
- pos++;
1502
- }
1503
- if (depth !== 0) continue;
1504
-
1505
- // pos is now after the closing paren. Skip trailing semicolon.
1506
- let rangeEnd = pos;
1507
- while (rangeEnd < code.length && /\s/.test(code[rangeEnd])) rangeEnd++;
1508
- if (code[rangeEnd] === ";") rangeEnd++;
1509
-
1510
- // Validate: the matched range should contain the expected handlerId
1511
- const matched = code.slice(startMatch.index, rangeEnd);
1512
- if (!matched.includes(handlerId)) continue;
1513
-
1514
- const stub = `const ${name} = { __brand: "prerenderHandler", $$id: "${handlerId}" };`;
1515
- code = code.slice(0, startMatch.index) + stub + code.slice(rangeEnd);
1516
-
1517
- // Remove the $$id assignment line (now redundant)
1518
- code = code.replace(
1519
- new RegExp(`\\n${name}\\.\\$\\$id\\s*=\\s*"[^"]+";`),
1520
- "",
1521
- );
1522
- }
1523
-
1524
- writeFileSync(chunkPath, code);
1525
- const newSize = Buffer.byteLength(code);
1526
- const savedKB = ((originalSize - newSize) / 1024).toFixed(1);
1527
- console.log(
1528
- `[rsc-router] Evicted handler code from RSC bundle (${savedKB} KB saved): ${handlerChunkInfo.fileName}`,
1529
- );
1530
- } catch (replaceErr: any) {
1531
- console.warn(
1532
- `[rsc-router] Failed to evict handler code: ${replaceErr.message}`,
1533
- );
1534
- }
1535
- // Clear after eviction to avoid re-running
1536
- handlerChunkInfo = null;
1537
- }
1538
-
1539
- // 2. Remap dev-mode client reference IDs in prerender data to production IDs.
1540
- // Prerender data is collected via a dev temp server whose RSC serializer
1541
- // uses dev URLs (e.g., /src/foo.tsx, /@fs/abs/path.tsx). Production uses
1542
- // SHA-256 hashes of root-relative paths. Rewrite the Flight I[] instructions.
1543
- for (const entry of Object.values(prerenderCollectedData)) {
1544
- for (const seg of (entry as any).segments) {
1545
- if (typeof seg.encoded !== "string") continue;
1546
- seg.encoded = seg.encoded.replace(
1547
- /I\["(\/[^"]+)"/g,
1548
- (_match: string, devId: string) => {
1549
- let rootRelative: string;
1550
- if (devId.startsWith("/@fs/")) {
1551
- // Absolute FS path via Vite dev server
1552
- const absPath = devId.slice(4); // strip /@fs
1553
- rootRelative = relative(projectRoot, absPath);
1554
- } else {
1555
- // Project-relative path with leading /
1556
- rootRelative = devId.slice(1);
1557
- }
1558
- const hash = createHash("sha256").update(rootRelative).digest("hex").slice(0, 12);
1559
- return `I["${hash}"`;
1560
- },
1561
- );
1562
- }
1563
- }
1564
-
1565
- // 3. Write prerender data as separate importable asset modules
1566
- // and inject a manifest import into the RSC entry.
1567
- if (existsSync(rscEntryPath)) {
1568
- const rscCode = readFileSync(rscEntryPath, "utf-8");
1569
- if (!rscCode.includes("__PRERENDER_MANIFEST")) {
1570
- try {
1571
- const assetsDir = resolve(projectRoot, "dist/rsc/assets");
1572
- mkdirSync(assetsDir, { recursive: true });
1573
-
1574
- const manifestEntries: string[] = [];
1575
- let totalBytes = 0;
1576
-
1577
- for (const [key, entry] of Object.entries(prerenderCollectedData)) {
1578
- const entryJson = JSON.stringify(entry);
1579
- const contentHash = createHash("sha256").update(entryJson).digest("hex").slice(0, 8);
1580
- const assetFileName = `__pr-${contentHash}.js`;
1581
- const assetPath = resolve(assetsDir, assetFileName);
1582
- const assetCode = `export default ${entryJson};\n`;
1583
- writeFileSync(assetPath, assetCode);
1584
- totalBytes += Buffer.byteLength(assetCode);
1585
- manifestEntries.push(`${JSON.stringify(key)}:()=>import("./assets/${assetFileName}")`);
1586
- }
1587
-
1588
- const manifestCode = `const m={${manifestEntries.join(",")}};export default m;\n`;
1589
- const manifestPath = resolve(projectRoot, "dist/rsc/__prerender-manifest.js");
1590
- writeFileSync(manifestPath, manifestCode);
1591
- totalBytes += Buffer.byteLength(manifestCode);
1592
-
1593
- const injection = `import __pm from "./__prerender-manifest.js";\nglobalThis.__PRERENDER_MANIFEST = __pm;\n`;
1594
- writeFileSync(rscEntryPath, injection + rscCode);
1595
-
1596
- const totalKB = (totalBytes / 1024).toFixed(1);
1597
- console.log(
1598
- `[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(prerenderCollectedData).length} entries)`,
1599
- );
1600
- } catch (err: any) {
1601
- throw new Error(`[rsc-router] Failed to write prerender assets: ${err.message}`);
1602
- }
1603
- }
1604
- }
1605
- },
1606
- },
1607
- };
1608
- }
1609
-
1610
- const VIRTUAL_ROUTES_MANIFEST_ID = "virtual:rsc-router/routes-manifest";
1611
- // VIRTUAL_PRERENDER_PATHS_ID removed: prerender data is served through the worker
1612
-
1613
- /**
1614
- * Resolve the entry path for build-time router discovery.
1615
- * - Node preset: uses the `router` option (may be undefined if auto-discovery failed).
1616
- * - Cloudflare preset: reads the `main` field from wrangler.json.
1617
- */
1618
- function resolveDiscoveryEntryPath(options: RangoOptions, routerPath?: string): string | undefined {
1619
- if (options.preset === "cloudflare") {
1620
- // Auto-detect from wrangler.json
1621
- const wranglerPaths = ["wrangler.json", "wrangler.jsonc"];
1622
- for (const filename of wranglerPaths) {
1623
- if (existsSync(filename)) {
1624
- try {
1625
- const raw = readFileSync(filename, "utf-8");
1626
- // Strip JSON comments for .jsonc
1627
- const cleaned = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
1628
- const config = JSON.parse(cleaned);
1629
- if (config.main) {
1630
- return config.main;
1631
- }
1632
- } catch {
1633
- // Ignore parse errors
1634
- }
1635
- }
1636
- }
1637
- return undefined;
1638
- }
1639
- // Node preset: use resolved routerPath (may be auto-discovered or explicit)
1640
- return routerPath;
1641
- }
1642
-
1643
- /**
1644
- * Stub plugin for virtual modules in the temp discovery server.
1645
- * The RSC entry may import virtual modules (routes-manifest, loader-manifest)
1646
- * that aren't available in the temp server. The RSC plugin also requires
1647
- * client/ssr entries which don't need real content for discovery.
1648
- */
1649
- function createVirtualStubPlugin(): Plugin {
1650
- const STUB_PREFIXES = [
1651
- "virtual:rsc-router/",
1652
- "virtual:entry-",
1653
- "virtual:vite-rsc/",
1654
- ];
1655
- return {
1656
- name: "@rangojs/router:virtual-stubs",
1657
- resolveId(id) {
1658
- if (STUB_PREFIXES.some((p) => id.startsWith(p))) {
1659
- return "\0stub:" + id;
1660
- }
1661
- return null;
1662
- },
1663
- load(id) {
1664
- if (id.startsWith("\0stub:")) {
1665
- return "export default {}";
1666
- }
1667
- return null;
1668
- },
1669
- };
1670
- }
1671
-
1672
- /**
1673
- * Generate a deterministic 12-char hex hash from a router id.
1674
- * Used to create collision-free directory names for per-router static output.
1675
- */
1676
- function hashRouterId(id: string): string {
1677
- return createHash("sha256").update(id).digest("hex").slice(0, 12);
1678
- }
1679
-
1680
- /**
1681
- * Wrap a value as `JSON.parse('...')` instead of a JS object literal.
1682
- * V8's JSON parser is significantly faster than its full JS parser for large
1683
- * objects, so this improves startup time for big route manifests.
1684
- */
1685
- function jsonParseExpression(value: unknown): string {
1686
- const json = JSON.stringify(value);
1687
- const escaped = json.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
1688
- return `JSON.parse('${escaped}')`;
1689
- }
1690
-
1691
- /**
1692
- * Plugin that auto-injects VERSION and routes-manifest into custom entry.rsc files.
1693
- * If a custom entry.rsc file uses createRSCHandler but doesn't pass version,
1694
- * this transform adds the import and property automatically.
1695
- * Also ensures the routes-manifest virtual module is always imported.
1696
- * @internal
1697
- */
1698
- function createVersionInjectorPlugin(rscEntryPath: string): Plugin {
1699
- let projectRoot = "";
1700
- let resolvedEntryPath = "";
1701
-
1702
- return {
1703
- name: "@rangojs/router:version-injector",
1704
- enforce: "pre",
1705
-
1706
- configResolved(config) {
1707
- projectRoot = config.root;
1708
- resolvedEntryPath = resolve(projectRoot, rscEntryPath);
1709
- },
1710
-
1711
- transform(code, id) {
1712
- // Only transform the RSC entry file
1713
- const normalizedId = Vite.normalizePath(id);
1714
- const normalizedEntry = Vite.normalizePath(resolvedEntryPath);
1715
-
1716
- if (normalizedId !== normalizedEntry) {
1717
- return null;
1718
- }
1719
-
1720
- // Prepend imports at the top of the file. ES imports are hoisted
1721
- // by the module system, so source position is irrelevant.
1722
- const prepend: string[] = [];
1723
- let newCode = code;
1724
-
1725
- if (!code.includes("virtual:rsc-router/routes-manifest")) {
1726
- prepend.push(`import "virtual:rsc-router/routes-manifest";`);
1727
- }
1728
-
1729
- // Auto-inject VERSION if file uses createRSCHandler without version
1730
- const needsVersion =
1731
- code.includes("createRSCHandler") &&
1732
- !code.includes("@rangojs/router:version") &&
1733
- /createRSCHandler\s*\(\s*\{/.test(code);
1734
-
1735
- if (needsVersion) {
1736
- prepend.push(`import { VERSION } from "@rangojs/router:version";`);
1737
- newCode = newCode.replace(
1738
- /createRSCHandler\s*\(\s*\{/,
1739
- "createRSCHandler({\n version: VERSION,"
1740
- );
1741
- }
1742
-
1743
- if (prepend.length === 0 && newCode === code) return null;
1744
-
1745
- newCode = prepend.join("\n") + (prepend.length > 0 ? "\n" : "") + newCode;
1746
-
1747
- return {
1748
- code: newCode,
1749
- map: null,
1750
- };
1751
- },
1752
- };
1753
- }
1754
-
1755
- const _require = createRequire(import.meta.url);
1756
- const _rangoVersion: string = _require("../../package.json").version;
1757
-
1758
- let _bannerPrinted = false;
1759
-
1760
- function printBanner(
1761
- mode: "dev" | "build" | "preview",
1762
- preset: string,
1763
- version: string
1764
- ): void {
1765
- if (_bannerPrinted) return;
1766
- _bannerPrinted = true;
1767
-
1768
- // ANSI codes
1769
- const dim = "\x1b[2m";
1770
- const bold = "\x1b[1m";
1771
- const reset = "\x1b[0m";
1772
-
1773
- const banner = `
1774
- ${dim} ✦ ✦ ✧. . .${reset}
1775
- ${dim} ╱${reset} ${bold}╔═╗${reset}${dim} * ╱ ✦ *${reset}
1776
- ${dim} ${reset}${bold}║ ║${reset} ${bold}╔═╗${reset}${dim} * ✧. ╱${reset}
1777
- ${dim} ${reset}${bold}╔╗ ║ ║ ║ ║${reset}${dim} * ╱${reset}
1778
- ${dim} ${reset}${bold}║║ ║ ║ ║ ║ ╦═╗╔═╗╔╗╔╔═╗╔═╗${reset}${dim} ✧ ✦${reset}
1779
- ${dim} ${reset}${bold}═╣║ ║ ╠═╝ ║ ╠╦╝╠═╣║║║║ ╦║ ║${reset}${dim} * ✧${reset}
1780
- ${dim} ${reset}${bold}║╚═╝ ╔═══╝ ╩╚═╩ ╩╝╚╝╚═╝╚═╝${reset}${dim} ✦ . *${reset}
1781
- ${dim} ${reset}${bold}╚══╗ ║${reset}${dim} * RSC Wrangler ✧ ✦${reset}
1782
- ${dim} * ${reset}${bold}║ ╠═${reset}${dim} * ✧. ╱${reset}
1783
- ${bold}══════╝ ╚═════════╩═══${reset}${dim} ✦ *${reset}
1784
-
1785
- v${version} · ${preset} · ${mode}
1786
- `;
1787
-
1788
- console.log(banner);
1789
- }
1790
-
1791
- /**
1792
- * Vite plugin for @rangojs/router.
1793
- *
1794
- * Includes @vitejs/plugin-rsc and all necessary transforms for the router
1795
- * to function correctly with React Server Components.
1796
- *
1797
- * @example Node.js (default)
1798
- * ```ts
1799
- * export default defineConfig({
1800
- * plugins: [react(), rango({ router: './src/router.tsx' })],
1801
- * });
1802
- * ```
1803
- *
1804
- * @example Cloudflare Workers
1805
- * ```ts
1806
- * export default defineConfig({
1807
- * plugins: [
1808
- * react(),
1809
- * rango({ preset: 'cloudflare' }),
1810
- * cloudflare({ viteEnvironment: { name: 'rsc' } }),
1811
- * ],
1812
- * });
1813
- * ```
1814
- */
1815
- export async function rango(
1816
- options?: RangoOptions
1817
- ): Promise<PluginOption[]> {
1818
- const resolvedOptions: RangoOptions = options ?? { preset: "node" };
1819
- const preset = resolvedOptions.preset ?? "node";
1820
- const showBanner = resolvedOptions.banner ?? true;
1821
-
1822
- const plugins: PluginOption[] = [];
1823
-
1824
- // Get package resolution info (workspace vs npm install)
1825
- const rangoAliases = getPackageAliases();
1826
- const excludeDeps = getExcludeDeps();
1827
-
1828
- // Track RSC entry path for version injection
1829
- let rscEntryPath: string | null = null;
1830
-
1831
- // Resolved router path (node preset only, may be auto-discovered)
1832
- let routerPath: string | undefined;
1833
-
1834
- // Build-time prerendering is enabled for both presets.
1835
- // Collection runs in-process via the RSC dev environment runner during discoverRouters().
1836
- const prerenderEnabled = true;
1837
-
1838
- if (preset === "cloudflare") {
1839
- // Cloudflare preset: configure entries for cloudflare worker setup
1840
- // Router is not needed here - worker.rsc.tsx imports it directly
1841
-
1842
- // Dynamically import @vitejs/plugin-rsc
1843
- const { default: rsc } = await import("@vitejs/plugin-rsc");
1844
-
1845
- // Only client and ssr entries - rsc entry is handled by cloudflare plugin
1846
- // Always use virtual modules for cloudflare preset
1847
- const finalEntries: { client: string; ssr: string } = {
1848
- client: VIRTUAL_IDS.browser,
1849
- ssr: VIRTUAL_IDS.ssr,
1850
- };
1851
-
1852
- plugins.push({
1853
- name: "@rangojs/router:cloudflare-integration",
1854
- enforce: "pre",
1855
-
1856
- config() {
1857
- // Configure environments for cloudflare deployment
1858
- return {
1859
- // Exclude rsc-router modules from optimization to prevent module duplication
1860
- // This ensures the same Context instance is used by both browser entry and RSC proxy modules
1861
- optimizeDeps: {
1862
- exclude: excludeDeps,
1863
- esbuildOptions: sharedEsbuildOptions,
1864
- },
1865
- resolve: {
1866
- alias: rangoAliases,
1867
- },
1868
- build: {
1869
- rollupOptions: { onwarn },
1870
- },
1871
- environments: {
1872
- client: {
1873
- build: {
1874
- rollupOptions: {
1875
- output: {
1876
- manualChunks: getManualChunks,
1877
- },
1878
- },
1879
- },
1880
- // Pre-bundle rsc-html-stream to prevent discovery during first request
1881
- // Exclude rsc-router modules to ensure same Context instance
1882
- optimizeDeps: {
1883
- include: ["rsc-html-stream/client"],
1884
- exclude: excludeDeps,
1885
- esbuildOptions: sharedEsbuildOptions,
1886
- },
1887
- },
1888
- ssr: {
1889
- // Build SSR inside RSC directory so wrangler can deploy self-contained dist/rsc
1890
- build: {
1891
- outDir: "./dist/rsc/ssr",
1892
- },
1893
- resolve: {
1894
- // Ensure single React instance in SSR child environment
1895
- dedupe: ["react", "react-dom"],
1896
- },
1897
- // Pre-bundle SSR entry and React for proper module linking with childEnvironments
1898
- // All deps must be listed to avoid late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
1899
- optimizeDeps: {
1900
- entries: [finalEntries.ssr],
1901
- include: [
1902
- "react",
1903
- "react-dom",
1904
- "react-dom/server.edge",
1905
- "react-dom/static.edge",
1906
- "react/jsx-runtime",
1907
- "react/jsx-dev-runtime",
1908
- "rsc-html-stream/server",
1909
- "@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
1910
- ],
1911
- exclude: excludeDeps,
1912
- esbuildOptions: sharedEsbuildOptions,
1913
- },
1914
- },
1915
- rsc: {
1916
- // RSC environment needs exclude list and esbuild options
1917
- // Exclude rsc-router modules to prevent createContext in RSC environment
1918
- optimizeDeps: {
1919
- // Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
1920
- include: [
1921
- "react",
1922
- "react/jsx-runtime",
1923
- "react/jsx-dev-runtime",
1924
- "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
1925
- ],
1926
- exclude: excludeDeps,
1927
- esbuildOptions: sharedEsbuildOptions,
1928
- },
1929
- },
1930
- },
1931
- };
1932
- },
1933
-
1934
- configResolved(config) {
1935
- if (showBanner) {
1936
- const mode = config.command === "serve" ? (process.argv.includes("preview") ? "preview" : "dev") : "build";
1937
- printBanner(mode, "cloudflare", _rangoVersion);
1938
- }
1939
- },
1940
-
1941
- });
1942
-
1943
- plugins.push(createVirtualEntriesPlugin(finalEntries));
1944
-
1945
- // Add RSC plugin with cloudflare-specific options
1946
- // Note: loadModuleDevProxy should NOT be used with childEnvironments
1947
- // since SSR runs in workerd alongside RSC
1948
- plugins.push(
1949
- rsc({
1950
- get entries() {
1951
- return finalEntries;
1952
- },
1953
- serverHandler: false,
1954
- }) as PluginOption
1955
- );
1956
- } else {
1957
- // Node preset: full RSC plugin integration
1958
- const nodeOptions = resolvedOptions as RangoNodeOptions;
1959
- routerPath = nodeOptions.router;
1960
-
1961
- // Auto-discover router when not specified
1962
- if (!routerPath) {
1963
- const earlyFilter = createScanFilter(process.cwd(), {
1964
- include: resolvedOptions.include,
1965
- exclude: resolvedOptions.exclude,
1966
- });
1967
- const candidates = findRouterFiles(process.cwd(), earlyFilter);
1968
- if (candidates.length === 1) {
1969
- // Convert absolute path to relative ./path
1970
- const abs = candidates[0];
1971
- const rel = abs.startsWith(process.cwd())
1972
- ? "./" + abs.slice(process.cwd().length + 1)
1973
- : abs;
1974
- routerPath = rel;
1975
- } else if (candidates.length > 1) {
1976
- const cwd = process.cwd();
1977
- const list = candidates
1978
- .map((f) => " - " + (f.startsWith(cwd) ? f.slice(cwd.length + 1) : f))
1979
- .join("\n");
1980
- throw new Error(
1981
- `[rsc-router] Multiple routers found. Specify \`router\` to choose one:\n${list}`
1982
- );
1983
- }
1984
- // 0 found: routerPath stays undefined, warn at startup via discovery plugin
1985
- }
1986
-
1987
- const rscOption = nodeOptions.rsc ?? true;
1988
-
1989
- // Add RSC plugin by default (can be disabled with rsc: false)
1990
- if (rscOption !== false) {
1991
- // Dynamically import @vitejs/plugin-rsc
1992
- const { default: rsc } = await import("@vitejs/plugin-rsc");
1993
-
1994
- // Resolve entry paths: use explicit config or virtual modules
1995
- const userEntries =
1996
- typeof rscOption === "boolean" ? {} : rscOption.entries || {};
1997
- const finalEntries = {
1998
- client: userEntries.client ?? VIRTUAL_IDS.browser,
1999
- ssr: userEntries.ssr ?? VIRTUAL_IDS.ssr,
2000
- rsc: userEntries.rsc ?? VIRTUAL_IDS.rsc,
2001
- };
2002
-
2003
- // Track RSC entry for version injection (only if custom entry provided)
2004
- rscEntryPath = userEntries.rsc ?? null;
2005
-
2006
- // Create wrapper plugin that checks for duplicates
2007
- let hasWarnedDuplicate = false;
2008
-
2009
- plugins.push({
2010
- name: "@rangojs/router:rsc-integration",
2011
- enforce: "pre",
2012
-
2013
- config() {
2014
- // Configure environments for RSC
2015
- // When using virtual entries, we need to explicitly configure optimizeDeps
2016
- // so Vite pre-bundles React before processing the virtual modules.
2017
- // Without this, the dep optimizer may run multiple times with different hashes,
2018
- // causing React instance mismatches.
2019
- const useVirtualClient = finalEntries.client === VIRTUAL_IDS.browser;
2020
- const useVirtualSSR = finalEntries.ssr === VIRTUAL_IDS.ssr;
2021
- const useVirtualRSC = finalEntries.rsc === VIRTUAL_IDS.rsc;
2022
-
2023
- return {
2024
- // Exclude rsc-router modules from optimization to prevent module duplication
2025
- // This ensures the same Context instance is used by both browser entry and RSC proxy modules
2026
- optimizeDeps: {
2027
- exclude: excludeDeps,
2028
- esbuildOptions: sharedEsbuildOptions,
2029
- },
2030
- build: {
2031
- rollupOptions: { onwarn },
2032
- },
2033
- resolve: {
2034
- alias: rangoAliases,
2035
- },
2036
- environments: {
2037
- client: {
2038
- build: {
2039
- rollupOptions: {
2040
- output: {
2041
- manualChunks: getManualChunks,
2042
- },
2043
- },
2044
- },
2045
- // Always exclude rsc-router modules, conditionally add virtual entry
2046
- optimizeDeps: {
2047
- exclude: excludeDeps,
2048
- esbuildOptions: sharedEsbuildOptions,
2049
- ...(useVirtualClient && {
2050
- // Tell Vite to scan the virtual entry for dependencies
2051
- entries: [VIRTUAL_IDS.browser],
2052
- }),
2053
- },
2054
- },
2055
- ...(useVirtualSSR && {
2056
- ssr: {
2057
- optimizeDeps: {
2058
- entries: [VIRTUAL_IDS.ssr],
2059
- // Pre-bundle all SSR deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
2060
- include: [
2061
- "react",
2062
- "react-dom",
2063
- "react-dom/server.edge",
2064
- "react-dom/static.edge",
2065
- "react/jsx-runtime",
2066
- "react/jsx-dev-runtime",
2067
- "@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
2068
- ],
2069
- exclude: excludeDeps,
2070
- esbuildOptions: sharedEsbuildOptions,
2071
- },
2072
- },
2073
- }),
2074
- ...(useVirtualRSC && {
2075
- rsc: {
2076
- optimizeDeps: {
2077
- entries: [VIRTUAL_IDS.rsc],
2078
- // Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
2079
- include: [
2080
- "react",
2081
- "react/jsx-runtime",
2082
- "react/jsx-dev-runtime",
2083
- "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
2084
- ],
2085
- esbuildOptions: sharedEsbuildOptions,
2086
- },
2087
- },
2088
- }),
2089
- },
2090
- };
2091
- },
2092
-
2093
- configResolved(config) {
2094
- if (showBanner) {
2095
- const mode = config.command === "serve" ? (process.argv.includes("preview") ? "preview" : "dev") : "build";
2096
- printBanner(mode, "node", _rangoVersion);
2097
- }
2098
-
2099
- // Count how many RSC base plugins there are (rsc:minimal is the main one)
2100
- const rscMinimalCount = config.plugins.filter(
2101
- (p) => p.name === "rsc:minimal"
2102
- ).length;
2103
-
2104
- if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
2105
- hasWarnedDuplicate = true;
2106
- console.warn(
2107
- "[rsc-router] Duplicate @vitejs/plugin-rsc detected. " +
2108
- "Remove rsc() from your config or use rango({ rsc: false }) for manual configuration."
2109
- );
2110
- }
2111
- },
2112
- });
2113
-
2114
- // Add virtual entries plugin
2115
- plugins.push(createVirtualEntriesPlugin(finalEntries, routerPath));
2116
-
2117
- // Add the RSC plugin directly
2118
- // Cast to PluginOption to handle type differences between bundled vite types
2119
- plugins.push(
2120
- rsc({
2121
- entries: finalEntries,
2122
- }) as PluginOption
2123
- );
2124
- }
2125
- }
2126
-
2127
- plugins.push(exposeActionId());
2128
-
2129
- // Consolidated plugin for create* ID injection (enforce: "post"):
2130
- // loaders, handles, location state, and prerender handlers.
2131
- plugins.push(exposeInternalIds());
2132
-
2133
- // Router ID injection runs at normal priority (no enforce) to avoid
2134
- // changing Vite's dep optimization timing.
2135
- plugins.push(exposeRouterId());
2136
-
2137
- // Add version virtual module plugin for cache invalidation
2138
- plugins.push(createVersionPlugin());
2139
-
2140
- // Resolve discovery entry path (used for both discovery and version injection).
2141
- // Node preset: uses the (possibly auto-discovered) router path.
2142
- // Cloudflare preset: auto-detects RSC entry from wrangler.json main field.
2143
- const discoveryEntryPath = resolveDiscoveryEntryPath(
2144
- resolvedOptions,
2145
- preset !== "cloudflare" ? routerPath : undefined,
2146
- );
2147
-
2148
- // Add version injector for custom entry.rsc files.
2149
- // For Cloudflare preset, the RSC entry is the worker file (from wrangler.json).
2150
- const injectorEntryPath = rscEntryPath ?? (preset === "cloudflare" ? discoveryEntryPath : null);
2151
- if (injectorEntryPath) {
2152
- plugins.push(createVersionInjectorPlugin(injectorEntryPath));
2153
- }
2154
-
2155
- // Transform CJS vendor files to ESM for browser compatibility
2156
- // optimizeDeps.include doesn't work because the file is loaded after initial optimization
2157
- plugins.push(createCjsToEsmPlugin());
2158
-
2159
- // Add router discovery plugin for build-time manifest generation.
2160
- if (discoveryEntryPath) {
2161
- plugins.push(createRouterDiscoveryPlugin(discoveryEntryPath, {
2162
- enableBuildPrerender: prerenderEnabled,
2163
- staticRouteTypesGeneration: resolvedOptions.staticRouteTypesGeneration,
2164
- include: resolvedOptions.include,
2165
- exclude: resolvedOptions.exclude,
2166
- }));
2167
- }
2168
-
2169
- return plugins;
2170
- }
2171
-
2172
-
2173
-
2174
- /**
2175
- * Transform CJS vendor files from @vitejs/plugin-rsc to ESM for browser compatibility.
2176
- * The react-server-dom vendor files are shipped as CJS which doesn't work in browsers.
2177
- */
2178
- function createCjsToEsmPlugin(): Plugin {
2179
- return {
2180
- name: "@rangojs/router:cjs-to-esm",
2181
- enforce: "pre",
2182
- transform(code, id) {
2183
- const cleanId = id.split("?")[0];
2184
-
2185
- // Transform the client.browser.js entry point to re-export from CJS
2186
- if (
2187
- cleanId.includes("vendor/react-server-dom/client.browser.js") ||
2188
- cleanId.includes("vendor\\react-server-dom\\client.browser.js")
2189
- ) {
2190
- const isProd = process.env.NODE_ENV === "production";
2191
- const cjsFile = isProd
2192
- ? "./cjs/react-server-dom-webpack-client.browser.production.js"
2193
- : "./cjs/react-server-dom-webpack-client.browser.development.js";
2194
-
2195
- return {
2196
- code: `export * from "${cjsFile}";`,
2197
- map: null,
2198
- };
2199
- }
2200
-
2201
- // Transform the actual CJS files to ESM
2202
- if (
2203
- (cleanId.includes("vendor/react-server-dom/cjs/") ||
2204
- cleanId.includes("vendor\\react-server-dom\\cjs\\")) &&
2205
- cleanId.includes("client.browser")
2206
- ) {
2207
- let transformed = code;
2208
-
2209
- // Extract the license comment to preserve it
2210
- const licenseMatch = transformed.match(/^\/\*\*[\s\S]*?\*\//);
2211
- const license = licenseMatch ? licenseMatch[0] : "";
2212
- if (license) {
2213
- transformed = transformed.slice(license.length);
2214
- }
2215
-
2216
- // Remove "use strict" (both dev and prod have this)
2217
- transformed = transformed.replace(/^\s*["']use strict["'];\s*/, "");
2218
-
2219
- // Remove the conditional IIFE wrapper (development only)
2220
- transformed = transformed.replace(
2221
- /^\s*["']production["']\s*!==\s*process\.env\.NODE_ENV\s*&&\s*\(function\s*\(\)\s*\{/,
2222
- ""
2223
- );
2224
-
2225
- // Remove the closing of the conditional IIFE at the end (development only)
2226
- transformed = transformed.replace(/\}\)\(\);?\s*$/, "");
2227
-
2228
- // Replace require('react') and require('react-dom') with imports (development)
2229
- transformed = transformed.replace(
2230
- /var\s+React\s*=\s*require\s*\(\s*["']react["']\s*\)\s*,[\s\n]+ReactDOM\s*=\s*require\s*\(\s*["']react-dom["']\s*\)\s*,/g,
2231
- 'import React from "react";\nimport ReactDOM from "react-dom";\nvar '
2232
- );
2233
-
2234
- // Replace require('react-dom') only (production - doesn't import React)
2235
- transformed = transformed.replace(
2236
- /var\s+ReactDOM\s*=\s*require\s*\(\s*["']react-dom["']\s*\)\s*,/g,
2237
- 'import ReactDOM from "react-dom";\nvar '
2238
- );
2239
-
2240
- // Transform exports.xyz = function() to export function xyz()
2241
- transformed = transformed.replace(
2242
- /exports\.(\w+)\s*=\s*function\s*\(/g,
2243
- "export function $1("
2244
- );
2245
-
2246
- // Transform exports.xyz = value to export const xyz = value
2247
- transformed = transformed.replace(
2248
- /exports\.(\w+)\s*=/g,
2249
- "export const $1 ="
2250
- );
2251
-
2252
- // Reconstruct with license at the top
2253
- transformed = license + "\n" + transformed;
2254
8
 
2255
- return {
2256
- code: transformed,
2257
- map: null,
2258
- };
2259
- }
9
+ export { rango } from "./rango.js";
10
+ export { poke } from "./plugins/refresh-cmd.js";
2260
11
 
2261
- return null;
2262
- },
2263
- };
2264
- }
12
+ export type {
13
+ RangoNodeOptions,
14
+ RangoCloudflareOptions,
15
+ RangoOptions,
16
+ } from "./plugin-types.js";