@rangojs/router 0.0.0-experimental.79 → 0.0.0-experimental.7c7e4327

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 (440) hide show
  1. package/AGENTS.md +8 -4
  2. package/README.md +301 -797
  3. package/dist/bin/rango.js +603 -145
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +3750 -1160
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +96 -24
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +85 -6
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +228 -33
  12. package/skills/caching/SKILL.md +336 -19
  13. package/skills/catalog.json +271 -0
  14. package/skills/comparison/SKILL.md +50 -0
  15. package/skills/comparison/agents/openai.yaml +4 -0
  16. package/skills/comparison/references/framework-comparison.md +837 -0
  17. package/skills/composability/SKILL.md +110 -4
  18. package/skills/css/SKILL.md +76 -0
  19. package/skills/debug-manifest/SKILL.md +5 -3
  20. package/skills/defer-hydration/SKILL.md +235 -0
  21. package/skills/document-cache/SKILL.md +87 -56
  22. package/skills/fonts/SKILL.md +1 -1
  23. package/skills/handler-use/SKILL.md +12 -10
  24. package/skills/hooks/SKILL.md +73 -691
  25. package/skills/hooks/data.md +273 -0
  26. package/skills/hooks/handle-and-actions.md +103 -0
  27. package/skills/hooks/navigation.md +110 -0
  28. package/skills/hooks/outlets.md +41 -0
  29. package/skills/hooks/state.md +228 -0
  30. package/skills/hooks/urls.md +135 -0
  31. package/skills/host-router/SKILL.md +129 -27
  32. package/skills/i18n/SKILL.md +276 -0
  33. package/skills/intercept/SKILL.md +75 -19
  34. package/skills/layout/SKILL.md +40 -19
  35. package/skills/links/SKILL.md +247 -17
  36. package/skills/loader/SKILL.md +248 -10
  37. package/skills/middleware/SKILL.md +25 -13
  38. package/skills/migrate-nextjs/SKILL.md +205 -20
  39. package/skills/migrate-react-router/SKILL.md +59 -670
  40. package/skills/migrate-react-router/cloudflare-workers.md +129 -0
  41. package/skills/migrate-react-router/component-migration.md +196 -0
  42. package/skills/migrate-react-router/data-and-actions.md +225 -0
  43. package/skills/migrate-react-router/route-mapping.md +271 -0
  44. package/skills/mime-routes/SKILL.md +29 -2
  45. package/skills/observability/SKILL.md +202 -0
  46. package/skills/parallel/SKILL.md +40 -10
  47. package/skills/ppr/SKILL.md +616 -0
  48. package/skills/prerender/SKILL.md +72 -60
  49. package/skills/rango/SKILL.md +318 -26
  50. package/skills/react-compiler/SKILL.md +168 -0
  51. package/skills/response-routes/SKILL.md +138 -49
  52. package/skills/route/SKILL.md +117 -9
  53. package/skills/router-setup/SKILL.md +44 -9
  54. package/skills/scripts/SKILL.md +179 -0
  55. package/skills/server-actions/SKILL.md +776 -0
  56. package/skills/shell-manifest/SKILL.md +185 -0
  57. package/skills/streams-and-websockets/SKILL.md +283 -0
  58. package/skills/tailwind/SKILL.md +28 -4
  59. package/skills/testing/SKILL.md +130 -0
  60. package/skills/testing/bindings.md +103 -0
  61. package/skills/testing/cache-prerender.md +127 -0
  62. package/skills/testing/client-components.md +124 -0
  63. package/skills/testing/e2e-parity.md +125 -0
  64. package/skills/testing/flight.md +91 -0
  65. package/skills/testing/handles.md +131 -0
  66. package/skills/testing/loader.md +128 -0
  67. package/skills/testing/middleware.md +99 -0
  68. package/skills/testing/render-handler.md +122 -0
  69. package/skills/testing/response-routes.md +95 -0
  70. package/skills/testing/reverse-and-types.md +85 -0
  71. package/skills/testing/server-actions.md +107 -0
  72. package/skills/testing/server-tree.md +128 -0
  73. package/skills/testing/setup.md +123 -0
  74. package/skills/theme/SKILL.md +1 -1
  75. package/skills/typesafety/SKILL.md +45 -626
  76. package/skills/typesafety/env-and-bindings.md +254 -0
  77. package/skills/typesafety/generated-files-and-cli.md +335 -0
  78. package/skills/typesafety/params-and-search.md +153 -0
  79. package/skills/typesafety/route-types.md +209 -0
  80. package/skills/use-cache/SKILL.md +74 -15
  81. package/skills/vercel/SKILL.md +128 -0
  82. package/skills/view-transitions/SKILL.md +337 -0
  83. package/src/__augment-tests__/augment.ts +81 -0
  84. package/src/__augment-tests__/augmented.check.ts +116 -0
  85. package/src/__internal.ts +0 -65
  86. package/src/browser/action-coordinator.ts +53 -36
  87. package/src/browser/action-fence.ts +47 -0
  88. package/src/browser/app-shell.ts +39 -0
  89. package/src/browser/connection-warmup.ts +134 -0
  90. package/src/browser/cookie-name.ts +140 -0
  91. package/src/browser/event-controller.ts +252 -158
  92. package/src/browser/history-state.ts +21 -0
  93. package/src/browser/index.ts +3 -3
  94. package/src/browser/invalidate-client-cache.ts +52 -0
  95. package/src/browser/logging.ts +28 -0
  96. package/src/browser/merge-segment-loaders.ts +6 -4
  97. package/src/browser/navigation-bridge.ts +94 -25
  98. package/src/browser/navigation-client.ts +144 -79
  99. package/src/browser/navigation-store-handle.ts +38 -0
  100. package/src/browser/navigation-store.ts +161 -73
  101. package/src/browser/navigation-transaction.ts +9 -59
  102. package/src/browser/network-error-handler.ts +34 -7
  103. package/src/browser/partial-update.ts +183 -144
  104. package/src/browser/prefetch/cache.ts +242 -77
  105. package/src/browser/prefetch/fetch.ts +325 -69
  106. package/src/browser/prefetch/queue.ts +61 -12
  107. package/src/browser/rango-state.ts +158 -76
  108. package/src/browser/react/Link.tsx +58 -20
  109. package/src/browser/react/NavigationProvider.tsx +202 -120
  110. package/src/browser/react/ScrollRestoration.tsx +10 -6
  111. package/src/browser/react/filter-segment-order.ts +66 -7
  112. package/src/browser/react/index.ts +0 -48
  113. package/src/browser/react/location-state-shared.ts +178 -8
  114. package/src/browser/react/location-state.ts +39 -14
  115. package/src/browser/react/use-action.ts +6 -15
  116. package/src/browser/react/use-handle.ts +17 -14
  117. package/src/browser/react/use-href.tsx +8 -1
  118. package/src/browser/react/use-link-status.ts +33 -8
  119. package/src/browser/react/use-navigation.ts +32 -7
  120. package/src/browser/react/use-params.ts +20 -10
  121. package/src/browser/react/use-reverse.ts +106 -0
  122. package/src/browser/react/use-router.ts +25 -3
  123. package/src/browser/react/use-search-params.ts +0 -5
  124. package/src/browser/react/use-segments.ts +11 -21
  125. package/src/browser/response-adapter.ts +99 -8
  126. package/src/browser/rsc-router.tsx +145 -28
  127. package/src/browser/scroll-restoration.ts +37 -22
  128. package/src/browser/segment-reconciler.ts +31 -21
  129. package/src/browser/segment-structure-assert.ts +2 -2
  130. package/src/browser/server-action-bridge.ts +236 -65
  131. package/src/browser/types.ts +102 -9
  132. package/src/browser/validate-redirect-origin.ts +43 -16
  133. package/src/build/collect-fallback-refs.ts +107 -0
  134. package/src/build/generate-manifest.ts +203 -154
  135. package/src/build/generate-route-types.ts +3 -1
  136. package/src/build/index.ts +11 -3
  137. package/src/build/prefix-tree-utils.ts +123 -0
  138. package/src/build/route-trie.ts +152 -21
  139. package/src/build/route-types/ast-route-extraction.ts +15 -8
  140. package/src/build/route-types/codegen.ts +16 -5
  141. package/src/build/route-types/include-resolution.ts +456 -62
  142. package/src/build/route-types/param-extraction.ts +6 -3
  143. package/src/build/route-types/per-module-writer.ts +22 -6
  144. package/src/build/route-types/router-processing.ts +128 -51
  145. package/src/build/route-types/scan-filter.ts +1 -1
  146. package/src/build/route-types/source-scan.ts +216 -0
  147. package/src/build/runtime-discovery.ts +13 -21
  148. package/src/cache/cache-error.ts +104 -0
  149. package/src/cache/cache-key-utils.ts +58 -13
  150. package/src/cache/cache-policy.ts +108 -34
  151. package/src/cache/cache-runtime.ts +421 -58
  152. package/src/cache/cache-scope.ts +187 -96
  153. package/src/cache/cache-tag.ts +149 -0
  154. package/src/cache/cf/cf-base64.ts +33 -0
  155. package/src/cache/cf/cf-cache-constants.ts +127 -0
  156. package/src/cache/cf/cf-cache-store.ts +2202 -372
  157. package/src/cache/cf/cf-cache-types.ts +349 -0
  158. package/src/cache/cf/cf-kv-utils.ts +46 -0
  159. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  160. package/src/cache/cf/index.ts +6 -16
  161. package/src/cache/document-cache.ts +126 -41
  162. package/src/cache/handle-snapshot.ts +70 -0
  163. package/src/cache/index.ts +23 -20
  164. package/src/cache/memory-segment-store.ts +243 -37
  165. package/src/cache/profile-registry.ts +46 -31
  166. package/src/cache/read-through-swr.ts +56 -12
  167. package/src/cache/segment-codec.ts +13 -21
  168. package/src/cache/shell-snapshot.ts +417 -0
  169. package/src/cache/tag-invalidation.ts +230 -0
  170. package/src/cache/types.ts +180 -99
  171. package/src/cache/vercel/index.ts +11 -0
  172. package/src/cache/vercel/vercel-cache-store.ts +1127 -0
  173. package/src/client.rsc.tsx +41 -21
  174. package/src/client.tsx +33 -61
  175. package/src/cloudflare/index.ts +11 -0
  176. package/src/cloudflare/tracing.ts +108 -0
  177. package/src/component-utils.ts +19 -0
  178. package/src/components/DefaultDocument.tsx +8 -2
  179. package/src/context-var.ts +18 -6
  180. package/src/decode-loader-results.ts +52 -0
  181. package/src/defer.ts +185 -0
  182. package/src/deps/ssr.ts +0 -1
  183. package/src/encode-kv.ts +49 -0
  184. package/src/errors.ts +30 -4
  185. package/src/escape-script.ts +52 -0
  186. package/src/handle.ts +67 -37
  187. package/src/handles/MetaTags.tsx +24 -53
  188. package/src/handles/Scripts.tsx +183 -0
  189. package/src/handles/breadcrumbs.ts +35 -8
  190. package/src/handles/deferred-resolution.ts +127 -0
  191. package/src/handles/is-thenable.ts +18 -0
  192. package/src/handles/meta.ts +14 -40
  193. package/src/handles/script.ts +244 -0
  194. package/src/host/cookie-handler.ts +9 -60
  195. package/src/host/errors.ts +13 -22
  196. package/src/host/index.ts +9 -2
  197. package/src/host/pattern-matcher.ts +23 -52
  198. package/src/host/router.ts +107 -99
  199. package/src/host/testing.ts +40 -27
  200. package/src/host/types.ts +37 -4
  201. package/src/host/utils.ts +1 -1
  202. package/src/href-client.ts +137 -22
  203. package/src/index.rsc.ts +97 -12
  204. package/src/index.ts +98 -14
  205. package/src/internal-debug.ts +11 -10
  206. package/src/loader-store.ts +500 -0
  207. package/src/loader.rsc.ts +20 -13
  208. package/src/loader.ts +12 -11
  209. package/src/missing-id-error.ts +68 -0
  210. package/src/outlet-context.ts +1 -1
  211. package/src/outlet-provider.tsx +1 -5
  212. package/src/prerender/param-hash.ts +16 -16
  213. package/src/prerender/store.ts +32 -37
  214. package/src/prerender.ts +78 -10
  215. package/src/redirect-origin.ts +114 -0
  216. package/src/regex-escape.ts +8 -0
  217. package/src/render-error-thrower.tsx +20 -0
  218. package/src/response-utils.ts +62 -0
  219. package/src/reverse.ts +65 -39
  220. package/src/root-error-boundary.tsx +1 -19
  221. package/src/route-content-wrapper.tsx +19 -77
  222. package/src/route-definition/dsl-helpers.ts +304 -309
  223. package/src/route-definition/helper-factories.ts +28 -140
  224. package/src/route-definition/helpers-types.ts +87 -59
  225. package/src/route-definition/index.ts +1 -2
  226. package/src/route-definition/redirect.ts +44 -11
  227. package/src/route-definition/resolve-handler-use.ts +12 -1
  228. package/src/route-definition/use-item-types.ts +29 -0
  229. package/src/route-map-builder.ts +41 -20
  230. package/src/route-types.ts +19 -46
  231. package/src/router/basename.ts +14 -0
  232. package/src/router/content-negotiation.ts +73 -25
  233. package/src/router/error-handling.ts +45 -18
  234. package/src/router/find-match.ts +129 -30
  235. package/src/router/handler-context.ts +27 -42
  236. package/src/router/instrument.ts +355 -0
  237. package/src/router/intercept-resolution.ts +39 -20
  238. package/src/router/lazy-includes.ts +82 -59
  239. package/src/router/loader-resolution.ts +167 -72
  240. package/src/router/logging.ts +0 -6
  241. package/src/router/manifest.ts +74 -40
  242. package/src/router/match-api.ts +80 -55
  243. package/src/router/match-context.ts +0 -22
  244. package/src/router/match-handlers.ts +211 -165
  245. package/src/router/match-middleware/background-revalidation.ts +40 -24
  246. package/src/router/match-middleware/cache-lookup.ts +159 -285
  247. package/src/router/match-middleware/cache-store.ts +64 -52
  248. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  249. package/src/router/match-middleware/segment-resolution.ts +0 -22
  250. package/src/router/match-pipelines.ts +1 -42
  251. package/src/router/match-result.ts +69 -79
  252. package/src/router/metrics.ts +0 -34
  253. package/src/router/middleware-types.ts +7 -134
  254. package/src/router/middleware.ts +298 -172
  255. package/src/router/navigation-snapshot.ts +7 -56
  256. package/src/router/params-util.ts +23 -0
  257. package/src/router/parse-pattern.ts +115 -0
  258. package/src/router/pattern-matching.ts +181 -150
  259. package/src/router/prefetch-cache-ttl.ts +51 -0
  260. package/src/router/prefetch-limits.ts +37 -0
  261. package/src/router/prerender-match.ts +112 -67
  262. package/src/router/preview-match.ts +6 -2
  263. package/src/router/request-classification.ts +50 -69
  264. package/src/router/revalidation.ts +123 -73
  265. package/src/router/route-snapshot.ts +14 -3
  266. package/src/router/router-context.ts +6 -29
  267. package/src/router/router-interfaces.ts +115 -36
  268. package/src/router/router-options.ts +166 -5
  269. package/src/router/router-registry.ts +2 -5
  270. package/src/router/segment-resolution/fresh.ts +131 -86
  271. package/src/router/segment-resolution/helpers.ts +86 -6
  272. package/src/router/segment-resolution/loader-cache.ts +139 -39
  273. package/src/router/segment-resolution/loader-mask.ts +67 -0
  274. package/src/router/segment-resolution/loader-snapshot.ts +251 -0
  275. package/src/router/segment-resolution/revalidation.ts +272 -320
  276. package/src/router/segment-resolution/static-store.ts +19 -5
  277. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  278. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  279. package/src/router/segment-resolution.ts +5 -1
  280. package/src/router/segment-wrappers.ts +6 -5
  281. package/src/router/state-cookie-name.ts +33 -0
  282. package/src/router/substitute-pattern-params.ts +75 -0
  283. package/src/router/telemetry-otel.ts +160 -200
  284. package/src/router/telemetry.ts +105 -20
  285. package/src/router/timeout.ts +0 -20
  286. package/src/router/tracing.ts +215 -0
  287. package/src/router/trie-matching.ts +171 -59
  288. package/src/router/types.ts +9 -63
  289. package/src/router/url-params.ts +57 -0
  290. package/src/router.ts +157 -71
  291. package/src/rsc/full-payload.ts +70 -0
  292. package/src/rsc/handler-context.ts +3 -2
  293. package/src/rsc/handler.ts +291 -217
  294. package/src/rsc/helpers.ts +168 -46
  295. package/src/rsc/index.ts +2 -5
  296. package/src/rsc/json-route-result.ts +38 -0
  297. package/src/rsc/loader-fetch.ts +114 -38
  298. package/src/rsc/manifest-init.ts +29 -42
  299. package/src/rsc/nonce.ts +10 -1
  300. package/src/rsc/origin-guard.ts +39 -25
  301. package/src/rsc/progressive-enhancement.ts +124 -13
  302. package/src/rsc/redirect-guard.ts +100 -0
  303. package/src/rsc/response-cache-serve.ts +238 -0
  304. package/src/rsc/response-error.ts +79 -12
  305. package/src/rsc/response-route-handler.ts +99 -189
  306. package/src/rsc/rsc-rendering.ts +421 -76
  307. package/src/rsc/runtime-warnings.ts +23 -10
  308. package/src/rsc/server-action.ts +282 -116
  309. package/src/rsc/shell-capture.ts +1158 -0
  310. package/src/rsc/shell-serve.ts +150 -0
  311. package/src/rsc/ssr-setup.ts +16 -0
  312. package/src/rsc/transition-gate.ts +89 -0
  313. package/src/rsc/types.ts +53 -5
  314. package/src/runtime-env.ts +18 -0
  315. package/src/search-params.ts +35 -30
  316. package/src/segment-loader-promise.ts +49 -4
  317. package/src/segment-system.tsx +350 -149
  318. package/src/serialize.ts +243 -0
  319. package/src/server/context.ts +208 -51
  320. package/src/server/cookie-parse.ts +32 -0
  321. package/src/server/cookie-store.ts +152 -5
  322. package/src/server/handle-store.ts +21 -38
  323. package/src/server/loader-registry.ts +33 -42
  324. package/src/server/request-context.ts +395 -176
  325. package/src/ssr/index.tsx +458 -178
  326. package/src/ssr/ssr-root.tsx +228 -0
  327. package/src/static-handler.ts +10 -13
  328. package/src/testing/cache-status.ts +162 -0
  329. package/src/testing/collect-handle.ts +46 -0
  330. package/src/testing/dispatch.ts +813 -0
  331. package/src/testing/dom.entry.ts +22 -0
  332. package/src/testing/e2e/fixture.ts +188 -0
  333. package/src/testing/e2e/index.ts +128 -0
  334. package/src/testing/e2e/matchers.ts +35 -0
  335. package/src/testing/e2e/page-helpers.ts +272 -0
  336. package/src/testing/e2e/parity.ts +387 -0
  337. package/src/testing/e2e/server.ts +195 -0
  338. package/src/testing/flight-matchers.ts +97 -0
  339. package/src/testing/flight-normalize.ts +11 -0
  340. package/src/testing/flight-runtime.d.ts +57 -0
  341. package/src/testing/flight-tree.ts +682 -0
  342. package/src/testing/flight.entry.ts +52 -0
  343. package/src/testing/flight.ts +257 -0
  344. package/src/testing/generated-routes.ts +199 -0
  345. package/src/testing/index.ts +105 -0
  346. package/src/testing/internal/context.ts +371 -0
  347. package/src/testing/internal/flight-client-globals.ts +30 -0
  348. package/src/testing/internal/seed-vars.ts +54 -0
  349. package/src/testing/render-handler.ts +357 -0
  350. package/src/testing/render-route.tsx +584 -0
  351. package/src/testing/run-loader.ts +385 -0
  352. package/src/testing/run-middleware.ts +205 -0
  353. package/src/testing/run-transition-when.ts +164 -0
  354. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  355. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  356. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  357. package/src/testing/vitest-stubs/version.ts +5 -0
  358. package/src/testing/vitest.ts +305 -0
  359. package/src/theme/ThemeProvider.tsx +56 -84
  360. package/src/theme/ThemeScript.tsx +7 -9
  361. package/src/theme/constants.ts +52 -13
  362. package/src/theme/index.ts +0 -7
  363. package/src/theme/theme-context.ts +1 -5
  364. package/src/theme/theme-script.ts +22 -21
  365. package/src/theme/use-theme.ts +0 -3
  366. package/src/types/boundaries.ts +0 -35
  367. package/src/types/cache-types.ts +13 -4
  368. package/src/types/error-types.ts +30 -90
  369. package/src/types/global-namespace.ts +54 -41
  370. package/src/types/handler-context.ts +110 -62
  371. package/src/types/index.ts +3 -10
  372. package/src/types/loader-types.ts +11 -9
  373. package/src/types/request-scope.ts +112 -0
  374. package/src/types/route-config.ts +20 -52
  375. package/src/types/route-entry.ts +0 -6
  376. package/src/types/segments.ts +135 -14
  377. package/src/urls/include-helper.ts +19 -64
  378. package/src/urls/include-provider.ts +71 -0
  379. package/src/urls/index.ts +2 -11
  380. package/src/urls/path-helper-types.ts +63 -17
  381. package/src/urls/path-helper.ts +22 -106
  382. package/src/urls/pattern-types.ts +72 -19
  383. package/src/urls/response-types.ts +22 -29
  384. package/src/urls/type-extraction.ts +98 -154
  385. package/src/urls/urls-function.ts +1 -19
  386. package/src/use-loader.tsx +292 -107
  387. package/src/vercel/index.ts +11 -0
  388. package/src/vercel/tracing.ts +88 -0
  389. package/src/vite/debug.ts +185 -0
  390. package/src/vite/discovery/bundle-postprocess.ts +8 -7
  391. package/src/vite/discovery/dev-prerender-cache.ts +117 -0
  392. package/src/vite/discovery/discover-routers.ts +127 -86
  393. package/src/vite/discovery/discovery-errors.ts +255 -0
  394. package/src/vite/discovery/gate-state.ts +171 -0
  395. package/src/vite/discovery/prerender-collection.ts +96 -68
  396. package/src/vite/discovery/route-types-writer.ts +40 -84
  397. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  398. package/src/vite/discovery/state.ts +45 -1
  399. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  400. package/src/vite/index.ts +4 -0
  401. package/src/vite/inject-client-debug.ts +88 -0
  402. package/src/vite/plugin-types.ts +210 -10
  403. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  404. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  405. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  406. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  407. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  408. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  409. package/src/vite/plugins/expose-action-id.ts +48 -95
  410. package/src/vite/plugins/expose-id-utils.ts +88 -55
  411. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  412. package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
  413. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  414. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  415. package/src/vite/plugins/expose-internal-ids.ts +505 -486
  416. package/src/vite/plugins/performance-tracks.ts +26 -25
  417. package/src/vite/plugins/refresh-cmd.ts +1 -1
  418. package/src/vite/plugins/use-cache-transform.ts +73 -83
  419. package/src/vite/plugins/vercel-output.ts +384 -0
  420. package/src/vite/plugins/version-injector.ts +40 -29
  421. package/src/vite/plugins/version-plugin.ts +37 -40
  422. package/src/vite/plugins/virtual-entries.ts +138 -27
  423. package/src/vite/rango.ts +236 -138
  424. package/src/vite/router-discovery.ts +927 -136
  425. package/src/vite/utils/ast-handler-extract.ts +26 -35
  426. package/src/vite/utils/banner.ts +1 -1
  427. package/src/vite/utils/bundle-analysis.ts +10 -15
  428. package/src/vite/utils/client-chunks.ts +184 -0
  429. package/src/vite/utils/directive-prologue.ts +40 -0
  430. package/src/vite/utils/forward-user-plugins.ts +171 -0
  431. package/src/vite/utils/manifest-utils.ts +4 -59
  432. package/src/vite/utils/package-resolution.ts +20 -52
  433. package/src/vite/utils/prerender-utils.ts +71 -43
  434. package/src/vite/utils/shared-utils.ts +142 -43
  435. package/src/browser/action-response-classifier.ts +0 -99
  436. package/src/browser/react/use-client-cache.ts +0 -58
  437. package/src/browser/shallow.ts +0 -40
  438. package/src/handles/index.ts +0 -7
  439. package/src/network-error-thrower.tsx +0 -23
  440. package/src/router/middleware-cookies.ts +0 -55
