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

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 +293 -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 +2508 -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 +24 -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-snapshot.ts +368 -0
  168. package/src/cache/tag-invalidation.ts +230 -0
  169. package/src/cache/taint.ts +153 -0
  170. package/src/cache/types.ts +222 -211
  171. package/src/cache/vercel/index.ts +11 -0
  172. package/src/cache/vercel/vercel-cache-store.ts +1113 -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 +173 -35
  205. package/src/index.ts +241 -73
  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 +527 -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 +897 -0
  313. package/src/rsc/shell-serve.ts +124 -0
  314. package/src/rsc/ssr-setup.ts +144 -0
  315. package/src/rsc/transition-gate.ts +89 -0
  316. package/src/rsc/types.ts +95 -12
  317. package/src/runtime-env.ts +18 -0
  318. package/src/search-params.ts +99 -82
  319. package/src/segment-content-promise.ts +67 -0
  320. package/src/segment-loader-promise.ts +149 -0
  321. package/src/segment-system.tsx +349 -134
  322. package/src/serialize.ts +243 -0
  323. package/src/server/context.ts +459 -85
  324. package/src/server/cookie-parse.ts +32 -0
  325. package/src/server/cookie-store.ts +310 -0
  326. package/src/server/fetchable-loader-store.ts +11 -6
  327. package/src/server/handle-store.ts +123 -42
  328. package/src/server/loader-registry.ts +51 -100
  329. package/src/server/request-context.ts +848 -157
  330. package/src/server.ts +15 -8
  331. package/src/ssr/index.tsx +443 -135
  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 +76 -98
  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 +44 -0
  387. package/src/urls/path-helper-types.ts +413 -0
  388. package/src/urls/path-helper.ts +280 -0
  389. package/src/urls/pattern-types.ts +160 -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
@@ -23,7 +23,7 @@ function ShopLayout() {
23
23
  );
24
24
  }
25
25
 
