@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.140

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 (460) hide show
  1. package/AGENTS.md +17 -0
  2. package/README.md +432 -7
  3. package/dist/bin/rango.js +2073 -213
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +7258 -2714
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +140 -67
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +329 -0
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +487 -0
  12. package/skills/caching/SKILL.md +357 -25
  13. package/skills/comparison/SKILL.md +50 -0
  14. package/skills/comparison/agents/openai.yaml +4 -0
  15. package/skills/comparison/references/framework-comparison.md +837 -0
  16. package/skills/composability/SKILL.md +246 -0
  17. package/skills/css/SKILL.md +76 -0
  18. package/skills/debug-manifest/SKILL.md +16 -10
  19. package/skills/document-cache/SKILL.md +87 -62
  20. package/skills/fonts/SKILL.md +6 -4
  21. package/skills/handler-use/SKILL.md +364 -0
  22. package/skills/hooks/SKILL.md +557 -79
  23. package/skills/host-router/SKILL.md +320 -0
  24. package/skills/i18n/SKILL.md +276 -0
  25. package/skills/intercept/SKILL.md +207 -15
  26. package/skills/layout/SKILL.md +146 -6
  27. package/skills/links/SKILL.md +304 -25
  28. package/skills/loader/SKILL.md +616 -54
  29. package/skills/middleware/SKILL.md +217 -37
  30. package/skills/migrate-nextjs/SKILL.md +611 -0
  31. package/skills/migrate-react-router/SKILL.md +927 -0
  32. package/skills/mime-routes/SKILL.md +42 -11
  33. package/skills/observability/SKILL.md +194 -0
  34. package/skills/parallel/SKILL.md +284 -3
  35. package/skills/ppr/SKILL.md +426 -0
  36. package/skills/prerender/SKILL.md +437 -52
  37. package/skills/rango/SKILL.md +369 -22
  38. package/skills/react-compiler/SKILL.md +168 -0
  39. package/skills/response-routes/SKILL.md +263 -121
  40. package/skills/route/SKILL.md +350 -21
  41. package/skills/router-setup/SKILL.md +246 -33
  42. package/skills/scripts/SKILL.md +179 -0
  43. package/skills/server-actions/SKILL.md +775 -0
  44. package/skills/shell-manifest/SKILL.md +185 -0
  45. package/skills/streams-and-websockets/SKILL.md +283 -0
  46. package/skills/tailwind/SKILL.md +27 -3
  47. package/skills/testing/SKILL.md +126 -222
  48. package/skills/testing/bindings.md +103 -0
  49. package/skills/testing/cache-prerender.md +127 -0
  50. package/skills/testing/client-components.md +124 -0
  51. package/skills/testing/e2e-parity.md +125 -0
  52. package/skills/testing/flight.md +91 -0
  53. package/skills/testing/handles.md +131 -0
  54. package/skills/testing/loader.md +128 -0
  55. package/skills/testing/middleware.md +99 -0
  56. package/skills/testing/render-handler.md +122 -0
  57. package/skills/testing/response-routes.md +95 -0
  58. package/skills/testing/reverse-and-types.md +85 -0
  59. package/skills/testing/server-actions.md +107 -0
  60. package/skills/testing/server-tree.md +128 -0
  61. package/skills/testing/setup.md +123 -0
  62. package/skills/theme/SKILL.md +9 -8
  63. package/skills/typesafety/SKILL.md +532 -103
  64. package/skills/use-cache/SKILL.md +367 -0
  65. package/skills/vercel/SKILL.md +128 -0
  66. package/skills/view-transitions/SKILL.md +337 -0
  67. package/src/__augment-tests__/augment.ts +81 -0
  68. package/src/__augment-tests__/augmented.check.ts +116 -0
  69. package/src/__internal.ts +77 -44
  70. package/src/bin/rango.ts +312 -15
  71. package/src/browser/action-coordinator.ts +114 -0
  72. package/src/browser/action-fence.ts +47 -0
  73. package/src/browser/app-shell.ts +39 -0
  74. package/src/browser/app-version.ts +14 -0
  75. package/src/browser/connection-warmup.ts +134 -0
  76. package/src/browser/cookie-name.ts +140 -0
  77. package/src/browser/event-controller.ts +293 -202
  78. package/src/browser/history-state.ts +101 -0
  79. package/src/browser/index.ts +3 -3
  80. package/src/browser/intercept-utils.ts +52 -0
  81. package/src/browser/invalidate-client-cache.ts +52 -0
  82. package/src/browser/link-interceptor.ts +24 -4
  83. package/src/browser/logging.ts +11 -0
  84. package/src/browser/merge-segment-loaders.ts +20 -12
  85. package/src/browser/navigation-bridge.ts +385 -576
  86. package/src/browser/navigation-client.ts +245 -75
  87. package/src/browser/navigation-store-handle.ts +38 -0
  88. package/src/browser/navigation-store.ts +184 -118
  89. package/src/browser/navigation-transaction.ts +247 -0
  90. package/src/browser/network-error-handler.ts +88 -0
  91. package/src/browser/partial-update.ts +412 -364
  92. package/src/browser/prefetch/cache.ts +359 -0
  93. package/src/browser/prefetch/fetch.ts +452 -0
  94. package/src/browser/prefetch/observer.ts +65 -0
  95. package/src/browser/prefetch/policy.ts +48 -0
  96. package/src/browser/prefetch/queue.ts +209 -0
  97. package/src/browser/prefetch/resource-ready.ts +77 -0
  98. package/src/browser/rango-state.ts +194 -0
  99. package/src/browser/react/Link.tsx +275 -68
  100. package/src/browser/react/NavigationProvider.tsx +265 -109
  101. package/src/browser/react/ScrollRestoration.tsx +10 -6
  102. package/src/browser/react/context.ts +11 -0
  103. package/src/browser/react/filter-segment-order.ts +70 -0
  104. package/src/browser/react/index.ts +0 -48
  105. package/src/browser/react/location-state-shared.ts +272 -60
  106. package/src/browser/react/location-state.ts +90 -20
  107. package/src/browser/react/mount-context.ts +6 -1
  108. package/src/browser/react/nonce-context.ts +23 -0
  109. package/src/browser/react/shallow-equal.ts +27 -0
  110. package/src/browser/react/use-action.ts +35 -66
  111. package/src/browser/react/use-handle.ts +39 -126
  112. package/src/browser/react/use-href.tsx +8 -1
  113. package/src/browser/react/use-link-status.ts +39 -13
  114. package/src/browser/react/use-navigation.ts +53 -69
  115. package/src/browser/react/use-params.ts +75 -0
  116. package/src/browser/react/use-pathname.ts +47 -0
  117. package/src/browser/react/use-reverse.ts +106 -0
  118. package/src/browser/react/use-router.ts +98 -0
  119. package/src/browser/react/use-search-params.ts +51 -0
  120. package/src/browser/react/use-segments.ts +72 -99
  121. package/src/browser/response-adapter.ts +164 -0
  122. package/src/browser/rsc-router.tsx +300 -72
  123. package/src/browser/scroll-restoration.ts +138 -50
  124. package/src/browser/segment-reconciler.ts +243 -0
  125. package/src/browser/segment-structure-assert.ts +17 -1
  126. package/src/browser/server-action-bridge.ts +668 -613
  127. package/src/browser/types.ts +223 -51
  128. package/src/browser/validate-redirect-origin.ts +56 -0
  129. package/src/build/collect-fallback-refs.ts +107 -0
  130. package/src/build/generate-manifest.ts +252 -161
  131. package/src/build/generate-route-types.ts +41 -1038
  132. package/src/build/index.ts +12 -7
  133. package/src/build/prefix-tree-utils.ts +123 -0
  134. package/src/build/route-trie.ts +225 -42
  135. package/src/build/route-types/ast-helpers.ts +25 -0
  136. package/src/build/route-types/ast-route-extraction.ts +105 -0
  137. package/src/build/route-types/codegen.ts +113 -0
  138. package/src/build/route-types/include-resolution.ts +812 -0
  139. package/src/build/route-types/param-extraction.ts +51 -0
  140. package/src/build/route-types/per-module-writer.ts +144 -0
  141. package/src/build/route-types/router-processing.ts +695 -0
  142. package/src/build/route-types/scan-filter.ts +85 -0
  143. package/src/build/route-types/source-scan.ts +216 -0
  144. package/src/build/runtime-discovery.ts +223 -0
  145. package/src/cache/background-task.ts +34 -0
  146. package/src/cache/cache-error.ts +104 -0
  147. package/src/cache/cache-key-utils.ts +60 -0
  148. package/src/cache/cache-policy.ts +199 -0
  149. package/src/cache/cache-runtime.ts +525 -0
  150. package/src/cache/cache-scope.ts +298 -332
  151. package/src/cache/cache-tag.ts +103 -0
  152. package/src/cache/cf/cf-base64.ts +33 -0
  153. package/src/cache/cf/cf-cache-constants.ts +127 -0
  154. package/src/cache/cf/cf-cache-store.ts +2500 -158
  155. package/src/cache/cf/cf-cache-types.ts +349 -0
  156. package/src/cache/cf/cf-kv-utils.ts +46 -0
  157. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  158. package/src/cache/cf/index.ts +17 -17
  159. package/src/cache/document-cache.ts +199 -92
  160. package/src/cache/handle-capture.ts +81 -0
  161. package/src/cache/handle-snapshot.ts +111 -0
  162. package/src/cache/index.ts +29 -35
  163. package/src/cache/memory-segment-store.ts +363 -30
  164. package/src/cache/profile-registry.ts +88 -0
  165. package/src/cache/read-through-swr.ts +178 -0
  166. package/src/cache/segment-codec.ts +248 -0
  167. package/src/cache/shell-cache.ts +386 -0
  168. package/src/cache/tag-invalidation.ts +230 -0
  169. package/src/cache/taint.ts +153 -0
  170. package/src/cache/types.ts +156 -211
  171. package/src/cache/vercel/index.ts +11 -0
  172. package/src/cache/vercel/vercel-cache-store.ts +1102 -0
  173. package/src/client.rsc.tsx +43 -21
  174. package/src/client.tsx +131 -347
  175. package/src/cloudflare/index.ts +11 -0
  176. package/src/cloudflare/tracing.ts +109 -0
  177. package/src/component-utils.ts +23 -4
  178. package/src/components/DefaultDocument.tsx +13 -3
  179. package/src/context-var.ts +168 -0
  180. package/src/debug.ts +19 -9
  181. package/src/decode-loader-results.ts +52 -0
  182. package/src/defer.ts +185 -0
  183. package/src/deps/ssr.ts +0 -1
  184. package/src/encode-kv.ts +49 -0
  185. package/src/errors.ts +106 -10
  186. package/src/escape-script.ts +52 -0
  187. package/src/handle.ts +110 -35
  188. package/src/handles/MetaTags.tsx +83 -59
  189. package/src/handles/Scripts.tsx +183 -0
  190. package/src/handles/breadcrumbs.ts +93 -0
  191. package/src/handles/deferred-resolution.ts +127 -0
  192. package/src/handles/is-thenable.ts +18 -0
  193. package/src/handles/meta.ts +44 -53
  194. package/src/handles/script.ts +244 -0
  195. package/src/host/cookie-handler.ts +20 -65
  196. package/src/host/errors.ts +21 -30
  197. package/src/host/index.ts +13 -9
  198. package/src/host/pattern-matcher.ts +50 -79
  199. package/src/host/router.ts +151 -121
  200. package/src/host/testing.ts +45 -32
  201. package/src/host/types.ts +52 -11
  202. package/src/host/utils.ts +2 -2
  203. package/src/href-client.ts +192 -57
  204. package/src/index.rsc.ts +177 -35
  205. package/src/index.ts +255 -71
  206. package/src/internal-debug.ts +9 -2
  207. package/src/loader-store.ts +500 -0
  208. package/src/loader.rsc.ts +31 -99
  209. package/src/loader.ts +30 -12
  210. package/src/missing-id-error.ts +68 -0
  211. package/src/outlet-context.ts +1 -1
  212. package/src/outlet-provider.tsx +41 -0
  213. package/src/prerender/param-hash.ts +16 -14
  214. package/src/prerender/store.ts +121 -21
  215. package/src/prerender.ts +460 -26
  216. package/src/redirect-origin.ts +100 -0
  217. package/src/regex-escape.ts +8 -0
  218. package/src/render-error-thrower.tsx +20 -0
  219. package/src/response-utils.ts +62 -0
  220. package/src/reverse.ts +198 -128
  221. package/src/root-error-boundary.tsx +42 -48
  222. package/src/route-content-wrapper.tsx +22 -77
  223. package/src/route-definition/dsl-helpers.ts +1116 -0
  224. package/src/route-definition/helper-factories.ts +88 -0
  225. package/src/route-definition/helpers-types.ts +505 -0
  226. package/src/route-definition/index.ts +54 -0
  227. package/src/route-definition/redirect.ts +134 -0
  228. package/src/route-definition/resolve-handler-use.ts +160 -0
  229. package/src/route-definition/use-item-types.ts +29 -0
  230. package/src/route-definition.ts +1 -1481
  231. package/src/route-map-builder.ts +82 -144
  232. package/src/route-name.ts +53 -0
  233. package/src/route-types.ts +71 -45
  234. package/src/router/basename.ts +14 -0
  235. package/src/router/content-negotiation.ts +263 -0
  236. package/src/router/debug-manifest.ts +72 -0
  237. package/src/router/error-handling.ts +54 -27
  238. package/src/router/find-match.ts +245 -0
  239. package/src/router/handler-context.ts +377 -125
  240. package/src/router/instrument.ts +350 -0
  241. package/src/router/intercept-resolution.ts +59 -28
  242. package/src/router/lazy-includes.ts +254 -0
  243. package/src/router/loader-resolution.ts +421 -157
  244. package/src/router/logging.ts +106 -6
  245. package/src/router/manifest.ts +131 -57
  246. package/src/router/match-api.ts +167 -246
  247. package/src/router/match-context.ts +4 -24
  248. package/src/router/match-handlers.ts +440 -0
  249. package/src/router/match-middleware/background-revalidation.ts +117 -93
  250. package/src/router/match-middleware/cache-lookup.ts +297 -150
  251. package/src/router/match-middleware/cache-store.ts +123 -51
  252. package/src/router/match-middleware/intercept-resolution.ts +44 -43
  253. package/src/router/match-middleware/segment-resolution.ts +64 -22
  254. package/src/router/match-pipelines.ts +11 -87
  255. package/src/router/match-result.ts +121 -50
  256. package/src/router/metrics.ts +219 -28
  257. package/src/router/middleware-types.ts +93 -0
  258. package/src/router/middleware.ts +505 -441
  259. package/src/router/navigation-snapshot.ts +133 -0
  260. package/src/router/params-util.ts +23 -0
  261. package/src/router/parse-pattern.ts +115 -0
  262. package/src/router/pattern-matching.ts +311 -142
  263. package/src/router/prefetch-cache-ttl.ts +51 -0
  264. package/src/router/prefetch-limits.ts +37 -0
  265. package/src/router/prerender-match.ts +547 -0
  266. package/src/router/preview-match.ts +102 -0
  267. package/src/router/request-classification.ts +278 -0
  268. package/src/router/revalidation.ts +203 -62
  269. package/src/router/route-snapshot.ts +246 -0
  270. package/src/router/router-context.ts +45 -48
  271. package/src/router/router-interfaces.ts +554 -0
  272. package/src/router/router-options.ts +779 -0
  273. package/src/router/router-registry.ts +21 -0
  274. package/src/router/segment-resolution/fresh.ts +772 -0
  275. package/src/router/segment-resolution/helpers.ts +348 -0
  276. package/src/router/segment-resolution/loader-cache.ts +250 -0
  277. package/src/router/segment-resolution/loader-mask.ts +44 -0
  278. package/src/router/segment-resolution/revalidation.ts +1331 -0
  279. package/src/router/segment-resolution/static-store.ts +81 -0
  280. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  281. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  282. package/src/router/segment-resolution.ts +25 -1354
  283. package/src/router/segment-wrappers.ts +292 -0
  284. package/src/router/state-cookie-name.ts +33 -0
  285. package/src/router/substitute-pattern-params.ts +75 -0
  286. package/src/router/telemetry-otel.ts +261 -0
  287. package/src/router/telemetry.ts +377 -0
  288. package/src/router/timeout.ts +128 -0
  289. package/src/router/tracing.ts +206 -0
  290. package/src/router/trie-matching.ts +240 -61
  291. package/src/router/types.ts +23 -70
  292. package/src/router/url-params.ts +57 -0
  293. package/src/router.ts +781 -2378
  294. package/src/rsc/full-payload.ts +70 -0
  295. package/src/rsc/handler-context.ts +46 -0
  296. package/src/rsc/handler.ts +905 -1142
  297. package/src/rsc/helpers.ts +275 -19
  298. package/src/rsc/index.ts +2 -25
  299. package/src/rsc/json-route-result.ts +38 -0
  300. package/src/rsc/loader-fetch.ts +305 -0
  301. package/src/rsc/manifest-init.ts +77 -0
  302. package/src/rsc/nonce.ts +14 -0
  303. package/src/rsc/origin-guard.ts +155 -0
  304. package/src/rsc/progressive-enhancement.ts +502 -0
  305. package/src/rsc/redirect-guard.ts +99 -0
  306. package/src/rsc/response-cache-serve.ts +238 -0
  307. package/src/rsc/response-error.ts +104 -0
  308. package/src/rsc/response-route-handler.ts +257 -0
  309. package/src/rsc/rsc-rendering.ts +337 -0
  310. package/src/rsc/runtime-warnings.ts +55 -0
  311. package/src/rsc/server-action.ts +522 -0
  312. package/src/rsc/shell-capture.ts +439 -0
  313. package/src/rsc/ssr-setup.ts +144 -0
  314. package/src/rsc/transition-gate.ts +89 -0
  315. package/src/rsc/types.ts +95 -12
  316. package/src/runtime-env.ts +18 -0
  317. package/src/search-params.ts +99 -82
  318. package/src/segment-content-promise.ts +67 -0
  319. package/src/segment-loader-promise.ts +149 -0
  320. package/src/segment-system.tsx +349 -134
  321. package/src/serialize.ts +243 -0
  322. package/src/server/context.ts +452 -85
  323. package/src/server/cookie-parse.ts +32 -0
  324. package/src/server/cookie-store.ts +310 -0
  325. package/src/server/fetchable-loader-store.ts +11 -6
  326. package/src/server/handle-store.ts +123 -42
  327. package/src/server/live.ts +130 -0
  328. package/src/server/loader-registry.ts +51 -100
  329. package/src/server/request-context.ts +842 -157
  330. package/src/server.ts +15 -8
  331. package/src/ssr/index.tsx +412 -136
  332. package/src/ssr/ssr-root.tsx +228 -0
  333. package/src/static-handler.ts +45 -18
  334. package/src/testing/cache-status.ts +162 -0
  335. package/src/testing/collect-handle.ts +46 -0
  336. package/src/testing/dispatch.ts +701 -0
  337. package/src/testing/dom.entry.ts +22 -0
  338. package/src/testing/e2e/fixture.ts +188 -0
  339. package/src/testing/e2e/index.ts +128 -0
  340. package/src/testing/e2e/matchers.ts +35 -0
  341. package/src/testing/e2e/page-helpers.ts +272 -0
  342. package/src/testing/e2e/parity.ts +387 -0
  343. package/src/testing/e2e/server.ts +195 -0
  344. package/src/testing/flight-matchers.ts +97 -0
  345. package/src/testing/flight-normalize.ts +11 -0
  346. package/src/testing/flight-runtime.d.ts +57 -0
  347. package/src/testing/flight-tree.ts +682 -0
  348. package/src/testing/flight.entry.ts +52 -0
  349. package/src/testing/flight.ts +257 -0
  350. package/src/testing/generated-routes.ts +199 -0
  351. package/src/testing/index.ts +105 -0
  352. package/src/testing/internal/context.ts +371 -0
  353. package/src/testing/internal/flight-client-globals.ts +30 -0
  354. package/src/testing/internal/seed-vars.ts +54 -0
  355. package/src/testing/render-handler.ts +357 -0
  356. package/src/testing/render-route.tsx +584 -0
  357. package/src/testing/run-loader.ts +385 -0
  358. package/src/testing/run-middleware.ts +205 -0
  359. package/src/testing/run-transition-when.ts +164 -0
  360. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  361. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  362. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  363. package/src/testing/vitest-stubs/version.ts +5 -0
  364. package/src/testing/vitest.ts +305 -0
  365. package/src/theme/ThemeProvider.tsx +40 -72
  366. package/src/theme/ThemeScript.tsx +12 -14
  367. package/src/theme/constants.ts +57 -15
  368. package/src/theme/index.ts +3 -20
  369. package/src/theme/theme-context.ts +5 -35
  370. package/src/theme/theme-script.ts +43 -39
  371. package/src/theme/use-theme.ts +0 -3
  372. package/src/types/boundaries.ts +123 -0
  373. package/src/types/cache-types.ts +207 -0
  374. package/src/types/error-types.ts +132 -0
  375. package/src/types/global-namespace.ts +113 -0
  376. package/src/types/handler-context.ts +839 -0
  377. package/src/types/index.ts +81 -0
  378. package/src/types/loader-types.ts +212 -0
  379. package/src/types/request-scope.ts +112 -0
  380. package/src/types/route-config.ts +138 -0
  381. package/src/types/route-entry.ts +114 -0
  382. package/src/types/segments.ts +271 -0
  383. package/src/types.ts +1 -1795
  384. package/src/urls/include-helper.ts +162 -0
  385. package/src/urls/include-provider.ts +71 -0
  386. package/src/urls/index.ts +43 -0
  387. package/src/urls/path-helper-types.ts +413 -0
  388. package/src/urls/path-helper.ts +275 -0
  389. package/src/urls/pattern-types.ts +124 -0
  390. package/src/urls/response-types.ts +109 -0
  391. package/src/urls/type-extraction.ts +316 -0
  392. package/src/urls/urls-function.ts +80 -0
  393. package/src/urls.ts +1 -1341
  394. package/src/use-loader.tsx +406 -141
  395. package/src/vercel/index.ts +11 -0
  396. package/src/vercel/tracing.ts +88 -0
  397. package/src/vite/debug.ts +185 -0
  398. package/src/vite/discovery/bundle-postprocess.ts +182 -0
  399. package/src/vite/discovery/discover-routers.ts +389 -0
  400. package/src/vite/discovery/discovery-errors.ts +255 -0
  401. package/src/vite/discovery/gate-state.ts +171 -0
  402. package/src/vite/discovery/prerender-collection.ts +467 -0
  403. package/src/vite/discovery/route-types-writer.ts +214 -0
  404. package/src/vite/discovery/self-gen-tracking.ts +73 -0
  405. package/src/vite/discovery/state.ts +161 -0
  406. package/src/vite/discovery/virtual-module-codegen.ts +183 -0
  407. package/src/vite/index.ts +23 -2255
  408. package/src/vite/inject-client-debug.ts +36 -0
  409. package/src/vite/plugin-types.ts +303 -0
  410. package/src/vite/plugins/cjs-to-esm.ts +90 -0
  411. package/src/vite/plugins/client-ref-dedup.ts +120 -0
  412. package/src/vite/plugins/client-ref-hashing.ts +118 -0
  413. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  414. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  415. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  416. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
  417. package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
  418. package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
  419. package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
  420. package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
  421. package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
  422. package/src/vite/plugins/expose-ids/types.ts +45 -0
  423. package/src/vite/plugins/expose-internal-ids.ts +805 -0
  424. package/src/vite/plugins/performance-tracks.ts +89 -0
  425. package/src/vite/plugins/refresh-cmd.ts +127 -0
  426. package/src/vite/plugins/use-cache-transform.ts +313 -0
  427. package/src/vite/plugins/vercel-output.ts +384 -0
  428. package/src/vite/plugins/version-injector.ts +94 -0
  429. package/src/vite/plugins/version-plugin.ts +263 -0
  430. package/src/vite/plugins/virtual-entries.ts +234 -0
  431. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  432. package/src/vite/rango.ts +560 -0
  433. package/src/vite/router-discovery.ts +1638 -0
  434. package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
  435. package/src/vite/utils/banner.ts +36 -0
  436. package/src/vite/utils/bundle-analysis.ts +132 -0
  437. package/src/vite/utils/client-chunks.ts +184 -0
  438. package/src/vite/utils/directive-prologue.ts +40 -0
  439. package/src/vite/utils/forward-user-plugins.ts +171 -0
  440. package/src/vite/utils/manifest-utils.ts +15 -0
  441. package/src/vite/utils/package-resolution.ts +89 -0
  442. package/src/vite/utils/prerender-utils.ts +249 -0
  443. package/src/vite/utils/shared-utils.ts +269 -0
  444. package/CLAUDE.md +0 -43
  445. package/dist/vite/index.named-routes.gen.ts +0 -103
  446. package/src/browser/lru-cache.ts +0 -69
  447. package/src/browser/react/use-client-cache.ts +0 -56
  448. package/src/browser/request-controller.ts +0 -164
  449. package/src/browser/shallow.ts +0 -35
  450. package/src/cache/memory-store.ts +0 -253
  451. package/src/handles/index.ts +0 -6
  452. package/src/href-context.ts +0 -33
  453. package/src/network-error-thrower.tsx +0 -21
  454. package/src/router.gen.ts +0 -6
  455. package/src/static-handler.gen.ts +0 -5
  456. package/src/urls.gen.ts +0 -8
  457. package/src/vite/expose-internal-ids.ts +0 -1167
  458. package/src/vite/package-resolution.ts +0 -125
  459. package/src/vite/virtual-entries.ts +0 -114
  460. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -0,0 +1,263 @@