@@ -1,9 +1,9 @@
1
1
  // ============================================================================
2
- // Browser Module - Browser entry point for RSC Router
2
+ // Browser Module - Browser entry point for Rango
3
3
  // ============================================================================
4
4
  //
5
5
  // Usage:
6
- // import { initBrowserApp, RSCRouter } from "rsc-router/browser";
6
+ // import { initBrowserApp, Rango } from "rsc-router/browser";
7
7
  //
8
8
  // For React components (Link, useNavigation, etc.):
9
9
  // import { Link, useNavigation, useAction, href } from "rsc-router/client";
@@ -13,6 +13,6 @@
13
13
  // Browser app initialization
14
14
  export {
15
15
  initBrowserApp,
16
- RSCRouter,
16
+ Rango,
17
17
  type InitBrowserAppOptions,
18
18
  } from "./rsc-router.js";
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Client seat of `invalidateClientCache()` (the `default` export condition).
3
+ *
4
+ * Makes the current client behave as if a server action had just completed:
5
+ * the history cache is marked stale (SWR), the prefetch map is flushed, the
6
+ * state rotates, and sibling tabs are broadcast to — the same
7
+ * `markCacheAsStaleAndBroadcast()` path the server-action bridge uses. This is
8
+ * the gentler mark-stale (not hard-clear) behavior, so Back renders the cached
9
+ * entry instantly and revalidates.
10
+ */
11
+
12
+ import { getRegisteredStore } from "./navigation-store-handle.js";
13
+ import { clearPrefetchCache } from "./prefetch/cache.js";
14
+
15
+ export function invalidateClientCache(): void {
16
+ if (typeof document === "undefined") {
17
+ // SSR pass of a client component also resolves the default condition. A
18
+ // render-time call must not take down the page; no-op with a dev warning.
19
+ if (process.env.NODE_ENV !== "production") {
20
+ console.warn(
21
+ "[rango] invalidateClientCache() was called during a server render; " +
22
+ "it is a no-op outside the browser.",
23
+ );
24
+ }
25
+ return;
26
+ }
27
+
28
+ const store = getRegisteredStore();
29
+ if (store) {
30
+ store.markCacheAsStaleAndBroadcast();
31
+ return;
32
+ }
33
+
34
+ // Pre-boot: no store registered yet. clearPrefetchCache() (which rotates the
35
+ // state) is complete at this point — there is no history cache to mark and no
36
+ // sibling state worth broadcasting.
37
+ clearPrefetchCache();
38
+ }
39
+
40
+ /**
41
+ * Client no-op for `keepClientCache()`. It is a server action directive (the
42
+ * `react-server` condition sets a response header the action bridge reads);
43
+ * there is nothing to suppress from the client side.
44
+ */
45
+ export function keepClientCache(): void {
46
+ if (process.env.NODE_ENV !== "production") {
47
+ console.warn(
48
+ "[rango] keepClientCache() has no effect on the client; it is a server " +
49
+ "action directive. Call it from inside a server action.",
50
+ );
51
+ }
52
+ }
@@ -1,5 +1,15 @@
1
1
  import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
