@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,93 @@
1
+ /**
2
+ * Built-in Breadcrumbs handle for accumulating breadcrumb items across route segments.
3
+ *
4
+ * Each layout/route pushes breadcrumb items via `ctx.use(Breadcrumbs)`.
5
+ * Items are collected in parent-to-child order with automatic deduplication
6
+ * by `href`: each href keeps its FIRST position but takes the LAST value, so a
7
+ * child re-pushing a parent href refreshes the label without reordering the trail.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // In route handler
12
+ * route("/blog/:slug", (ctx) => {
13
+ * const breadcrumb = ctx.use(Breadcrumbs);
14
+ * breadcrumb({ label: "Blog", href: "/blog" });
15
+ * breadcrumb({ label: post.title, href: `/blog/${ctx.params.slug}` });
16
+ * });
17
+ *
18
+ * // In client component (consume with useHandle)
19
+ * const crumbs = useHandle(Breadcrumbs);
20
+ * crumbs.map((c) => <a href={c.href}>{c.label}</a>);
21
+ * ```
22
+ */
23
+
24
+ import type { ReactNode } from "react";
25
+ import { createHandle, type Handle } from "../handle.js";
26
+
27
+ /**
28
+ * A single breadcrumb item.
29
+ *
30
+ * @property label - Display text for the breadcrumb
31
+ * @property href - URL the breadcrumb links to
32
+ * @property content - Optional extra content (sync or async) rendered alongside the label
33
+ */
34
+ export interface BreadcrumbItem {
35
+ label: string;
36
+ href: string;
37
+ content?: ReactNode | Promise<ReactNode>;
38
+ }
39
+
40
+ /**
41
+ * Collect function for Breadcrumbs handle.
42
+ * Flattens segments in parent-to-child order with deduplication by href: each
43
+ * href keeps its FIRST position but takes the LAST value (re-pushing a parent
44
+ * href refreshes the label in place without reordering the trail). Deferred
45
+ * crumbs (a pushed Promise or `ctx.use(Breadcrumbs).defer()`) are resolved
46
+ * BEFORE collect runs (resolve-by-default), so collect only ever sees resolved
47
+ * items. An item without a string `href` is passed through by identity and
48
+ * excluded from the href dedup.
49
+ */
50
+ function collectBreadcrumbs(segments: BreadcrumbItem[][]): BreadcrumbItem[] {
51
+ const all = segments.flat();
52
+
53
+ const hasHref = (item: unknown): item is BreadcrumbItem =>
54
+ item != null &&
55
+ typeof item === "object" &&
56
+ typeof (item as { href?: unknown }).href === "string";
57
+
58
+ // Dedup crumbs by href: keep the FIRST position (preserving parent->child
59
+ // order) but the LAST value (a child re-pushing a parent's href can refresh
60
+ // its label). Items without an href pass through by identity at their original
61
+ // position.
62
+ const valueByHref = new Map<string, BreadcrumbItem>();
63
+ for (const item of all) {
64
+ if (hasHref(item)) valueByHref.set(item.href, item);
65
+ }
66
+
67
+ const result: BreadcrumbItem[] = [];
68
+ const emitted = new Set<string>();
69
+ for (const item of all) {
70
+ if (!hasHref(item)) {
71
+ result.push(item);
72
+ continue;
73
+ }
74
+ // Emit each href once, at its first occurrence, with the final value.
75
+ if (!emitted.has(item.href)) {
76
+ emitted.add(item.href);
77
+ result.push(valueByHref.get(item.href)!);
78
+ }
79
+ }
80
+ return result;
81
+ }
82
+
83
+ /**
84
+ * Built-in handle for accumulating breadcrumb navigation items.
85
+ *
86
+ * Use `ctx.use(Breadcrumbs)` in route handlers to push breadcrumb items.
87
+ * Use `useHandle(Breadcrumbs)` in client components to consume them.
88
+ */
89
+ export const Breadcrumbs: Handle<BreadcrumbItem, BreadcrumbItem[]> =
90
+ createHandle<BreadcrumbItem, BreadcrumbItem[]>(
91
+ collectBreadcrumbs,
92
+ "__rsc_router_breadcrumbs__",
93
+ );
@@ -0,0 +1,127 @@
1
+ import type { HandleData, HandleStore } from "../server/handle-store.js";
2
+ import { isThenable } from "./is-thenable.js";
3
+
4
+ /**
5
+ * Runtime-neutral resolution of deferred (Promise) handle values. Shared by the
6
+ * server full-render path (resolve before the payload is finalized so SSR sees
7
+ * resolved values) and the client soft-nav path (NavigationProvider resolves
8
+ * each yield before applying it). Pure — imports only `isThenable` — so it is
9
+ * safe in both the RSC server environment AND the browser.
10
+ *
11
+ * Resolution is SHALLOW: only an entry that is ITSELF a thenable is awaited. A
12
+ * value that merely contains a promise (e.g. `{ data: somePromise }`) is a
13
+ * non-thenable, so the `isThenable` check skips it and it passes through verbatim
14
+ * — the nested promise is the consumer's responsibility. Resolution runs each
15
+ * entry through `Promise.all` with a per-entry `try/catch` (NOT `allSettled`), so
16
+ * one rejecting entry is dropped without rejecting the batch or aborting siblings.
17
+ */
18
+
19
+ /**
20
+ * Handle names ($$id) whose snapshot carries a deferred (top-level Promise)
21
+ * value. Used by the client to decide which buckets to hold-and-resolve, and
22
+ * `.size > 0` answers "does this snapshot have any deferred value".
23
+ */
24
+ export function deferredHandleNames(data: HandleData): Set<string> {
25
+ const names = new Set<string>();
26
+ for (const [handleName, segments] of Object.entries(data)) {
27
+ for (const values of Object.values(segments)) {
28
+ if (values.some(isThenable)) {
29
+ names.add(handleName);
30
+ break;
31
+ }
32
+ }
33
+ }
34
+ return names;
35
+ }
36
+
37
+ /**
38
+ * Snapshot with deferred (Promise) values awaited (shallow — only top-level
39
+ * thenables). A rejected deferred is dropped, and a deferred that resolves to
40
+ * `null`/`undefined` is dropped (the `.defer({ else })` skip semantics), so a
41
+ * nullish deferred slot never reaches a collector. Sync (non-thenable) values —
42
+ * including a legitimate sync `null` push — pass through unchanged.
43
+ */
44
+ export async function resolveDeferredHandleValues(
45
+ data: HandleData,
46
+ ): Promise<HandleData> {
47
+ const out: HandleData = {};
48
+ await Promise.all(
49
+ Object.entries(data).flatMap(([handleName, segments]) => {
50
+ out[handleName] = {};
51
+ return Object.entries(segments).map(async ([segmentId, values]) => {
52
+ out[handleName][segmentId] = await resolveValues(values);
53
+ });
54
+ }),
55
+ );
56
+ return out;
57
+ }
58
+
59
+ // Resolve each entry IN ORDER. A non-thenable passes through verbatim (including
60
+ // a legitimate sync `null`/`undefined` push — the "await iff thenable" contract).
61
+ // A thenable is awaited and dropped when it rejects OR resolves to null/undefined
62
+ // (the `.defer({ else })` skip semantics: a forgotten resolver times out to
63
+ // `else ?? undefined`), so a nullish deferred slot never reaches a collector.
64
+ async function resolveValues(values: unknown[]): Promise<unknown[]> {
65
+ const resolved = await Promise.all(
66
+ values.map(async (v) => {
67
+ if (!isThenable(v)) return { keep: true, value: v };
68
+ try {
69
+ const value = await v;
70
+ return { keep: value != null, value };
71
+ } catch {
72
+ return { keep: false, value: undefined };
73
+ }
74
+ }),
75
+ );
76
+ return resolved.filter((r) => r.keep).map((r) => r.value);
77
+ }
78
+
79
+ /**
80
+ * Full-render handle stream: a one-shot async generator that yields the FINAL
81
+ * handle snapshot with every top-level deferred value resolved. Drop-in for
82
+ * `handleStore.stream()` on full / HTML renders (initial load, 404, progressive
83
+ * enhancement), where the consumer drains the generator to completion before
84
+ * rendering anyway — so the single final yield is equivalent to the streamed
85
+ * yields' converged state, and the SSR markup plus the first sync `useHandle`
86
+ * read see resolved values. `getData()` seals the store and awaits the handler
87
+ * barrier; `resolveDeferredHandleValues` then awaits the pushed-value promises.
88
+ * A hung handle promise blocks the full render like any unresolved await (no
89
+ * handle-specific timeout). Partial / action payloads keep streaming via
90
+ * `handleStore.stream()`.
91
+ */
92
+ export async function* resolvedHandleStream(
93
+ handleStore: HandleStore,
94
+ ): AsyncGenerator<HandleData, void, unknown> {
95
+ // Drain stream() (NOT getData()) for the converged snapshot: stream() sets the
96
+ // store's `completed` flag on seal+settle, and that flag is what makes a LATE
97
+ // push throw LateHandlePushError — an async JSX subtree that suspended and later
98
+ // calls ctx.use(Handle)(...) after collection. getData() never sets `completed`,
99
+ // so the late push would silently land. Both wait for the same settle barrier, so
100
+ // the final yielded value is identical; we just keep the late-push guard.
101
+ let snapshot: HandleData = {};
102
+ for await (const data of handleStore.stream()) {
103
+ snapshot = data;
104
+ }
105
+ yield await resolveDeferredHandleValues(snapshot);
106
+ }
107
+
108
+ /**
109
+ * Resolve the deferred (Promise) values in ONE segment's handle bucket
110
+ * (`handleName -> entries[]`). Same shallow + drop-rejections rule as
111
+ * {@link resolveDeferredHandleValues}, but for the segment-keyed shape the
112
+ * prerender/static collection paths use (`getDataForSegment`). Prerender is a
113
+ * build-time cache, so the baked artifact must hold resolved values — a hit
114
+ * replays them into the segment system, where collect/useHandle expect resolved
115
+ * data.
116
+ */
117
+ export async function resolveSegmentHandleValues(
118
+ segHandles: Record<string, unknown[]>,
119
+ ): Promise<Record<string, unknown[]>> {
120
+ const out: Record<string, unknown[]> = {};
121
+ await Promise.all(
122
+ Object.entries(segHandles).map(async ([handleName, values]) => {
123
+ out[handleName] = await resolveValues(values);
124
+ }),
125
+ );
126
+ return out;
127
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Single thenable predicate for the resolve-by-default handle machinery
3
+ * (`handles/deferred-resolution.ts`, its sole owner) — it decides which top-level
4
+ * handle entries are deferred (`Promise`) values to await before any consumer
5
+ * sees them, and which pass through verbatim.
6
+ *
7
+ * Requires a CALLABLE `then` (`typeof obj.then === "function"`), not merely a
8
+ * `"then" in obj` membership check, so a non-promise carrying a `then` field
9
+ * (e.g. a serialized shape `{ then: 5 }`) is treated as a plain sync value rather
10
+ * than awaited. A single predicate keeps that classification consistent.
11
+ */
12
+ export function isThenable(value: unknown): value is PromiseLike<unknown> {
13
+ return (
14
+ value !== null &&
15
+ typeof value === "object" &&
16
+ typeof (value as { then?: unknown }).then === "function"
17
+ );
18
+ }
@@ -31,15 +31,13 @@
31
31
  import { createHandle, type Handle } from "../handle.js";
32
32
  import type {
33
33
  MetaDescriptor,
34
+ MetaDescriptorBase,
34
35
  TitleDescriptor,
35
36
  UnsetDescriptor,
36
37
  } from "../router/types.js";
37
38
 
38
- /**
39
- * Type guard for unset descriptor
40
- */
41
39
  function isUnsetDescriptor(
42
- descriptor: MetaDescriptor
40
+ descriptor: MetaDescriptor,
43
41
  ): descriptor is UnsetDescriptor {
44
42
  return (
45
43
  typeof descriptor === "object" &&
@@ -49,11 +47,8 @@ function isUnsetDescriptor(
49
47
  );
50
48
  }
51
49
 
52
- /**
53
- * Type guard for title descriptor (any form)
54
- */
55
50
  function isTitleDescriptor(
56
- descriptor: MetaDescriptor
51
+ descriptor: MetaDescriptor,
57
52
  ): descriptor is { title: TitleDescriptor } {
58
53
  return (
59
54
  typeof descriptor === "object" &&
@@ -62,11 +57,8 @@ function isTitleDescriptor(
62
57
  );
63
58
  }
64
59
 
65
- /**
66
- * Type guard for title template descriptor
67
- */
68
60
  function isTitleTemplate(
69
- title: TitleDescriptor
61
+ title: TitleDescriptor,
70
62
  ): title is { template: string; default: string } {
71
63
  return (
72
64
  typeof title === "object" &&
@@ -76,19 +68,13 @@ function isTitleTemplate(
76
68
  );
77
69
  }
78
70
 
79
- /**
80
- * Type guard for absolute title descriptor
81
- */
82
- function isAbsoluteTitle(title: TitleDescriptor): title is { absolute: string } {
71
+ function isAbsoluteTitle(
72
+ title: TitleDescriptor,
73
+ ): title is { absolute: string } {
83
74
  return typeof title === "object" && title !== null && "absolute" in title;
84
75
  }
85
76
 
86
- /**
87
- * Get a unique key for a meta descriptor for deduplication.
88
- * Returns undefined for descriptors that shouldn't be deduplicated.
89
- */
90
77
  function getMetaKey(descriptor: MetaDescriptor): string | undefined {
91
- // Skip unset descriptors - they are processed separately
92
78
  if (isUnsetDescriptor(descriptor)) {
93
79
  return undefined;
94
80
  }
@@ -108,13 +94,10 @@ function getMetaKey(descriptor: MetaDescriptor): string | undefined {
108
94
  return `httpEquiv:${descriptor.httpEquiv}`;
109
95
  }
110
96
  if ("script:ld+json" in descriptor) {
111
- // JSON-LD scripts can have multiple, don't dedupe by default
112
97
  return undefined;
113
98
  }
114
99
  if ("tagName" in descriptor) {
115
- // For link tags, dedupe by rel if present
116
100
  if (descriptor.tagName === "link" && "rel" in descriptor) {
117
- // Some link rels should be unique (canonical), others not (stylesheet)
118
101
  const uniqueRels = ["canonical", "icon", "apple-touch-icon"];
119
102
  if (uniqueRels.includes(descriptor.rel as string)) {
120
103
  return `link:${descriptor.rel}`;
@@ -134,14 +117,11 @@ const defaultMetaDescriptors: MetaDescriptor[] = [
134
117
  { name: "viewport", content: "width=device-width, initial-scale=1" },
135
118
  ];
136
119
 
137
- /**
138
- * Helper to add or replace a descriptor in the result array
139
- */
140
120
  function addOrReplace(
141
121
  result: MetaDescriptor[],
142
122
  keyToIndex: Map<string, number>,
143
123
  descriptor: MetaDescriptor,
144
- key: string | undefined
124
+ key: string | undefined,
145
125
  ): void {
146
126
  if (key !== undefined && keyToIndex.has(key)) {
147
127
  result[keyToIndex.get(key)!] = descriptor;
@@ -153,12 +133,9 @@ function addOrReplace(
153
133
  }
154
134
  }
155
135
 
156
- /**
157
- * Helper to update indices after removing an element
158
- */
159
136
  function updateIndicesAfterRemoval(
160
137
  keyToIndex: Map<string, number>,
161
- removedIndex: number
138
+ removedIndex: number,
162
139
  ): void {
163
140
  for (const [key, index] of keyToIndex) {
164
141
  if (index > removedIndex) {
@@ -167,17 +144,11 @@ function updateIndicesAfterRemoval(
167
144
  }
168
145
  }
169
146
 
170
- /**
171
- * Collect function for Meta handle.
172
- * Includes default meta descriptors, then deduplicates by key with later routes overriding earlier ones.
173
- * Supports title templates, absolute titles, and unset descriptors.
174
- */
175
147
  function collectMeta(segments: MetaDescriptor[][]): MetaDescriptor[] {
176
148
  const result: MetaDescriptor[] = [];
177
149
  const keyToIndex = new Map<string, number>();
178
150
  let titleTemplate: string | undefined;
179
151
 
180
- // Add defaults first so they can be overridden
181
152
  for (const descriptor of defaultMetaDescriptors) {
182
153
  const key = getMetaKey(descriptor);
183
154
  if (key !== undefined) {
@@ -188,7 +159,9 @@ function collectMeta(segments: MetaDescriptor[][]): MetaDescriptor[] {
188
159
 
189
160
  for (const descriptors of segments) {
190
161
  for (const descriptor of descriptors) {
191
- // Handle unset descriptors
162
+ // Deferred (Promise) descriptors are resolved BEFORE collectMeta runs
163
+ // (resolve-by-default), so every descriptor here is synchronous and
164
+ // participates in key-based dedup + title-templating like any other.
192
165
  if (isUnsetDescriptor(descriptor)) {
193
166
  const keyToRemove = descriptor.unset;
194
167
  if (keyToIndex.has(keyToRemove)) {
@@ -200,33 +173,46 @@ function collectMeta(segments: MetaDescriptor[][]): MetaDescriptor[] {
200
173
  continue;
201
174
  }
202
175
 
203
- // Handle title descriptors with template/absolute support
204
176
  if (isTitleDescriptor(descriptor)) {
205
177
  const titleValue = descriptor.title;
206
178
 
207
179
  if (isTitleTemplate(titleValue)) {
208
- // Store template for subsequent title descriptors in child segments
209
180
  titleTemplate = titleValue.template;
210
- // Set the default title
211
- addOrReplace(result, keyToIndex, { title: titleValue.default }, "title");
181
+ addOrReplace(
182
+ result,
183
+ keyToIndex,
184
+ { title: titleValue.default },
185
+ "title",
186
+ );
212
187
  continue;
213
188
  }
214
189
 
215
190
  if (isAbsoluteTitle(titleValue)) {
216
- // Absolute title bypasses any template
217
- addOrReplace(result, keyToIndex, { title: titleValue.absolute }, "title");
191
+ addOrReplace(
192
+ result,
193
+ keyToIndex,
194
+ { title: titleValue.absolute },
195
+ "title",
196
+ );
218
197
  continue;
219
198
  }
220
199
 
221
- // String title - apply template if one exists
200
+ // Insert the title literally. String.prototype.replace treats the
201
+ // replacement string specially ($&, $`, $', $$, $n), so a title like
202
+ // "Save $5" or one containing "$&" would be mangled. split/join inserts
203
+ // the raw value with no special-character interpretation.
222
204
  const finalTitle = titleTemplate
223
- ? titleTemplate.replace("%s", titleValue as string)
205
+ ? titleTemplate.split("%s").join(titleValue as string)
224
206
  : titleValue;
225
- addOrReplace(result, keyToIndex, { title: finalTitle as string }, "title");
207
+ addOrReplace(
208
+ result,
209
+ keyToIndex,
210
+ { title: finalTitle as string },
211
+ "title",
212
+ );
226
213
  continue;
227
214
  }
228
215
 
229
- // Handle all other descriptors
230
216
  const key = getMetaKey(descriptor);
231
217
  addOrReplace(result, keyToIndex, descriptor, key);
232
218
  }
@@ -240,8 +226,13 @@ function collectMeta(segments: MetaDescriptor[][]): MetaDescriptor[] {
240
226
  *
241
227
  * Use `ctx.use(Meta)` in route handlers to push meta descriptors.
242
228
  * Use `<MetaTags />` component to render them in the document head.
229
+ *
230
+ * Deferred (Promise) descriptors are resolved before collectMeta runs
231
+ * (resolve-by-default), so they participate in deduplication and `%s`
232
+ * title-templating identically to synchronous descriptors. A descriptor that
233
+ * resolves to `null`/`undefined` (or rejects) is dropped.
243
234
  */
244
- export const Meta: Handle<MetaDescriptor, MetaDescriptor[]> = createHandle<MetaDescriptor, MetaDescriptor[]>(
245
- collectMeta,
246
- "__rsc_router_meta__"
247
- );
235
+ export const Meta: Handle<MetaDescriptor, MetaDescriptor[]> = createHandle<
236
+ MetaDescriptor,
237
+ MetaDescriptor[]
238
+ >(collectMeta, "__rsc_router_meta__");