1
+ import { parseAst, type Plugin } from "vite";
2
+ import { VIRTUAL_IDS, getVirtualVersionContent } from "./virtual-entries.js";
3
+ import { hasUseClientDirective } from "../utils/directive-prologue.js";
4
+
5
+ interface ClientModuleSignature {
6
+ key: string;
7
+ }
8
+
9
+ function isCodeModule(id: string): boolean {
10
+ return /\.(tsx?|jsx?)($|\?)/.test(id);
11
+ }
12
+
13
+ function normalizeModuleId(id: string): string {
14
+ return id.split("?", 1)[0];
15
+ }
16
+
17
+ function getClientModuleSignature(
18
+ source: string,
19
+ ): ClientModuleSignature | undefined {
20
+ // Same leading-directive sniff the rango HMR plugin uses (shared helper, so the
21
+ // two agree on what counts as a client module). A parse failure yields false.
22
+ if (!hasUseClientDirective(source)) return undefined;
23
+
24
+ let program: any;
25
+ try {
26
+ program = parseAst(source, { lang: "tsx" });
27
+ } catch {
28
+ return undefined;
29
+ }
30
+
31
+ const exports = new Set<string>();
32
+ let hasDefault = false;
33
+ let hasExportAll = false;
34
+
35
+ const collectBindingNames = (pattern: any) => {
36
+ if (!pattern) return;
37
+ if (pattern.type === "Identifier") {
38
+ exports.add(pattern.name);
39
+ } else if (pattern.type === "ObjectPattern") {
40
+ for (const prop of pattern.properties ?? []) {
41
+ if (prop?.type === "RestElement") {
42
+ collectBindingNames(prop.argument);
43
+ } else {
44
+ collectBindingNames(prop?.value);
45
+ }
46
+ }
47
+ } else if (pattern.type === "ArrayPattern") {
48
+ for (const el of pattern.elements ?? []) {
49
+ if (el?.type === "RestElement") {
50
+ collectBindingNames(el.argument);
51
+ } else {
52
+ collectBindingNames(el);
53
+ }
54
+ }
55
+ }
56
+ };
57
+
58
+ const collectDeclarationNames = (declaration: any) => {
59
+ if (!declaration) return;
60
+ if (declaration.type === "VariableDeclaration") {
61
+ for (const decl of declaration.declarations ?? []) {
62
+ collectBindingNames(decl?.id);
63
+ }
64
+ return;
65
+ }
66
+ collectBindingNames(declaration.id);
67
+ };
68
+
69
+ for (const node of program.body ?? []) {
70
+ if (node?.type === "ExportDefaultDeclaration") {
71
+ hasDefault = true;
72
+ continue;
73
+ }
74
+ if (node?.type === "ExportAllDeclaration") {
75
+ hasExportAll = true;
76
+ continue;
77
+ }
78
+ if (node?.type !== "ExportNamedDeclaration") continue;
79
+
80
+ collectDeclarationNames(node.declaration);
81
+
82
+ for (const specifier of node.specifiers ?? []) {
83
+ const exportedName =
84
+ specifier?.exported?.name ?? specifier?.exported?.value;
85
+ if (exportedName === "default") {
86
+ hasDefault = true;
87
+ } else if (typeof exportedName === "string") {
88
+ exports.add(exportedName);
89
+ }
90
+ }
91
+ }
92
+
93
+ return {
94
+ key: JSON.stringify({
95
+ default: hasDefault,
96
+ exportAll: hasExportAll,
97
+ exports: [...exports].sort(),
98
+ }),
99
+ };
100
+ }
101
+
102
+ /**
103
+ * Plugin providing rsc-router:version virtual module.
104
+ * Exports VERSION that changes when RSC modules change (dev) or at build time (production).
105
+ *
106
+ * The version is used for:
107
+ * 1. Cache invalidation - CFCacheStore uses VERSION to invalidate stale cache
108
+ * 2. Version mismatch detection - client sends version, server reloads on mismatch
109
+ *
110
+ * In dev mode, the version updates when:
111
+ * - Server starts (initial version)
112
+ * - RSC modules change via HMR (triggers version module invalidation)
113
+ *
114
+ * Client-only HMR changes don't update the version since they don't affect
115
+ * server-rendered content or cached RSC payloads.
116
+ * @internal
117
+ */
118
+ export function createVersionPlugin(): Plugin {
119
+ // Generate version at plugin creation time (build/server start)
120
+ const buildVersion = Date.now().toString(16);
121
+ let currentVersion = buildVersion;
122
+ let isDev = false;
123
+ let server: any = null;
124
+ let resolvedCacheDir: string | undefined;
125
+ const clientModuleSignatures = new Map<string, ClientModuleSignature>();
126
+
127
+ let versionCounter = 0;
128
+ const bumpVersion = (reason: string) => {
129
+ currentVersion = Date.now().toString(16) + String(++versionCounter);
130
+ console.log(`[rango] ${reason}, version updated: ${currentVersion}`);
131
+
132
+ const rscEnv = server?.environments?.rsc;
133
+ const versionMod = rscEnv?.moduleGraph?.getModuleById(
134
+ "\0" + VIRTUAL_IDS.version,
135
+ );
136
+ if (versionMod) {
137
+ rscEnv.moduleGraph.invalidateModule(versionMod);
138
+ }
139
+ };
140
+
141
+ return {
142
+ name: "@rangojs/router:version",
143
+ enforce: "pre",
144
+
145
+ configResolved(config) {
146
+ isDev = config.command === "serve";
147
+ resolvedCacheDir = config.cacheDir
148
+ ? String(config.cacheDir).replace(/\\/g, "/")
149
+ : undefined;
150
+ },
151
+
152
+ configureServer(devServer) {
153
+ server = devServer;
154
+
155
+ devServer.watcher.on("unlink", (filePath) => {
156
+ if (!isDev) return;
157
+ if (!clientModuleSignatures.has(filePath)) return;
158
+ clientModuleSignatures.delete(filePath);
159
+ bumpVersion("Client module removed");
160
+ });
161
+ },
162
+
163
+ resolveId(id) {
164
+ if (id === VIRTUAL_IDS.version) {
165
+ return "\0" + id;
166
+ }
167
+ return null;
168
+ },
169
+
170
+ load(id) {
171
+ if (id === "\0" + VIRTUAL_IDS.version) {
172
+ return getVirtualVersionContent(currentVersion);
173
+ }
174
+ return null;
175
+ },
176
+
177
+ transform(code, id) {
178
+ if (!isDev || !isCodeModule(id)) return null;
179
+ const normalizedId = normalizeModuleId(id);
180
+ if (
181
+ !code.includes("use client") &&
182
+ !clientModuleSignatures.has(normalizedId)
183
+ ) {
184
+ return null;
185
+ }
186
+
187
+ const signature = getClientModuleSignature(code);
188
+ if (signature) {
189
+ clientModuleSignatures.set(normalizedId, signature);
190
+ } else {
191
+ clientModuleSignatures.delete(normalizedId);
192
+ }
193
+ return null;
194
+ },
195
+
196
+ async hotUpdate(ctx) {
197
+ if (!isDev) return;
198
+
199
+ const isRscModule = this.environment?.name === "rsc";
200
+
201
+ if (!isRscModule) return;
202
+
203
+ if (isViteDepCachePath(ctx.file, resolvedCacheDir)) return;
204
+
205
+ if (
206
+ ctx.modules.length === 1 &&
207
+ ctx.modules[0].id === "\0" + VIRTUAL_IDS.version
208
+ ) {
209
+ return;
210
+ }
211
+
212
+ if (isCodeModule(ctx.file)) {
213
+ const filePath = normalizeModuleId(ctx.file);
214
+ const previousSignature = clientModuleSignatures.get(filePath);
215
+ try {
216
+ const source = await ctx.read();
217
+ const nextSignature = getClientModuleSignature(source);
218
+ if (nextSignature) {
219
+ clientModuleSignatures.set(filePath, nextSignature);
220
+ if (
221
+ previousSignature &&
222
+ previousSignature.key === nextSignature.key
223
+ ) {
224
+ return;
225
+ }
226
+ } else {
227
+ clientModuleSignatures.delete(filePath);
228
+ if (!previousSignature) {
229
+ if (ctx.modules.length === 0) return;
230
+ }
231
+ }
232
+ } catch {}
233
+ } else {
234
+ if (ctx.modules.length === 0) return;
235
+ }
236
+
237
+ bumpVersion("RSC module changed");
238
+ },
239
+ };
240
+ }
241
+
242
+ export function isViteDepCachePath(
243
+ filePath: string | undefined,
244
+ cacheDir?: string,
245
+ ): boolean {
246
+ if (!filePath) return false;
247
+ const normalized = filePath.replace(/\\/g, "/");
248
+
249
+ if (cacheDir) {
250
+ const normalizedCacheDir = cacheDir.replace(/\\/g, "/").replace(/\/+$/, "");
251
+ if (
252
+ normalized === normalizedCacheDir ||
253
+ normalized.startsWith(normalizedCacheDir + "/")
254
+ ) {
255
+ return true;
256
+ }
257
+ }
258
+
259
+ return (
260
+ /\/node_modules\/\.vite[^/]*\//.test(normalized) ||
261
+ normalized.includes("/.vite-isolated/")
262
+ );
263
+ }
@@ -0,0 +1,234 @@
1
+ export const VIRTUAL_ENTRY_BROWSER: string = `
2
+ import {
3
+ createFromReadableStream,
4
+ createFromFetch,
5
+ setServerCallback,
6
+ encodeReply,
7
+ createTemporaryReferenceSet,
8
+ } from "@rangojs/router/internal/deps/browser";
9
+ import { createElement, StrictMode } from "react";
10
+ import { hydrateRoot } from "react-dom/client";
11
+ import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
12
+ import { initBrowserApp, Rango } from "@rangojs/router/browser";
13
+
14
+ async function initializeApp() {
15
+ const deps = {
16
+ createFromFetch,
17
+ createFromReadableStream,
18
+ encodeReply,
19
+ setServerCallback,
20
+ createTemporaryReferenceSet,
21
+ };
22
+
23
+ // initBrowserApp resolves the initial payload and returns the browser app
24
+ // context, including strictMode (default true) from createRouter. StrictMode
25
+ // is the default; createRouter({ strictMode: false }) ships the opt-out in the
26
+ // payload metadata. StrictMode emits no DOM, so toggling never changes markup.
27
+ const { strictMode } = await initBrowserApp({ rscStream, deps });
28
+
29
+ const app = createElement(Rango);
30
+ hydrateRoot(
31
+ document,
32
+ strictMode === false ? app : createElement(StrictMode, null, app)
33
+ );
34
+ }
35
+
36
+ initializeApp().catch(console.error);
37
+ `.trim();
38
+
39
+ export const VIRTUAL_ENTRY_SSR: string = `
40
+ import { createFromReadableStream } from "@rangojs/router/internal/deps/ssr";
41
+ import { renderToReadableStream, resume } from "react-dom/server.edge";
42
+ import { prerender } from "react-dom/static.edge";
43
+ import { injectRSCPayload } from "@rangojs/router/internal/deps/html-stream-server";
44
+ import {
45
+ createSSRHandler,
46
+ createShellCaptureHandler,
47
+ createShellResumeHandler,
48
+ } from "@rangojs/router/ssr";
49
+
50
+ export const renderHTML = createSSRHandler({
51
+ createFromReadableStream,
52
+ renderToReadableStream,
53
+ injectRSCPayload,
54
+ loadBootstrapScriptContent: () =>
55
+ import.meta.viteRsc.loadBootstrapScriptContent("index"),
56
+ });
57
+
58
+ export const captureShellHTML = createShellCaptureHandler({
59
+ createFromReadableStream,
60
+ renderToReadableStream,
61
+ injectRSCPayload,
62
+ prerender,
63
+ resume,
64
+ loadBootstrapScriptContent: () =>
65
+ import.meta.viteRsc.loadBootstrapScriptContent("index"),
66
+ });
67
+
68
+ export const resumeShellHTML = createShellResumeHandler({
69
+ createFromReadableStream,
70
+ renderToReadableStream,
71
+ injectRSCPayload,
72
+ prerender,
73
+ resume,
74
+ loadBootstrapScriptContent: () =>
75
+ import.meta.viteRsc.loadBootstrapScriptContent("index"),
76
+ });
77
+ `.trim();
78
+
79
+ /**
80
+ * Virtual modules an RSC entry must import at startup to register the data the
81
+ * request handler needs before the first request arrives:
82
+ *
83
+ * - routes-manifest: the pre-generated route map so href()/matching work on a
84
+ * cold start (full map in build, in-memory no-op in dev).
85
+ * - loader-manifest: setLoaderImports() for fetchable loaders. Critical for
86
+ * serverless/multi-process deployments and for fetchable loaders reachable
87
+ * only through a client component — without it those loaders are never
88
+ * registered for the _rsc_loader endpoint and fail in production.
89
+ *
90
+ * Single source of truth: both the generated virtual RSC entry below and the
91
+ * custom-entry injector (version-injector) consume this list, so a new
92
+ * bootstrap manifest cannot be added to one path and forgotten on the other.
93
+ * That exact drift (loader-manifest present here but missing from the injector)
94
+ * is what left fetchable loaders unresolved on custom worker entries.
95
+ */
96
+ export const RSC_ENTRY_BOOTSTRAP_IMPORTS: readonly string[] = [
97
+ "virtual:rsc-router/routes-manifest",
98
+ "virtual:rsc-router/loader-manifest",
99
+ ];
100
+
101
+ export function getVirtualEntryRSC(routerPath: string): string {
102
+ const bootstrapImports = RSC_ENTRY_BOOTSTRAP_IMPORTS.map(
103
+ (id) => `import "${id}";`,
104
+ ).join("\n");
105
+ return `
106
+ import {
107
+ renderToReadableStream,
108
+ decodeReply,
109
+ createTemporaryReferenceSet,
110
+ loadServerAction,
111
+ decodeAction,
112
+ decodeFormState,
113
+ } from "@rangojs/router/internal/deps/rsc";
114
+ import { router } from "${routerPath}";
115
+ import { createRSCHandler } from "@rangojs/router/internal/rsc-handler";
116
+ import { VERSION } from "@rangojs/router:version";
117
+
118
+ // Startup bootstrap imports (routes + loader manifests). See
119
+ // RSC_ENTRY_BOOTSTRAP_IMPORTS — the same list the custom-entry injector uses.
120
+ ${bootstrapImports}
121
+
122
+ // Lazily create the handler on first request so that ESM live bindings
123
+ // have resolved by the time we read \`router\`. During HMR the module may
124
+ // re-evaluate before router.tsx finishes, leaving the import undefined.
125
+ let _handler;
126
+ export default function handler(request, env) {
127
+ if (!_handler) {
128
+ _handler = createRSCHandler({
129
+ router,
130
+ version: VERSION,
131
+ // Forward the router's CSP nonce provider. createRSCHandler reads the
132
+ // provider only from options.nonce; without this, createRouter({ nonce })
133
+ // is silently dropped on the Node preset (the Cloudflare path wires it via
134
+ // router.fetch). router.nonce is undefined when unconfigured, a safe no-op.
135
+ nonce: router.nonce,
136
+ deps: {
137
+ renderToReadableStream,
138
+ decodeReply,
139
+ createTemporaryReferenceSet,
140
+ loadServerAction,
141
+ decodeAction,
142
+ decodeFormState,
143
+ },
144
+ loadSSRModule: () =>
145
+ import.meta.viteRsc.loadModule("ssr", "index"),
146
+ });
147
+ }
148
+ return _handler(request, env);
149
+ }
150
+ `.trim();
151
+ }
152
+
153
+ export function getVirtualEntryRSCHost(hostEntryPath: string): string {
154
+ return `
155
+ import * as __hostEntry from "${hostEntryPath}";
156
+ import { isNoRouteMatchError } from "@rangojs/router/host";
157
+
158
+ // Register every sub-app's fetchable loaders + route manifests at startup, same
159
+ // as the single-router entry. Discovery's host fallback populates these for all
160
+ // mounted sub-apps, so the aggregate manifests cover the whole host tree.
161
+ import "virtual:rsc-router/loader-manifest";
162
+ import "virtual:rsc-router/routes-manifest";
163
+
164
+ // The host entry module must export the HostRouter instance (createHostRouter()),
165
+ // as a default export or a named \`hostRouter\`/\`router\` export. A Cloudflare-style
166
+ // \`export default { fetch }\` object is not a HostRouter and is rejected (on first
167
+ // request; see the lazy resolution below).
168
+ // We require BOTH .match() and .host(): a regular createRouter() also exposes
169
+ // .match(), so matching on .match() alone would accept an ordinary router and then
170
+ // return its MatchResult (not a Response) at runtime. .host() is unique to a
171
+ // HostRouter, so it disambiguates a mistaken \`hostRouter\` path.
172
+ // Exports are read dynamically (m[name]) so Rollup does not emit IMPORT_IS_UNDEFINED
173
+ // warnings for the named exports a default-only host module legitimately omits.
174
+ const __resolveHostRouter = (m) => {
175
+ for (const name of ["default", "hostRouter", "router"]) {
176
+ const candidate = m[name];
177
+ if (
178
+ candidate &&
179
+ typeof candidate.match === "function" &&
180
+ typeof candidate.host === "function"
181
+ )
182
+ return candidate;
183
+ }
184
+ return undefined;
185
+ };
186
+
187
+ // Resolve + validate the HostRouter lazily on first request, mirroring the
188
+ // single-router entry's \`_handler\`. During HMR the host module can re-evaluate
189
+ // before its createHostRouter() export has resolved; validating at module-
190
+ // evaluation time would then throw a spurious "must export a HostRouter" error
191
+ // overlay for a perfectly valid app. Resolving on first request lets the live
192
+ // binding settle first.
193
+ let _hostRouter;
194
+
195
+ // input = { env, ctx } from the launcher / node server. The host router threads
196
+ // it unchanged to each matched sub-app's handler and cache factory.
197
+ // On node/vercel rango owns this entry, so there is no user worker to translate
198
+ // an unmatched host into a response: catch NoRouteMatchError and return 404
199
+ // (parity with the documented Cloudflare catch). Other errors propagate.
200
+ export default async function handler(request, input) {
201
+ if (!_hostRouter) {
202
+ _hostRouter = __resolveHostRouter(__hostEntry);
203
+ if (!_hostRouter) {
204
+ throw new Error(
205
+ "[rango] The host entry (${hostEntryPath}) must export a HostRouter instance (createHostRouter()) for the node/vercel preset: a default export, or a named 'hostRouter'/'router' export. An ordinary createRouter() is not a host router (it has no .host()), and a Cloudflare-style 'export default { fetch }' object is not supported on this preset."
206
+ );
207
+ }
208
+ }
209
+ try {
210
+ return await _hostRouter.match(request, input);
211
+ } catch (err) {
212
+ // isNoRouteMatchError also matches by name: a workspace with a duplicated
213
+ // @rangojs/router copy can throw a NoRouteMatchError whose prototype differs
214
+ // from this module's import, so a bare instanceof would turn an
215
+ // unmatched-host 404 into a 500.
216
+ if (isNoRouteMatchError(err)) {
217
+ return new Response("Not Found", { status: 404 });
218
+ }
219
+ throw err;
220
+ }
221
+ }
222
+ `.trim();
223
+ }
224
+
225
+ export const VIRTUAL_IDS = {
226
+ browser: "virtual:rsc-router/entry.browser.js",
227
+ ssr: "virtual:rsc-router/entry.ssr.js",
228
+ rsc: "virtual:rsc-router/entry.rsc.js",
229
+ version: "@rangojs/router:version",
230
+ } as const;
231
+
232
+ export function getVirtualVersionContent(version: string): string {
233
+ return `export const VERSION = ${JSON.stringify(version)};`;
234
+ }
@@ -0,0 +1,29 @@
1
+ import type { Plugin } from "vite";
2
+
3
+ /**
4
+ * Stub plugin that resolves and provides empty exports for virtual modules
5
+ * that the RSC entry may import but aren't needed for route discovery.
6
+ * @internal
7
+ */
8
+ export function createVirtualStubPlugin(): Plugin {
9
+ const STUB_PREFIXES = [
10
+ "virtual:rsc-router/",
11
+ "virtual:entry-",
12
+ "virtual:vite-rsc/",
13
+ ];
14
+ return {
15
+ name: "@rangojs/router:virtual-stubs",
16
+ resolveId(id) {
17
+ if (STUB_PREFIXES.some((p) => id.startsWith(p))) {
18
+ return "\0stub:" + id;
19
+ }
20
+ return null;
21
+ },
22
+ load(id) {
23
+ if (id.startsWith("\0stub:")) {
24
+ return "export default {}";
25
+ }
26
+ return null;
27
+ },
28
+ };
29
+ }