2
2
 
3
+ /**
4
+ * Module-level debug flag for guarding call sites whose debug arguments do
5
+ * non-trivial work (joins, maps, spreads, object literals). Because the Vite
6
+ * transform folds INTERNAL_RANGO_DEBUG to a literal, an `if (IS_BROWSER_DEBUG)`
7
+ * guard is minifier-DCE-able — the whole block drops from the production bundle.
8
+ * Prefer this over isBrowserDebugEnabled() at hot call sites: a const guard folds
9
+ * where a function call may not.
10
+ */
11
+ export const IS_BROWSER_DEBUG: boolean = INTERNAL_RANGO_DEBUG;
12
+
3
13
  interface BrowserLogContext {
4
14
  requestId: string;
5
15
  txId: string;
@@ -53,3 +63,21 @@ export function debugLog(msg: string, ...args: unknown[]): void {
53
63
  console.log(msg, ...args);
54
64
  }
55
65
  }
66
+
67
+ /**
68
+ * Boot-sequence debug log: one line per initial-document step (flight decode,
69
+ * handle stream, bridge wiring, initial tree build, hydration commit), each
70
+ * stamped with performance.now() so the gap BEFORE hydrateRoot is visible.
71
+ * The initial document path was otherwise silent — FE debug only started
72
+ * talking at the first soft navigation, so a boot stall (e.g. an await that
73
+ * holds initBrowserApp, and with it hydrateRoot) was invisible.
74
+ */
75
+ export function bootLog(step: string, details?: Record<string, unknown>): void {
76
+ if (!INTERNAL_RANGO_DEBUG) return;
77
+ const prefix = `[Browser][boot] ${step} @ ${Math.round(performance.now())}ms`;
78
+ if (details) {
79
+ console.log(prefix, details);
80
+ return;
81
+ }
82
+ console.log(prefix);
83
+ }
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedSegment } from "./types.js";
2
- import { debugLog } from "./logging.js";
2
+ import { debugLog, IS_BROWSER_DEBUG } from "./logging.js";
3
3
 