26
- export const urlpatterns = urls(({ path, layout, intercept, loader }) => [
26
+ export const urlpatterns = urls(({ path, layout, intercept, loader, loading }) => [
27
27
  layout(<ShopLayout />, () => [
28
28
  // Intercept product detail - shows modal during soft navigation
29
29
  intercept(
@@ -45,11 +45,11 @@ export const urlpatterns = urls(({ path, layout, intercept, loader }) => [
45
45
 
46
46
  ## Navigation Behavior
47
47
 
48
- | Navigation Type | What Renders |
49
- |-----------------|--------------|
48
+ | Navigation Type | What Renders |
49
+ | ------------------------------ | ---------------------------------------------------- |
50
50
  | Click link `/shop/product/abc` | `<ProductModal />` in `@modal`, background preserved |
51
- | Direct URL `/shop/product/abc` | Full `<ProductPage />` page |
52
- | Browser back | Close modal, restore previous state |
51
+ | Direct URL `/shop/product/abc` | Full `<ProductPage />` page |
52
+ | Browser back | Close modal, restore previous state |
53
53
 
54
54
  ## Intercept with Layout
55
55
 
@@ -68,18 +68,115 @@ intercept(
68
68
  )
69
69
  ```
70
70
 
71
- ## Conditional Intercept with when()
71
+ ## Intercept Middleware
72
72
 
73
- Only intercept based on navigation context:
73
+ Intercepts support their own middleware chain via the use callback. The full chain for an intercept request is:
74
+
75
+ ```
76
+ global mw (router.use) -> route mw (urls middleware()) -> intercept mw -> intercept handler -> intercept loaders
77
+ ```
78
+
79
+ ```typescript
80
+ intercept(
81
+ "@modal",
82
+ "product",
83
+ <ProductModal />,
84
+ () => [
85
+ middleware(async (ctx, next) => {
86
+ // Runs only for this intercept, after global and route middleware
87
+ ctx.set("interceptSource", "modal");
88
+ await next();
89
+ }),
90
+ loader(ProductLoader),
91
+ ]
92
+ )
93
+ ```
94
+
95
+ The intercept handler can read context variables set by all upstream middleware layers (global, route, and intercept-specific).
96
+
97
+ Handler/layout `ctx.set()` data follows the same rule as elsewhere:
98
+ intercepts see data produced in the current render pass, but partial
99
+ action revalidation only recomputes segments that actually revalidate.
100
+ If an intercept depends on data established by an outer layout/handler,
101
+ revalidate that outer segment too or reload/guard the data inside the
102
+ intercept.
103
+
104
+ ### Revalidation Contracts for Intercept Dependencies
105
+
106
+ Use named revalidation contracts on both the outer producer and the intercept
107
+ consumer when they share `ctx.set()` data:
108
+
109
+ ```typescript
110
+ import * as ProductActions from "./actions/product";
111
+
112
+ export const revalidateProductShell = (ctx) =>
113
+ ctx.isAction(ProductActions) || undefined;
114
+
115
+ layout(ProductLayout, () => [
116
+ revalidate(revalidateProductShell), // producer reruns
117
+ intercept("@modal", "product", <ProductModal />, () => [
118
+ revalidate(revalidateProductShell), // consumer reruns
119
+ loader(ProductLoader),
120
+ ]),
121
+ ]);
122
+ ```
123
+
124
+ Compose multiple contracts if the intercept depends on multiple upstream
125
+ domains.
126
+
127
+ Helper handoff style keeps intercept trees terse:
128
+
129
+ ```typescript
130
+ import { revalidate } from "@rangojs/router";
131
+
132
+ export const revalidateProduct = () => [
133
+ revalidate(revalidateProductShell),
134
+ ];
135
+
136
+ layout(ProductLayout, () => [
137
+ revalidateProduct(),
138
+ intercept("@modal", "product", <ProductModal />, () => [
139
+ revalidateProduct(),
140
+ loader(ProductLoader),
141
+ ]),
142
+ ]);
143
+ ```
144
+
145
+ ## Conditional Intercept with the `when` config
146
+
147
+ Only intercept based on navigation context. `when` is the 4th argument
148
+ (an `InterceptConfig` object); the other use-items go in the 5th-argument
149
+ callback.
74
150
 
75
151
  ```typescript
76
152
  intercept(
77
153
  "@modal",
78
154
  "product",
79
155
  <ProductModal />,
156
+ // Only intercept when coming from a different section
157
+ { when: ({ from }) => !from.pathname.startsWith("/shop/product/") },
158
+ () => [
159
+ loader(ProductLoader),
160
+ ]
161
+ )
162
+ ```
163
+
164
+ `when` is a match-time selector receiving `{ from, to, params, segments, ... }`.
165
+ Pass an array of predicates for AND logic (all must return true). Omit `when`
166
+ entirely and the intercept always activates.
167
+
168
+ ```typescript
169
+ intercept(
170
+ "@modal",
171
+ "product",
172
+ <ProductModal />,
173
+ {
174
+ when: [
175
+ ({ from }) => from.pathname.startsWith("/shop"),
176
+ ({ params }) => params.slug !== "featured",
177
+ ],
178
+ },
80
179
  () => [
81
- // Only intercept when coming from a different section
82
- when(({ from }) => !from.pathname.startsWith("/shop/product/")),
83
180
  loader(ProductLoader),
84
181
  ]
85
182
  )
@@ -106,15 +203,15 @@ Use navigation to close:
106
203
 
107
204
  ```typescript
108
205
  "use client";
109
- import { useNavigation } from "@rangojs/router/client";
206
+ import { useRouter } from "@rangojs/router/client";
110
207
 
111
208
  function ModalWrapper({ children }) {
112
- const { goBack } = useNavigation();
209
+ const router = useRouter();
113
210
 
114
211
  return (
115
- <div className="modal-overlay" onClick={goBack}>
212
+ <div className="modal-overlay" onClick={() => router.back()}>
116
213
  <div className="modal" onClick={(e) => e.stopPropagation()}>
117
- <button onClick={goBack}>Close</button>
214
+ <button onClick={() => router.back()}>Close</button>
118
215
  {children}
119
216
  </div>
120
217
  </div>
@@ -122,6 +219,82 @@ function ModalWrapper({ children }) {
122
219
  }
123
220
  ```
124
221
 
222
+ ## Interaction with View Transitions
223
+
224
+ A layout that owns the `@modal` slot can also configure `transition()` for page
225
+ fades — opening a modal does **not** fire the layout's view transition. Rango
226
+ narrows the layout's `<ViewTransition>` wrap to the layout's default outlet
227
+ content, so `<ParallelOutlet />` (the slot where the modal mounts) is a sibling
228
+ of the wrap, not inside its subtree. Form actions submitted from inside an open
229
+ modal also commit without firing the underlying layout's transition, and the
230
+ modal subtree identity is preserved across revalidation (no remount,
231
+ `useActionState` survives). Closing the modal restores the page without a
232
+ stray transition.
233
+
234
+ For a modal-only morph (e.g. when intercepted URLs change while the modal
235
+ stays open), use an element-level React `<ViewTransition>` inside the modal
236
+ component — `transition()` accepted on `intercept()` via the DSL is not
237
+ applied to slot rendering today.
238
+
239
+ Caveat: route-level `transition()` wraps the route component itself, so a
240
+ `<ParallelOutlet />` rendered directly inside that route component would still
241
+ be inside the route's VT subtree. Mount the slot in a layout instead when you
242
+ combine intercept modals with route-level transitions.
243
+
244
+ See [skills/view-transitions](../view-transitions/SKILL.md) for the full
245
+ contract and direction-aware examples.
246
+
247
+ ## Interaction with Prerender
248
+
249
+ When the target route of an intercept uses `Prerender`, the intercept handler is
250
+ also resolved at build time and stored alongside the main pre-rendered segments.
251
+ This means intercept navigations to pre-rendered routes are served from the
252
+ prerender store without executing handler code at runtime.
253
+
254
+ ```typescript
255
+ // The detail route is pre-rendered
256
+ export const ProductDetail = Prerender(
257
+ async () => [{ slug: "shoes" }, { slug: "jacket" }],
258
+ async (ctx) => <ProductPage slug={ctx.params.slug} />,
259
+ );
260
+
261
+ // urls.tsx
262
+ layout(ShopLayout, () => [
263
+ path("/:slug", ProductDetail, { name: "detail" }, () => [
264
+ loader(ProductLoader),
265
+ ]),
266
+
267
+ // This intercept is also pre-rendered at build time
268
+ intercept(
269
+ "@modal",
270
+ ".detail",
271
+ <ProductModal />,
272
+ { when: ({ from }) => from.pathname.startsWith("/shop") },
273
+ () => [loader(ProductLoader)],
274
+ ),
275
+ ])
276
+ ```
277
+
278
+ Build-time behavior:
279
+
280
+ - The intercept handler (`<ProductModal />`) is resolved with BuildContext
281
+ - Result is stored under the key `"detail/paramHash/i"` (intercept variant)
282
+ - `when` config conditions are skipped at build time (all intercepts pre-rendered unconditionally)
283
+ - `when` is still evaluated at runtime by the intercept-resolution middleware
284
+
285
+ Runtime behavior:
286
+
287
+ - Intercept navigation: prerender store serves the `/i` variant (frozen handler + fresh loaders)
288
+ - Direct navigation: prerender store serves the main variant (full page)
289
+ - If no intercept prerender entry exists, falls through to live intercept resolution
290
+
291
+ Loaders inside the intercept always run fresh at request time, same as regular
292
+ pre-rendered routes.
293
+
294
+ During action-driven partial revalidation, this same partial rule applies:
295
+ refreshing the intercept does not implicitly rebuild non-revalidated outer
296
+ segments.
297
+
125
298
  ## Complete Example
126
299
 
127
300
  ```typescript
@@ -158,7 +331,6 @@ export const shopPatterns = urls(({
158
331
  intercept,
159
332
  loader,
160
333
  loading,
161
- when,
162
334
  }) => [
163
335
  layout(<ShopLayout />, () => [
164
336
  parallel({
@@ -170,8 +342,8 @@ export const shopPatterns = urls(({
170
342
  "@modal",
171
343
  "product", // Route name (without prefix)
172
344
  <ProductModalContent />,
345
+ { when: ({ from }) => !from.pathname.startsWith("/shop/product/") },
173
346
  () => [
174
- when(({ from }) => !from.pathname.startsWith("/shop/product/")),
175
347
  layout(<ModalWrapper />),
176
348
  loading(<ProductModalSkeleton />),
177
349
  loader(ProductLoader, () => [cache()]),
@@ -188,3 +360,23 @@ export const shopPatterns = urls(({
188
360
  ]),
189
361
  ]);
190
362
  ```
363
+
364
+ ## Handler-attached `.use`
365
+
366
+ Intercept handlers can carry their own middleware, loaders, loading state, error/notFound boundaries, and even nested `layout`/`route` defaults via `.use` — useful for self-contained modal components that travel with their own data and chrome. (Conditional activation is set via the `when` config on the mount-site `intercept()` call, not inside `.use`.)
367
+
368
+ ```typescript
369
+ const QuickViewModal: Handler = async (ctx) => {
370
+ const product = await ctx.use(ProductLoader);
371
+ return <QuickView product={product} />;
372
+ };
373
+ QuickViewModal.use = () => [
374
+ loader(ProductLoader),
375
+ loading(<QuickViewSkeleton />),
376
+ layout(<ModalChrome />),
377
+ ];
378
+
379
+ intercept("@modal", "product", QuickViewModal);
380
+ ```
381
+
382
+ Explicit `use()` at the mount site merges with `handler.use` (handler defaults first, explicit second). See [skills/handler-use](../handler-use/SKILL.md) for merge order and the per-mount-site allowed-types table.
@@ -45,9 +45,7 @@ layout(<ShopLayout />, () => [
45
45
  ### Component Function
46
46
 
47
47
  ```typescript
48
- layout(ShopLayout, () => [
49
- path("/shop", ShopIndex, { name: "shop" }),
50
- ])
48
+ layout(ShopLayout, () => [path("/shop", ShopIndex, { name: "shop" })]);
51
49
  ```
52
50
 
53
51
  ### Handler with Context
@@ -117,6 +115,8 @@ function ShopLayout() {
117
115
  }
118
116
  ```
119
117
 
118
+ A layout's `transition()` config wraps the content that flows through `<Outlet />` — not the layout chrome itself, and not sibling `<ParallelOutlet />` slots. Stacking transitions across nested layouts collapses around the deepest default outlet content. See [skills/view-transitions](../view-transitions/SKILL.md) for the full wrap rules and intercept-modal interaction.
119
+
120
120
  ## Named Outlets
121
121
 
122
122
  For parallel routes, use named outlets:
@@ -141,9 +141,69 @@ function DashboardLayout() {
141
141
  }
142
142
  ```
143
143
 
144
+ ## Orphan Layout (inside route)
145
+
146
+ A layout as a child of `path()` wraps the route content and can read
147
+ data set by the route handler via `ctx.get()`. The handler always
148
+ executes before its children.
149
+
150
+ This is the recommended way to pass handler data downward, and it is
151
+ safe under partial action revalidation with zero configuration: orphan
152
+ layouts (and their parallels) belong to the route entry, and on an
153
+ action the whole entry re-runs together by default — route segment,
154
+ loaders, and `belongsToRoute` children all seed revalidate-true, with
155
+ handler-first ordering preserved. Producer and consumer cannot desync
156
+ unless you narrow one side with a predicate that returns a hard `false`
157
+ (then put the same contract on both — see "Revalidation Contracts").
158
+
159
+ Data from an **outer** handler or layout entry is the opposite case:
160
+ outer entries do not revalidate on actions by default (parent-chain
161
+ skip). If an orphan layout depends on data established above its own
162
+ route entry, that outer segment must share a revalidation contract, or
163
+ the orphan must guard/reload the data independently. See `/rango` →
164
+ "Passing data down the tree" for the full safest-first ladder.
165
+
166
+ ```typescript
167
+ import { Outlet, ParallelOutlet } from "@rangojs/router/client";
168
+
169
+ urls(({ path, layout, parallel }) => [
170
+ path("/product/:slug", (ctx) => {
171
+ const product = await fetchProduct(ctx.params.slug);
172
+ ctx.set("product", product);
173
+ return <ProductPage product={product} />;
174
+ }, { name: "product" }, () => [
175
+ layout((ctx) => {
176
+ const product = ctx.get("product");
177
+ return (
178
+ <div>
179
+ <Breadcrumb name={product?.name} />
180
+ <Outlet />
181
+ <ParallelOutlet name="@related" />
182
+ </div>
183
+ );
184
+ }, () => [
185
+ parallel({
186
+ "@related": (ctx) => {
187
+ const product = ctx.get("product");
188
+ return <RelatedProducts category={product?.category} />;
189
+ },
190
+ }),
191
+ ]),
192
+ ]),
193
+ ])
194
+ ```
195
+
196
+ Orphan layouts can call `ctx.get()` to read data set by their parent
197
+ handler. They can also call `ctx.set()`, though the primary pattern is
198
+ for route handlers and middleware to write context variables and for
199
+ orphan layouts to read them.
200
+
144
201
  ## Layout Revalidation
145
202
 
146
- Layouts don't revalidate by default. Control with `revalidate()`:
203
+ Standalone `layout()` entries don't revalidate by default — on an action,
204
+ parent-chain segments are skipped unless a `revalidate()` opts them in.
205
+ (Orphan layouts inside a `path()` are the opposite: they ride along with
206
+ the route entry by default.) Control with `revalidate()`:
147
207
 
148
208
  ```typescript
149
209
  layout(<ShopLayout />, () => [
@@ -154,18 +214,76 @@ layout(<ShopLayout />, () => [
154
214
  ])
155
215
 
156
216
  // Or revalidate based on conditions
217
+ import * as CartActions from "./actions/cart";
218
+
157
219
  layout(<CartLayout />, () => [
158
- revalidate(({ actionId }) => actionId?.includes("Cart") ?? false),
220
+ revalidate((ctx) => ctx.isAction(CartActions) || undefined),
159
221
 
160
222
  path("/cart", CartPage, { name: "cart" }),
161
223
  ])
162
224
  ```
163
225
 
226
+ If child segments read data that was established by this layout or by a
227
+ route handler above them, revalidate the outer segment too. Partial
228
+ revalidation does not re-run non-revalidated ancestors just to rebuild
229
+ their `ctx.set()` state.
230
+
231
+ ### Revalidation Contracts
232
+
233
+ Contracts are the tool for cross-entry sharing — the bottom rung of the
234
+ data-passing ladder (`/rango` → "Passing data down the tree"). Before
235
+ writing one, check whether the producer can move down a rung: into the
236
+ consumer's own entry as an orphan layout, into middleware, or into a
237
+ loader. When the data genuinely must flow from an outer entry, define
238
+ named revalidation functions and reuse them on both producer and
239
+ consumer segments:
240
+
241
+ ```typescript
242
+ // revalidation-contracts.ts
243
+ import { addToCart } from "./actions/cart";
244
+
245
+ export const revalidateCartData = (ctx) => ctx.isAction(addToCart) || undefined;
246
+ ```
247
+
248
+ ```typescript
249
+ layout(<CartLayout />, () => [
250
+ revalidate(revalidateCartData), // producer
251
+ path("/cart", CartPage, { name: "cart" }, () => [
252
+ revalidate(revalidateCartData), // consumer
253
+ ]),
254
+ ]);
255
+ ```
256
+
257
+ If a segment depends on multiple upstream domains, compose multiple
258
+ contracts (`revalidateAuthData`, `revalidateCartData`, and so on).
259
+
260
+ You can also package them as importable handoff helpers:
261
+
262
+ ```typescript
263
+ // revalidation-contracts.ts
264
+ import { revalidate } from "@rangojs/router";
265
+ import * as AuthActions from "./actions/auth";
266
+
267
+ export const revalidateAuthData = (ctx) =>
268
+ ctx.isAction(AuthActions) || undefined;
269
+ export const revalidateAuth = () => [revalidate(revalidateAuthData)];
270
+ ```
271
+
272
+ ```typescript
273
+ layout(<ShellLayout />, () => [
274
+ revalidateAuth(),
275
+ path("/account", AccountPage, { name: "account" }, () => [
276
+ revalidateAuth(),
277
+ ]),
278
+ ]);
279
+ ```
280
+
164
281
  ## Complete Example
165
282
 
166
283
  ```typescript
167
284
  import { urls } from "@rangojs/router";
168
285
  import { Outlet, ParallelOutlet } from "@rangojs/router/client";
286
+ import * as CartActions from "./actions/cart";
169
287
 
170
288
  function ShopLayout() {
171
289
  return (
@@ -195,7 +313,7 @@ export const shopPatterns = urls(({ path, layout, parallel, loader, revalidate }
195
313
  }, () => [
196
314
  // Layout loaders
197
315
  loader(CartLoader, () => [
198
- revalidate(({ actionId }) => actionId?.includes("Cart") ?? false),
316
+ revalidate((ctx) => ctx.isAction(CartActions) || undefined),
199
317
  ]),
200
318
 
201
319
  // Parallel routes
@@ -211,3 +329,25 @@ export const shopPatterns = urls(({ path, layout, parallel, loader, revalidate }
211
329
  ]),
212
330
  ]);
213
331
  ```
332
+
333
+ ## Handler-attached `.use`
334
+
335
+ Layout handlers can carry their own middleware, default parallels, and includes via `.use` so a layout becomes a self-contained unit reusable across mount sites.
336
+
337
+ ```typescript
338
+ const AdminLayout: Handler = (ctx) => {
339
+ const user = ctx.get(CurrentUser);
340
+ return <Admin user={user} />;
341
+ };
342
+ AdminLayout.use = () => [
343
+ middleware(requireAdmin),
344
+ parallel({ "@adminNotifs": AdminNotifsSlot }),
345
+ ];
346
+
347
+ // Mount site declares structure only; defaults travel with the layout.
348
+ layout(AdminLayout, () => [
349
+ path("/admin", AdminIndex, { name: "admin.index" }),
350
+ ]);
351
+ ```
352
+
353
+ Allowed item types in a layout's `.use` mirror the layout `use()` callback (the broadest set). Explicit `use()` at the mount site merges with `handler.use` (handler defaults first, explicit second). See [skills/handler-use](../handler-use/SKILL.md) for merge order and per-mount-site allowed types.