4
4
  /**
5
5
  * Merge partial loader data from server with cached loader data.
@@ -19,9 +19,11 @@ export function mergeSegmentLoaders(
19
19
  const serverLoaderIds = fromServer.loaderIds || [];
20
20
  const cachedLoaderIds = fromCache.loaderIds || [];
21
21
 
22
- debugLog(
23
- `[Browser] Merging partial loaders: server has ${serverLoaderIds.join(", ")}, cache has ${cachedLoaderIds.join(", ")}`,
24
- );
22
+ if (IS_BROWSER_DEBUG) {
23
+ debugLog(
24
+ `[Browser] Merging partial loaders: server has ${serverLoaderIds.join(", ")}, cache has ${cachedLoaderIds.join(", ")}`,
25
+ );
26
+ }
25
27
 
26
28
  return {
27
29
  ...fromCache,
@@ -5,13 +5,15 @@ import type {
5
5
  ResolvedSegment,
6
6
  } from "./types.js";
7
7
  import { setAppVersion } from "./app-version.js";
8
+ import { isActionFenceActive } from "./action-fence.js";
9
+ import { getRangoState } from "./rango-state.js";
8
10
  import * as React from "react";
9
11
  import { startTransition } from "react";
10
12
  import {
11
13
  createNavigationTransaction,
12
14
  resolveNavigationState,
13
15
  } from "./navigation-transaction.js";
14
- import { buildHistoryState } from "./history-state.js";
16
+ import { buildHistoryState, pushHistoryWithIdx } from "./history-state.js";
15
17
  import {
16
18
  handleNavigationStart,
17
19
  handleNavigationEnd,
@@ -30,6 +32,7 @@ import { isInterceptOnlyCache } from "./intercept-utils.js";
30
32
  import {
31
33
  toNetworkError,
32
34
  emitNetworkError,
35
+ emitNavigationError,
33
36
  isBackgroundSuppressible,
34
37
  } from "./network-error-handler.js";
35
38
  import { debugLog } from "./logging.js";
@@ -48,7 +51,7 @@ export { createNavigationTransaction };
48
51
  */
49
52
  export interface NavigationBridgeConfigWithController extends NavigationBridgeConfig {
50
53
  eventController: EventController;
51
- /** RSC version from initial payload metadata */
54
+ /** RSC version from initial payload metadata. */
52
55
  version?: string;
53
56
  }
54
57
 
@@ -159,11 +162,7 @@ export function createNavigationBridge(
159
162
  },
160
163
  {},
161
164
  );
162
- if (options.replace) {
163
- window.history.replaceState(historyState, "", url);
164
- } else {
165
- window.history.pushState(historyState, "", url);
166
- }
165
+ pushHistoryWithIdx(historyState, url, options?.replace ?? false);
167
166
 
168
167
  // Ensure new history entry has a scroll restoration key
169
168
  ensureHistoryKey();
@@ -217,17 +216,20 @@ export function createNavigationBridge(
217
216
  store.setInterceptSourceUrl(null);
218
217
  }
219
218
 
220
- // Before navigating away, update the source page's cache with the latest handleData.
221
- // This ensures the cache has correct handleData even if handles were streaming.
219
+ // Before navigating away, update the source page's cache with the latest
220
+ // handleData. This ensures the cache has correct handleData even if handles
221
+ // were streaming. Use updateCacheHandleData (not cacheSegmentsForHistory):
222
+ // the source page's segments are unchanged, so this is a handleData refresh,
223
+ // not a commit. Critically it PRESERVES the entry's stale flag — when the
224
+ // source page has a deferred Meta still pending, its entry was marked stale
225
+ // (invalidate-on-pending) so a popstate return revalidates; re-committing it
226
+ // here would reset stale to false and serve the carried (pre-resolution)
227
+ // title as fresh. It also leaves the nav-instance token intact.
222
228
  const sourceHistoryKey = store.getHistoryKey();
223
229
  const sourceCached = store.getCachedSegments(sourceHistoryKey);
224
230
  if (sourceCached?.segments && sourceCached.segments.length > 0) {
225
231
  const currentHandleData = eventController.getHandleState().data;
226
- store.cacheSegmentsForHistory(
227
- sourceHistoryKey,
228
- sourceCached.segments,
229
- currentHandleData,
230
- );
232
+ store.updateCacheHandleData(sourceHistoryKey, currentHandleData);
231
233
  }
232
234
 
233
235
  // Check if we have cached segments for target URL
@@ -327,8 +329,15 @@ export function createNavigationBridge(
327
329
  } as NavigateOptionsInternal);
328
330
  }
329
331
 
330
- if (error instanceof DOMException && error.name === "AbortError") {
331
- debugLog("[Browser] Navigation aborted by newer navigation");
332
+ // Aborted, or superseded by a newer navigation. A superseded nav may
333
+ // reject with a non-AbortError (e.g. a Flight decode that fails after its
334
+ // signal was aborted), so check the signal too -- otherwise we would
335
+ // render a boundary that clobbers the newer navigation's content.
336
+ if (
337
+ (error instanceof DOMException && error.name === "AbortError") ||
338
+ tx.handle.signal.aborted
339
+ ) {
340
+ debugLog("[Browser] Navigation aborted or superseded");
332
341
  return;
333
342
  }
334
343
 
@@ -345,7 +354,13 @@ export function createNavigationBridge(
345
354
  return;
346
355
  }
347
356
 
348
- throw error;
357
+ // A response we could not process (undecodable Flight body, or an
358
+ // unanticipated failure building the response). Surface the route's
359
+ // error boundary rather than let the rejection abort the navigation
360
+ // silently. Prefetched responses funnel here too: a failed warm-prefetch
361
+ // payload rejects on consumption and propagates to this catch.
362
+ console.error("[Browser] Unprocessable navigation response:", error);
363
+ emitNavigationError(onUpdate, error, url);
349
364
  } finally {
350
365
  tx[Symbol.dispose]();
351
366
  }
@@ -374,6 +389,14 @@ export function createNavigationBridge(
374
389
  tx.with({ url: window.location.href, replace: true, scroll: false }),
375
390
  );
376
391
  } catch (error) {
392
+ // Aborted or superseded: bail without rendering a boundary (see navigate()).
393
+ if (
394
+ (error instanceof DOMException && error.name === "AbortError") ||
395
+ tx.handle.signal.aborted
396
+ ) {
397
+ return;
398
+ }
399
+
377
400
  const networkError = toNetworkError(error, {
378
401
  url: window.location.href,
379
402
  operation: "revalidation",
@@ -386,7 +409,12 @@ export function createNavigationBridge(
386
409
  emitNetworkError(onUpdate, networkError, window.location.href);
387
410
  return;
388
411
  }
389
- throw error;
412
+
413
+ // refresh() shares the fetchPartialUpdate chokepoint with navigate()/
414
+ // popstate, so an unprocessable response must surface the error boundary
415
+ // here too rather than become an uncaught rejection.
416
+ console.error("[Browser] Unprocessable refresh response:", error);
417
+ emitNavigationError(onUpdate, error, window.location.href);
390
418
  } finally {
391
419
  tx[Symbol.dispose]();
392
420
  }
@@ -450,11 +478,22 @@ export function createNavigationBridge(
450
478
  // Helper to check if streaming is in progress
451
479
  const isStreaming = () => eventController.getState().isStreaming;
452
480
 
481
+ // Surface any external rotation of the rango state cookie (a server
482
+ // Set-Cookie, a sibling tab, a cookie clear) BEFORE reading the stale bit.
483
+ // The divergence observer only runs inside getRangoState() — fetch-time —
484
+ // so a popstate-first interaction would otherwise serve a pre-mutation
485
+ // page as fresh and never fetch to trigger the observer. Reading here lets
486
+ // the observer mark the history cache stale so getCachedSegments sees it.
487
+ getRangoState();
488
+
453
489
  // Check if we can restore from history cache
454
490
  const cached = store.getCachedSegments(historyKey);
455
491
  const cachedSegments = cached?.segments;
456
492
  const cachedHandleData = cached?.handleData;
457
- const isStale = cached?.stale ?? false;
493
+ // While an action is in flight the fence persists no stale flag, so OR it
494
+ // in here: a popstate during the flight serves the cached entry AND
495
+ // revalidates (SWR) instead of serving it as fresh.
496
+ const isStale = (cached?.stale ?? false) || isActionFenceActive();
458
497
 
459
498
  if (cachedSegments && cachedSegments.length > 0) {
460
499
  // Update store to point to this history entry
@@ -496,7 +535,14 @@ export function createNavigationBridge(
496
535
  },
497
536
  scroll: { restore: true, isStreaming },
498
537
  };
499
- const hasTransition = cachedSegments.some((s) => s.transition);
538
+ // Intercept-driven popstate (entering OR leaving an intercept) only
539
+ // mutates the parallel slot; the main outlet shows the same content.
540
+ // Skip startViewTransition in those cases — same rationale as the
541
+ // intercept guard in partial-update.ts's hasTransition computation.
542
+ const hasTransition =
543
+ !isIntercept &&
544
+ !isLeavingIntercept &&
545
+ cachedSegments.some((s) => s.transition);
500
546
  if (hasTransition) {
501
547
  startTransition(() => {
502
548
  if (addTransitionType) {
@@ -511,8 +557,19 @@ export function createNavigationBridge(
511
557
  // SWR: If stale, trigger background revalidation
512
558
  if (isStale) {
513
559
  debugLog("[Browser] Cache is stale, background revalidating...");
514
- // Background revalidation - don't await, just fire and forget
515
- const segmentIds = cachedSegments.map((s) => s.id);
560
+ // Background revalidation - don't await, just fire and forget.
561
+ // When the entry's handles are incomplete (a deferred Meta was still
562
+ // pending when the user navigated away — see handlesPending), send NO
563
+ // segment IDs so the server returns a FULL re-render with the handle
564
+ // stream. A normal stale revalidation sends the cached IDs and the
565
+ // server returns a diff-only payload that omits unchanged segments'
566
+ // handles, so a deferred Meta would never re-stream and the title
567
+ // would stay the pre-resolution carry. handlesPending is set only for
568
+ // the deferred-Meta-aborted case, so action/cross-tab SWR keeps the
569
+ // cheap diff path.
570
+ const segmentIds = cached?.handlesPending
571
+ ? []
572
+ : cachedSegments.map((s) => s.id);
516
573
 
517
574
  const tx = createNavigationTransaction(
518
575
  store,
@@ -586,8 +643,13 @@ export function createNavigationBridge(
586
643
  // Restore scroll position after fetch completes
587
644
  handleNavigationEnd({ restore: true, isStreaming });
588
645
  } catch (error) {
589
- if (error instanceof DOMException && error.name === "AbortError") {
590
- debugLog("[Browser] Popstate navigation aborted");
646
+ // Aborted or superseded by a newer navigation: bail without clobbering
647
+ // content with a boundary (see navigate()).
648
+ if (
649
+ (error instanceof DOMException && error.name === "AbortError") ||
650
+ tx.handle.signal.aborted
651
+ ) {
652
+ debugLog("[Browser] Popstate navigation aborted or superseded");
591
653
  return;
592
654
  }
593
655
 
@@ -604,7 +666,10 @@ export function createNavigationBridge(
604
666
  return;
605
667
  }
606
668
 
607
- throw error;
669
+ // Unprocessable response on a back/forward navigation: surface the
670
+ // error boundary instead of an uncaught rejection (see navigate()).
671
+ console.error("[Browser] Unprocessable popstate response:", error);
672
+ emitNavigationError(onUpdate, error, url);
608
673
  } finally {
609
674
  tx[Symbol.dispose]();
610
675
  }
@@ -659,6 +724,10 @@ export function createNavigationBridge(
659
724
  };
660
725
  },
661
726
 
727
+ getVersion(): string | undefined {
728
+ return version;
729
+ },
730
+
662
731
  updateVersion(newVersion: string): void {
663
732
  version = newVersion;
664
733
  setAppVersion(newVersion);