@rangojs/router 0.0.0-experimental.b9cb8739 → 0.0.0-experimental.bdaf10aa

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 (449) hide show
  1. package/AGENTS.md +8 -4
  2. package/README.md +303 -741
  3. package/dist/bin/rango.js +730 -184
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +4344 -1335
  6. package/dist/vite/index.js.bak +5448 -0
  7. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  8. package/package.json +86 -15
  9. package/skills/api-client/SKILL.md +211 -0
  10. package/skills/breadcrumbs/SKILL.md +85 -6
  11. package/skills/bundle-analysis/SKILL.md +159 -0
  12. package/skills/cache-guide/SKILL.md +251 -24
  13. package/skills/caching/SKILL.md +375 -17
  14. package/skills/catalog.json +271 -0
  15. package/skills/comparison/SKILL.md +50 -0
  16. package/skills/comparison/agents/openai.yaml +4 -0
  17. package/skills/comparison/references/framework-comparison.md +837 -0
  18. package/skills/composability/SKILL.md +110 -4
  19. package/skills/css/SKILL.md +76 -0
  20. package/skills/debug-manifest/SKILL.md +5 -3
  21. package/skills/defer-hydration/SKILL.md +235 -0
  22. package/skills/document-cache/SKILL.md +87 -56
  23. package/skills/fonts/SKILL.md +1 -1
  24. package/skills/handler-use/SKILL.md +364 -0
  25. package/skills/hooks/SKILL.md +73 -691
  26. package/skills/hooks/data.md +273 -0
  27. package/skills/hooks/handle-and-actions.md +103 -0
  28. package/skills/hooks/navigation.md +110 -0
  29. package/skills/hooks/outlets.md +41 -0
  30. package/skills/hooks/state.md +228 -0
  31. package/skills/hooks/urls.md +135 -0
  32. package/skills/host-router/SKILL.md +129 -27
  33. package/skills/i18n/SKILL.md +276 -0
  34. package/skills/intercept/SKILL.md +94 -18
  35. package/skills/layout/SKILL.md +62 -19
  36. package/skills/links/SKILL.md +249 -17
  37. package/skills/loader/SKILL.md +302 -54
  38. package/skills/middleware/SKILL.md +59 -16
  39. package/skills/migrate-nextjs/SKILL.md +745 -0
  40. package/skills/migrate-react-router/SKILL.md +153 -0
  41. package/skills/migrate-react-router/cloudflare-workers.md +129 -0
  42. package/skills/migrate-react-router/component-migration.md +196 -0
  43. package/skills/migrate-react-router/data-and-actions.md +225 -0
  44. package/skills/migrate-react-router/route-mapping.md +271 -0
  45. package/skills/mime-routes/SKILL.md +29 -2
  46. package/skills/observability/SKILL.md +202 -0
  47. package/skills/parallel/SKILL.md +225 -10
  48. package/skills/ppr/SKILL.md +622 -0
  49. package/skills/prerender/SKILL.md +178 -124
  50. package/skills/rango/SKILL.md +318 -24
  51. package/skills/react-compiler/SKILL.md +168 -0
  52. package/skills/response-routes/SKILL.md +138 -49
  53. package/skills/route/SKILL.md +172 -9
  54. package/skills/router-setup/SKILL.md +131 -11
  55. package/skills/scripts/SKILL.md +179 -0
  56. package/skills/server-actions/SKILL.md +776 -0
  57. package/skills/shell-manifest/SKILL.md +185 -0
  58. package/skills/streams-and-websockets/SKILL.md +283 -0
  59. package/skills/tailwind/SKILL.md +28 -4
  60. package/skills/testing/SKILL.md +130 -0
  61. package/skills/testing/bindings.md +103 -0
  62. package/skills/testing/cache-prerender.md +127 -0
  63. package/skills/testing/client-components.md +124 -0
  64. package/skills/testing/e2e-parity.md +125 -0
  65. package/skills/testing/flight.md +91 -0
  66. package/skills/testing/handles.md +131 -0
  67. package/skills/testing/loader.md +128 -0
  68. package/skills/testing/middleware.md +99 -0
  69. package/skills/testing/render-handler.md +122 -0
  70. package/skills/testing/response-routes.md +95 -0
  71. package/skills/testing/reverse-and-types.md +85 -0
  72. package/skills/testing/server-actions.md +107 -0
  73. package/skills/testing/server-tree.md +128 -0
  74. package/skills/testing/setup.md +123 -0
  75. package/skills/theme/SKILL.md +1 -1
  76. package/skills/typesafety/SKILL.md +45 -616
  77. package/skills/typesafety/env-and-bindings.md +254 -0
  78. package/skills/typesafety/generated-files-and-cli.md +335 -0
  79. package/skills/typesafety/params-and-search.md +153 -0
  80. package/skills/typesafety/route-types.md +209 -0
  81. package/skills/use-cache/SKILL.md +74 -15
  82. package/skills/vercel/SKILL.md +128 -0
  83. package/skills/view-transitions/SKILL.md +337 -0
  84. package/src/__augment-tests__/augment.ts +81 -0
  85. package/src/__augment-tests__/augmented.check.ts +116 -0
  86. package/src/__internal.ts +1 -66
  87. package/src/browser/action-coordinator.ts +53 -36
  88. package/src/browser/action-fence.ts +47 -0
  89. package/src/browser/app-shell.ts +39 -0
  90. package/src/browser/app-version.ts +14 -0
  91. package/src/browser/connection-warmup.ts +134 -0
  92. package/src/browser/cookie-name.ts +140 -0
  93. package/src/browser/event-controller.ts +257 -158
  94. package/src/browser/history-state.ts +21 -0
  95. package/src/browser/index.ts +3 -3
  96. package/src/browser/invalidate-client-cache.ts +52 -0
  97. package/src/browser/logging.ts +28 -0
  98. package/src/browser/merge-segment-loaders.ts +6 -4
  99. package/src/browser/navigation-bridge.ts +132 -33
  100. package/src/browser/navigation-client.ts +218 -68
  101. package/src/browser/navigation-store-handle.ts +38 -0
  102. package/src/browser/navigation-store.ts +203 -80
  103. package/src/browser/navigation-transaction.ts +18 -66
  104. package/src/browser/network-error-handler.ts +34 -7
  105. package/src/browser/partial-update.ts +241 -127
  106. package/src/browser/prefetch/cache.ts +271 -44
  107. package/src/browser/prefetch/fetch.ts +367 -40
  108. package/src/browser/prefetch/queue.ts +144 -23
  109. package/src/browser/prefetch/resource-ready.ts +77 -0
  110. package/src/browser/rango-state.ts +158 -76
  111. package/src/browser/react/Link.tsx +121 -16
  112. package/src/browser/react/NavigationProvider.tsx +240 -122
  113. package/src/browser/react/ScrollRestoration.tsx +10 -6
  114. package/src/browser/react/context.ts +7 -2
  115. package/src/browser/react/filter-segment-order.ts +66 -7
  116. package/src/browser/react/index.ts +0 -48
  117. package/src/browser/react/location-state-shared.ts +178 -8
  118. package/src/browser/react/location-state.ts +39 -14
  119. package/src/browser/react/use-action.ts +6 -15
  120. package/src/browser/react/use-handle.ts +23 -69
  121. package/src/browser/react/use-href.tsx +8 -1
  122. package/src/browser/react/use-link-status.ts +33 -8
  123. package/src/browser/react/use-navigation.ts +32 -7
  124. package/src/browser/react/use-params.ts +20 -10
  125. package/src/browser/react/use-reverse.ts +106 -0
  126. package/src/browser/react/use-router.ts +46 -11
  127. package/src/browser/react/use-search-params.ts +0 -5
  128. package/src/browser/react/use-segments.ts +11 -21
  129. package/src/browser/response-adapter.ts +99 -8
  130. package/src/browser/rsc-router.tsx +272 -80
  131. package/src/browser/scroll-restoration.ts +56 -22
  132. package/src/browser/segment-reconciler.ts +44 -7
  133. package/src/browser/segment-structure-assert.ts +2 -2
  134. package/src/browser/server-action-bridge.ts +244 -71
  135. package/src/browser/types.ts +136 -12
  136. package/src/browser/validate-redirect-origin.ts +43 -16
  137. package/src/build/collect-fallback-refs.ts +107 -0
  138. package/src/build/generate-manifest.ts +207 -158
  139. package/src/build/generate-route-types.ts +6 -1
  140. package/src/build/index.ts +11 -3
  141. package/src/build/prefix-tree-utils.ts +123 -0
  142. package/src/build/route-trie.ts +198 -41
  143. package/src/build/route-types/ast-route-extraction.ts +15 -8
  144. package/src/build/route-types/codegen.ts +16 -5
  145. package/src/build/route-types/include-resolution.ts +464 -63
  146. package/src/build/route-types/param-extraction.ts +6 -3
  147. package/src/build/route-types/per-module-writer.ts +22 -6
  148. package/src/build/route-types/router-processing.ts +336 -110
  149. package/src/build/route-types/scan-filter.ts +9 -2
  150. package/src/build/route-types/source-scan.ts +216 -0
  151. package/src/build/runtime-discovery.ts +13 -21
  152. package/src/cache/cache-error.ts +104 -0
  153. package/src/cache/cache-key-utils.ts +58 -13
  154. package/src/cache/cache-policy.ts +108 -34
  155. package/src/cache/cache-runtime.ts +454 -97
  156. package/src/cache/cache-scope.ts +235 -103
  157. package/src/cache/cache-tag.ts +149 -0
  158. package/src/cache/cf/cf-base64.ts +33 -0
  159. package/src/cache/cf/cf-cache-constants.ts +127 -0
  160. package/src/cache/cf/cf-cache-store.ts +2446 -170
  161. package/src/cache/cf/cf-cache-types.ts +349 -0
  162. package/src/cache/cf/cf-kv-utils.ts +46 -0
  163. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  164. package/src/cache/cf/index.ts +11 -17
  165. package/src/cache/document-cache.ts +144 -49
  166. package/src/cache/handle-snapshot.ts +70 -0
  167. package/src/cache/index.ts +24 -20
  168. package/src/cache/memory-segment-store.ts +243 -37
  169. package/src/cache/profile-registry.ts +46 -31
  170. package/src/cache/read-through-swr.ts +56 -12
  171. package/src/cache/segment-codec.ts +13 -21
  172. package/src/cache/shell-snapshot.ts +417 -0
  173. package/src/cache/tag-invalidation.ts +230 -0
  174. package/src/cache/taint.ts +55 -0
  175. package/src/cache/types.ts +194 -99
  176. package/src/cache/vercel/index.ts +11 -0
  177. package/src/cache/vercel/vercel-cache-store.ts +1132 -0
  178. package/src/client.rsc.tsx +41 -21
  179. package/src/client.tsx +116 -290
  180. package/src/cloudflare/index.ts +11 -0
  181. package/src/cloudflare/tracing.ts +108 -0
  182. package/src/component-utils.ts +19 -0
  183. package/src/components/DefaultDocument.tsx +8 -2
  184. package/src/context-var.ts +84 -2
  185. package/src/debug.ts +2 -2
  186. package/src/decode-loader-results.ts +52 -0
  187. package/src/defer.ts +185 -0
  188. package/src/deps/ssr.ts +0 -1
  189. package/src/encode-kv.ts +49 -0
  190. package/src/errors.ts +30 -4
  191. package/src/escape-script.ts +52 -0
  192. package/src/handle.ts +104 -34
  193. package/src/handles/MetaTags.tsx +24 -53
  194. package/src/handles/Scripts.tsx +183 -0
  195. package/src/handles/breadcrumbs.ts +35 -8
  196. package/src/handles/deferred-resolution.ts +127 -0
  197. package/src/handles/is-thenable.ts +18 -0
  198. package/src/handles/meta.ts +14 -40
  199. package/src/handles/script.ts +244 -0
  200. package/src/host/cookie-handler.ts +9 -60
  201. package/src/host/errors.ts +13 -22
  202. package/src/host/index.ts +9 -2
  203. package/src/host/pattern-matcher.ts +23 -52
  204. package/src/host/router.ts +107 -99
  205. package/src/host/testing.ts +40 -27
  206. package/src/host/types.ts +37 -4
  207. package/src/host/utils.ts +1 -1
  208. package/src/href-client.ts +137 -22
  209. package/src/index.rsc.ts +100 -13
  210. package/src/index.ts +143 -19
  211. package/src/internal-debug.ts +11 -10
  212. package/src/loader-store.ts +500 -0
  213. package/src/loader.rsc.ts +20 -13
  214. package/src/loader.ts +12 -11
  215. package/src/missing-id-error.ts +68 -0
  216. package/src/outlet-context.ts +1 -1
  217. package/src/outlet-provider.tsx +1 -5
  218. package/src/prerender/param-hash.ts +16 -16
  219. package/src/prerender/store.ts +37 -41
  220. package/src/prerender.ts +215 -86
  221. package/src/redirect-origin.ts +114 -0
  222. package/src/regex-escape.ts +8 -0
  223. package/src/render-error-thrower.tsx +20 -0
  224. package/src/response-utils.ts +62 -0
  225. package/src/reverse.ts +65 -15
  226. package/src/root-error-boundary.tsx +1 -19
  227. package/src/route-content-wrapper.tsx +19 -77
  228. package/src/route-definition/dsl-helpers.ts +485 -303
  229. package/src/route-definition/helper-factories.ts +28 -140
  230. package/src/route-definition/helpers-types.ts +153 -77
  231. package/src/route-definition/index.ts +4 -2
  232. package/src/route-definition/redirect.ts +53 -12
  233. package/src/route-definition/resolve-handler-use.ts +160 -0
  234. package/src/route-definition/use-item-types.ts +29 -0
  235. package/src/route-map-builder.ts +48 -21
  236. package/src/route-types.ts +37 -46
  237. package/src/router/basename.ts +14 -0
  238. package/src/router/content-negotiation.ts +164 -17
  239. package/src/router/error-handling.ts +45 -18
  240. package/src/router/find-match.ts +130 -29
  241. package/src/router/handler-context.ts +83 -39
  242. package/src/router/instrument.ts +355 -0
  243. package/src/router/intercept-resolution.ts +50 -24
  244. package/src/router/lazy-includes.ts +89 -63
  245. package/src/router/loader-resolution.ts +286 -56
  246. package/src/router/logging.ts +5 -8
  247. package/src/router/manifest.ts +105 -56
  248. package/src/router/match-api.ts +178 -218
  249. package/src/router/match-context.ts +0 -22
  250. package/src/router/match-handlers.ts +211 -165
  251. package/src/router/match-middleware/background-revalidation.ts +66 -22
  252. package/src/router/match-middleware/cache-lookup.ts +214 -263
  253. package/src/router/match-middleware/cache-store.ts +105 -50
  254. package/src/router/match-middleware/intercept-resolution.ts +8 -28
  255. package/src/router/match-middleware/segment-resolution.ts +52 -18
  256. package/src/router/match-pipelines.ts +1 -42
  257. package/src/router/match-result.ts +128 -44
  258. package/src/router/metrics.ts +5 -34
  259. package/src/router/middleware-types.ts +13 -142
  260. package/src/router/middleware.ts +301 -177
  261. package/src/router/navigation-snapshot.ts +133 -0
  262. package/src/router/params-util.ts +23 -0
  263. package/src/router/parse-pattern.ts +115 -0
  264. package/src/router/pattern-matching.ts +181 -150
  265. package/src/router/prefetch-cache-ttl.ts +51 -0
  266. package/src/router/prefetch-limits.ts +37 -0
  267. package/src/router/prerender-match.ts +203 -58
  268. package/src/router/preview-match.ts +35 -103
  269. package/src/router/request-classification.ts +291 -0
  270. package/src/router/revalidation.ts +123 -73
  271. package/src/router/route-snapshot.ts +256 -0
  272. package/src/router/router-context.ts +11 -29
  273. package/src/router/router-interfaces.ts +146 -35
  274. package/src/router/router-options.ts +202 -15
  275. package/src/router/router-registry.ts +2 -5
  276. package/src/router/segment-resolution/fresh.ts +301 -78
  277. package/src/router/segment-resolution/helpers.ts +115 -30
  278. package/src/router/segment-resolution/loader-cache.ts +156 -39
  279. package/src/router/segment-resolution/loader-mask.ts +60 -0
  280. package/src/router/segment-resolution/loader-snapshot.ts +259 -0
  281. package/src/router/segment-resolution/mask-nested.ts +83 -0
  282. package/src/router/segment-resolution/revalidation.ts +477 -385
  283. package/src/router/segment-resolution/static-store.ts +19 -5
  284. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  285. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  286. package/src/router/segment-resolution.ts +5 -1
  287. package/src/router/segment-wrappers.ts +8 -5
  288. package/src/router/state-cookie-name.ts +33 -0
  289. package/src/router/substitute-pattern-params.ts +75 -0
  290. package/src/router/telemetry-otel.ts +160 -200
  291. package/src/router/telemetry.ts +105 -20
  292. package/src/router/timeout.ts +0 -20
  293. package/src/router/tracing.ts +215 -0
  294. package/src/router/trie-matching.ts +171 -59
  295. package/src/router/types.ts +10 -63
  296. package/src/router/url-params.ts +57 -0
  297. package/src/router.ts +210 -71
  298. package/src/rsc/full-payload.ts +70 -0
  299. package/src/rsc/handler-context.ts +3 -2
  300. package/src/rsc/handler.ts +682 -508
  301. package/src/rsc/helpers.ts +168 -46
  302. package/src/rsc/index.ts +2 -5
  303. package/src/rsc/json-route-result.ts +38 -0
  304. package/src/rsc/loader-fetch.ts +127 -31
  305. package/src/rsc/manifest-init.ts +33 -42
  306. package/src/rsc/nonce.ts +10 -1
  307. package/src/rsc/origin-guard.ts +39 -25
  308. package/src/rsc/progressive-enhancement.ts +138 -15
  309. package/src/rsc/redirect-guard.ts +100 -0
  310. package/src/rsc/response-cache-serve.ts +238 -0
  311. package/src/rsc/response-error.ts +79 -12
  312. package/src/rsc/response-route-handler.ts +99 -189
  313. package/src/rsc/rsc-rendering.ts +509 -73
  314. package/src/rsc/runtime-warnings.ts +23 -10
  315. package/src/rsc/server-action.ts +287 -113
  316. package/src/rsc/shell-capture.ts +1190 -0
  317. package/src/rsc/shell-serve.ts +181 -0
  318. package/src/rsc/ssr-setup.ts +18 -2
  319. package/src/rsc/transition-gate.ts +89 -0
  320. package/src/rsc/types.ts +62 -6
  321. package/src/runtime-env.ts +18 -0
  322. package/src/search-params.ts +35 -30
  323. package/src/segment-content-promise.ts +67 -0
  324. package/src/segment-loader-promise.ts +167 -0
  325. package/src/segment-system.tsx +449 -132
  326. package/src/serialize.ts +243 -0
  327. package/src/server/context.ts +367 -61
  328. package/src/server/cookie-parse.ts +32 -0
  329. package/src/server/cookie-store.ts +152 -5
  330. package/src/server/handle-store.ts +40 -38
  331. package/src/server/loader-registry.ts +38 -46
  332. package/src/server/request-context.ts +558 -173
  333. package/src/ssr/index.tsx +491 -174
  334. package/src/ssr/inject-rsc-eager.ts +167 -0
  335. package/src/ssr/ssr-root.tsx +228 -0
  336. package/src/static-handler.ts +27 -18
  337. package/src/testing/cache-status.ts +162 -0
  338. package/src/testing/collect-handle.ts +46 -0
  339. package/src/testing/dispatch.ts +813 -0
  340. package/src/testing/dom.entry.ts +22 -0
  341. package/src/testing/e2e/fixture.ts +188 -0
  342. package/src/testing/e2e/index.ts +128 -0
  343. package/src/testing/e2e/matchers.ts +35 -0
  344. package/src/testing/e2e/page-helpers.ts +272 -0
  345. package/src/testing/e2e/parity.ts +387 -0
  346. package/src/testing/e2e/server.ts +195 -0
  347. package/src/testing/flight-matchers.ts +97 -0
  348. package/src/testing/flight-normalize.ts +11 -0
  349. package/src/testing/flight-runtime.d.ts +57 -0
  350. package/src/testing/flight-tree.ts +682 -0
  351. package/src/testing/flight.entry.ts +52 -0
  352. package/src/testing/flight.ts +257 -0
  353. package/src/testing/generated-routes.ts +199 -0
  354. package/src/testing/index.ts +105 -0
  355. package/src/testing/internal/context.ts +371 -0
  356. package/src/testing/internal/flight-client-globals.ts +30 -0
  357. package/src/testing/internal/seed-vars.ts +54 -0
  358. package/src/testing/render-handler.ts +357 -0
  359. package/src/testing/render-route.tsx +584 -0
  360. package/src/testing/run-loader.ts +385 -0
  361. package/src/testing/run-middleware.ts +205 -0
  362. package/src/testing/run-transition-when.ts +164 -0
  363. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  364. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  365. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  366. package/src/testing/vitest-stubs/version.ts +5 -0
  367. package/src/testing/vitest.ts +305 -0
  368. package/src/theme/ThemeProvider.tsx +56 -84
  369. package/src/theme/ThemeScript.tsx +7 -9
  370. package/src/theme/constants.ts +52 -13
  371. package/src/theme/index.ts +0 -7
  372. package/src/theme/theme-context.ts +1 -5
  373. package/src/theme/theme-script.ts +22 -21
  374. package/src/theme/use-theme.ts +0 -3
  375. package/src/types/boundaries.ts +0 -35
  376. package/src/types/cache-types.ts +17 -8
  377. package/src/types/error-types.ts +30 -90
  378. package/src/types/global-namespace.ts +54 -41
  379. package/src/types/handler-context.ts +234 -82
  380. package/src/types/index.ts +3 -10
  381. package/src/types/loader-types.ts +44 -15
  382. package/src/types/request-scope.ts +112 -0
  383. package/src/types/route-config.ts +20 -52
  384. package/src/types/route-entry.ts +19 -7
  385. package/src/types/segments.ts +137 -14
  386. package/src/urls/include-helper.ts +40 -75
  387. package/src/urls/include-provider.ts +71 -0
  388. package/src/urls/index.ts +2 -11
  389. package/src/urls/path-helper-types.ts +102 -23
  390. package/src/urls/path-helper.ts +62 -111
  391. package/src/urls/pattern-types.ts +84 -19
  392. package/src/urls/response-types.ts +25 -22
  393. package/src/urls/type-extraction.ts +98 -154
  394. package/src/urls/urls-function.ts +1 -19
  395. package/src/use-loader.tsx +346 -89
  396. package/src/vercel/index.ts +11 -0
  397. package/src/vercel/tracing.ts +88 -0
  398. package/src/vite/debug.ts +185 -0
  399. package/src/vite/discovery/bundle-postprocess.ts +36 -38
  400. package/src/vite/discovery/dev-prerender-cache.ts +117 -0
  401. package/src/vite/discovery/discover-routers.ts +130 -85
  402. package/src/vite/discovery/discovery-errors.ts +255 -0
  403. package/src/vite/discovery/gate-state.ts +171 -0
  404. package/src/vite/discovery/prerender-collection.ts +214 -132
  405. package/src/vite/discovery/route-types-writer.ts +40 -84
  406. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  407. package/src/vite/discovery/state.ts +57 -6
  408. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  409. package/src/vite/index.ts +15 -0
  410. package/src/vite/inject-client-debug.ts +88 -0
  411. package/src/vite/plugin-types.ts +234 -62
  412. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  413. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  414. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  415. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  416. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  417. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  418. package/src/vite/plugins/expose-action-id.ts +49 -98
  419. package/src/vite/plugins/expose-id-utils.ts +96 -51
  420. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  421. package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
  422. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  423. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  424. package/src/vite/plugins/expose-internal-ids.ts +553 -317
  425. package/src/vite/plugins/performance-tracks.ts +89 -0
  426. package/src/vite/plugins/refresh-cmd.ts +89 -27
  427. package/src/vite/plugins/use-cache-transform.ts +73 -83
  428. package/src/vite/plugins/vercel-output.ts +384 -0
  429. package/src/vite/plugins/version-injector.ts +40 -29
  430. package/src/vite/plugins/version-plugin.ts +46 -37
  431. package/src/vite/plugins/virtual-entries.ts +138 -27
  432. package/src/vite/rango.ts +353 -303
  433. package/src/vite/router-discovery.ts +1090 -166
  434. package/src/vite/utils/ast-handler-extract.ts +26 -35
  435. package/src/vite/utils/banner.ts +4 -4
  436. package/src/vite/utils/bundle-analysis.ts +10 -15
  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 +4 -59
  441. package/src/vite/utils/package-resolution.ts +20 -52
  442. package/src/vite/utils/prerender-utils.ts +98 -38
  443. package/src/vite/utils/shared-utils.ts +144 -44
  444. package/src/browser/action-response-classifier.ts +0 -99
  445. package/src/browser/react/use-client-cache.ts +0 -58
  446. package/src/browser/shallow.ts +0 -40
  447. package/src/handles/index.ts +0 -7
  448. package/src/network-error-thrower.tsx +0 -23
  449. package/src/router/middleware-cookies.ts +0 -55
@@ -7,11 +7,12 @@
7
7
  */
8
8
 
9
9
  import { RouterError } from "../errors.js";
10
- import { requireRequestContext } from "../server/request-context.js";
10
+ import { getRequestContext } from "../server/request-context.js";
11
11
  import { contextGet } from "../context-var.js";
12
12
  import { NOCACHE_SYMBOL } from "../cache/taint.js";
13
- import { traverseBack } from "../router/pattern-matching.js";
14
- import { createCacheScope } from "../cache/cache-scope.js";
13
+ import { RESPONSE_TYPE_MIME } from "../router/content-negotiation.js";
14
+ import { createCacheScope, resolveCacheTags } from "../cache/cache-scope.js";
15
+ import { serveResponseRouteWithCache } from "./response-cache-serve.js";
15
16
  import { executeMiddleware } from "../router/middleware.js";
16
17
  import {
17
18
  createReverseFunction,
@@ -20,13 +21,21 @@ import {
20
21
  import type { MiddlewareFn } from "../router/middleware.js";
21
22
  import type { EntryData } from "../server/context.js";
22
23
  import type { HandlerContext } from "./handler-context.js";
23
- import { createResponseErrorPayload } from "./response-error.js";
24
+ import { createProblemDetails } from "./response-error.js";
24
25
  import {
25
26
  createResponseWithMergedHeaders,
26
27
  finalizeResponse,
27
28
  isCacheableStatus,
28
29
  buildRouteMiddlewareEntries,
30
+ mergeStubHeadersAndFinalize,
29
31
  } from "./helpers.js";
32
+ import { isWebSocketUpgradeResponse } from "../response-utils.js";
33
+ import { stringifyJsonRouteResult } from "./json-route-result.js";
34
+ import {
35
+ EXTERNAL_REDIRECT_MARKER,
36
+ isExternalRedirect,
37
+ markExternalRedirect,
38
+ } from "../redirect-origin.js";
30
39
 
31
40
  export interface ResponseRouteMatch {
32
41
  responseType: string;
@@ -70,7 +79,7 @@ export async function handleResponseRoute<TEnv>(
70
79
  }
71
80
 
72
81
  // Build lightweight context for response handler
73
- const reqCtx = requireRequestContext();
82
+ const reqCtx = getRequestContext();
74
83
  const cleanUrl = stripInternalParams(url);
75
84
  const responseHandlerCtx = {
76
85
  request,
@@ -78,10 +87,13 @@ export async function handleResponseRoute<TEnv>(
78
87
  env,
79
88
  searchParams: cleanUrl.searchParams,
80
89
  url: cleanUrl,
90
+ originalUrl: reqCtx.originalUrl,
81
91
  pathname: url.pathname,
82
92
  reverse: createReverseFunction(handlerCtx.getRequiredRouteMap()),
83
93
  get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as any,
84
94
  header: (name: string, value: string) => reqCtx.header(name, value),
95
+ waitUntil: reqCtx.waitUntil.bind(reqCtx),
96
+ executionContext: reqCtx.executionContext,
85
97
  _responseType: preview.responseType,
86
98
  };
87
99
  // Brand with taint symbol so "use cache" detects it as request-scoped
@@ -96,51 +108,39 @@ export async function handleResponseRoute<TEnv>(
96
108
  // so that stub headers (cookies, custom headers set via ctx.header()) are included.
97
109
  // Use Headers (not Record<string, string>) to preserve duplicate entries like Set-Cookie.
98
110
  const rewrapResponse = (result: Response) => {
111
+ // 204/205/304 are NOT short-circuited — they're valid for the Response
112
+ // constructor and must honor ctx.setStatus() overrides. Only upgrade
113
+ // responses (status 101 / `webSocket` property) bypass reconstruction.
114
+ if (isWebSocketUpgradeResponse(result)) {
115
+ return mergeStubHeadersAndFinalize(result);
116
+ }
99
117
  const headers = new Headers();
100
118
  result.headers.forEach((value, key) => {
119
+ // Never copy the reserved external-redirect marker off a handler result.
120
+ // It is not a trust signal -- the opt-in is the out-of-band brand below
121
+ // -- and a proxy-style route returning an attacker-controlled upstream
122
+ // response must not let a forged value ride through to the browser.
123
+ if (key.toLowerCase() === EXTERNAL_REDIRECT_MARKER) return;
101
124
  if (key.toLowerCase() === "set-cookie") {
102
125
  headers.append(key, value);
103
126
  } else {
104
127
  headers.set(key, value);
105
128
  }
106
129
  });
107
- return createResponseWithMergedHeaders(result.body, {
130
+ const rewrapped = createResponseWithMergedHeaders(result.body, {
108
131
  status: result.status,
109
132
  headers,
110
133
  });
111
- };
112
-
113
- // JSON response routes: wrap in { data } / { error } envelope
114
- if (preview.responseType === "json") {
115
- try {
116
- const result = await (preview.handler as Function)(responseHandlerCtx);
117
- if (result instanceof Response) {
118
- return rewrapResponse(result);
119
- }
120
- return createResponseWithMergedHeaders(
121
- JSON.stringify({ data: result }),
122
- {
123
- status: 200,
124
- headers: { "content-type": "application/json;charset=utf-8" },
125
- },
126
- );
127
- } catch (error) {
128
- handlerCtx.callOnError(error, "handler", errorCtx);
129
- const isDev = process.env.NODE_ENV !== "production";
130
- const status = error instanceof RouterError ? error.status : 500;
131
- return createResponseWithMergedHeaders(
132
- JSON.stringify({
133
- error: createResponseErrorPayload(error, isDev),
134
- }),
135
- {
136
- status,
137
- headers: { "content-type": "application/json;charset=utf-8" },
138
- },
139
- );
134
+ // Transfer the out-of-band external brand only when the handler result is
135
+ // genuinely branded (a real redirect(url, { external: true })). A proxied
136
+ // upstream Response is never branded, so an attacker cannot opt a response
137
+ // route's redirect out of the same-origin guard by injecting the header.
138
+ if (isExternalRedirect(result)) {
139
+ markExternalRedirect(rewrapped);
140
140
  }
141
- }
141
+ return rewrapped;
142
+ };
142
143
 
143
- // Non-JSON response routes: catch errors and return plain Response
144
144
  try {
145
145
  const result = await (preview.handler as Function)(responseHandlerCtx);
146
146
 
@@ -148,38 +148,56 @@ export async function handleResponseRoute<TEnv>(
148
148
  return rewrapResponse(result);
149
149
  }
150
150
 
151
- // Auto-wrap based on response type tag
152
- switch (preview.responseType) {
153
- case "text":
154
- return createResponseWithMergedHeaders(String(result), {
155
- status: 200,
156
- headers: { "content-type": "text/plain;charset=utf-8" },
157
- });
158
- case "html":
159
- return createResponseWithMergedHeaders(String(result), {
160
- status: 200,
161
- headers: { "content-type": "text/html;charset=utf-8" },
162
- });
163
- case "xml":
164
- return createResponseWithMergedHeaders(String(result), {
165
- status: 200,
166
- headers: { "content-type": "application/xml;charset=utf-8" },
167
- });
168
- case "md":
169
- return createResponseWithMergedHeaders(String(result), {
170
- status: 200,
171
- headers: { "content-type": "text/markdown;charset=utf-8" },
172
- });
173
- default:
174
- // image, stream, any -- must return Response
175
- throw new Error(
176
- `Response route handler for "${preview.responseType}" must return a Response object, got ${typeof result}`,
177
- );
151
+ // Handled before the MIME lookup (json is also a RESPONSE_TYPE_MIME key).
152
+ if (preview.responseType === "json") {
153
+ // Runtime guard: the json() return type rejects nested Promises at
154
+ // compile time, but an `as`-cast or untyped (JS) handler can still slip
155
+ // one through. stringifyJsonRouteResult throws a clear error instead of
156
+ // shipping empty data (shared with dispatch() so the two cannot drift).
157
+ const body = stringifyJsonRouteResult(result);
158
+ return createResponseWithMergedHeaders(body, {
159
+ status: 200,
160
+ headers: { "content-type": "application/json;charset=utf-8" },
161
+ });
178
162
  }
163
+
164
+ // Object.hasOwn (not truthiness) so prototype names like "toString" are not
165
+ // matched; image/stream/any are absent and fall through to the throw.
166
+ if (Object.hasOwn(RESPONSE_TYPE_MIME, preview.responseType)) {
167
+ return createResponseWithMergedHeaders(String(result), {
168
+ status: 200,
169
+ headers: {
170
+ "content-type": `${RESPONSE_TYPE_MIME[preview.responseType]};charset=utf-8`,
171
+ },
172
+ });
173
+ }
174
+
175
+ throw new Error(
176
+ `Response route handler for "${preview.responseType}" must return a Response object, got ${typeof result}`,
177
+ );
179
178
  } catch (error) {
180
179
  handlerCtx.callOnError(error, "handler", errorCtx);
181
180
  const isDev = process.env.NODE_ENV !== "production";
182
- const status = error instanceof RouterError ? error.status : 500;
181
+ const derivedStatus = error instanceof RouterError ? error.status : 500;
182
+ // Resolve the effective status the same way createResponseWithMergedHeaders
183
+ // will (ctx.res.status override) so the problem body's status/title match
184
+ // the actual HTTP status — e.g. when a handler called ctx.setStatus()
185
+ // before throwing.
186
+ const status =
187
+ reqCtx.res.status !== 200 ? reqCtx.res.status : derivedStatus;
188
+
189
+ if (preview.responseType === "json") {
190
+ return createResponseWithMergedHeaders(
191
+ JSON.stringify(createProblemDetails(error, status, isDev)),
192
+ {
193
+ status,
194
+ headers: {
195
+ "content-type": "application/problem+json;charset=utf-8",
196
+ },
197
+ },
198
+ );
199
+ }
200
+
183
201
  const message =
184
202
  error instanceof RouterError
185
203
  ? error.message
@@ -196,7 +214,9 @@ export async function handleResponseRoute<TEnv>(
196
214
  // Wrap callHandler to append Vary: Accept on content-negotiated responses
197
215
  const callHandlerWithVary = async () => {
198
216
  const response = await callHandler();
199
- if (preview.negotiated) {
217
+ if (preview.negotiated && !isWebSocketUpgradeResponse(response)) {
218
+ // Skip Vary on upgrade responses: headers are semantically immutable
219
+ // on some runtimes, and Vary is meaningless for a 101 response.
200
220
  response.headers.append("Vary", "Accept");
201
221
  }
202
222
  return response;
@@ -217,130 +237,20 @@ export async function handleResponseRoute<TEnv>(
217
237
  return callHandlerWithVary();
218
238
  };
219
239
 
220
- // Resolve cache config from entry tree (same pattern as match-api.ts)
240
+ // Response-route cache: resolved through the shared serve leaf
241
+ // (rsc/response-cache-serve.ts) so production and the dispatch testing
242
+ // primitive share ONE owner of the cache contract. Returns undefined when no
243
+ // cache applies, so we fall through to a plain handler run.
221
244
  if (preview.manifestEntry) {
222
- let cacheScope: ReturnType<typeof createCacheScope> = null;
223
- for (const entry of traverseBack(preview.manifestEntry)) {
224
- if (entry.cache) {
225
- cacheScope = createCacheScope(entry.cache, cacheScope);
226
- }
227
- }
228
-
229
- if (cacheScope?.enabled) {
230
- // Evaluate condition skip response cache when condition returns false
231
- let conditionPassed = true;
232
- if (cacheScope.config !== false && cacheScope.config.condition) {
233
- try {
234
- conditionPassed = !!cacheScope.config.condition(reqCtx);
235
- } catch {
236
- conditionPassed = false;
237
- }
238
- }
239
-
240
- const store = cacheScope.getStore() ?? reqCtx._cacheStore;
241
- if (conditionPassed && store?.getResponse && store?.putResponse) {
242
- // Build cache key with response:{type}: prefix to avoid collision
243
- // with segment keys and differentiate between response types.
244
- // Include host and url.search so query-driven and multi-host
245
- // responses cache separately.
246
- let cacheKey = `response:${preview.responseType}:${url.host}${url.pathname}${url.search}`;
247
-
248
- // Priority 1: Route-level key function (full override)
249
- if (cacheScope.config !== false && cacheScope.config.key) {
250
- try {
251
- const customKey = await cacheScope.config.key(reqCtx);
252
- cacheKey = `response:${customKey}`;
253
- } catch {
254
- // Fall back to default key on route-level key failure
255
- }
256
- } else if (store.keyGenerator) {
257
- // Priority 2: Store-level keyGenerator (modifies default key)
258
- try {
259
- cacheKey = await store.keyGenerator(reqCtx, cacheKey);
260
- } catch {
261
- // Fall back to default key on keyGenerator failure
262
- }
263
- }
264
-
265
- // Save pre-handler callbacks (registered by app-level middleware
266
- // before we reach the cache block) and clear the live array.
267
- // createResponseWithMergedHeaders (inside the handler) eagerly
268
- // executes any callbacks present in _onResponseCallbacks, so
269
- // handler-registered callbacks are baked into the handler's
270
- // response and the cached artifact. Pre-handler callbacks are
271
- // NOT in the live array during execution, so they are applied
272
- // once per serve on every path (hit + miss) below.
273
- const savedCallbacks = reqCtx._onResponseCallbacks;
274
- reqCtx._onResponseCallbacks = [];
275
-
276
- const applyPreHandlerCallbacks = (response: Response): Response => {
277
- let result = response;
278
- for (const callback of savedCallbacks) {
279
- result = callback(result) ?? result;
280
- }
281
- return result;
282
- };
283
-
284
- try {
285
- const cached = await store.getResponse(cacheKey);
286
-
287
- if (cached && isCacheableStatus(cached.response.status)) {
288
- if (!cached.shouldRevalidate) {
289
- // Fresh hit
290
- return applyPreHandlerCallbacks(cached.response);
291
- }
292
-
293
- // Stale hit (SWR) - return cached, revalidate in background
294
- reqCtx.waitUntil(async () => {
295
- try {
296
- // finalizeResponse drains any onResponse callbacks registered
297
- // during middleware execution (e.g. middleware short-circuit)
298
- // that createResponseWithMergedHeaders didn't reach.
299
- const fresh = finalizeResponse(await executeHandler());
300
- if (isCacheableStatus(fresh.status)) {
301
- await store.putResponse!(
302
- cacheKey,
303
- fresh.clone(),
304
- cacheScope!.ttl,
305
- cacheScope!.swr,
306
- );
307
- }
308
- } catch (error) {
309
- console.error(`[ResponseCache] Revalidation failed:`, error);
310
- }
311
- });
312
-
313
- return applyPreHandlerCallbacks(cached.response);
314
- }
315
- } catch (error) {
316
- console.error(`[ResponseCache] Cache lookup failed:`, error);
317
- }
318
-
319
- // Cache miss - execute handler and cache the result.
320
- // createResponseWithMergedHeaders inside the handler drains callbacks
321
- // registered during handler execution. finalizeResponse catches any
322
- // remaining callbacks (e.g. from middleware short-circuit where the
323
- // handler never ran) so the cached artifact includes all transforms.
324
- const response = finalizeResponse(await executeHandler());
325
-
326
- if (isCacheableStatus(response.status)) {
327
- reqCtx.waitUntil(async () => {
328
- try {
329
- await store.putResponse!(
330
- cacheKey,
331
- response.clone(),
332
- cacheScope!.ttl,
333
- cacheScope!.swr,
334
- );
335
- } catch (error) {
336
- console.error(`[ResponseCache] Cache write failed:`, error);
337
- }
338
- });
339
- }
340
-
341
- return applyPreHandlerCallbacks(response);
342
- }
343
- }
245
+ const cached = await serveResponseRouteWithCache({
246
+ reqCtx,
247
+ manifestEntry: preview.manifestEntry,
248
+ responseType: preview.responseType,
249
+ url,
250
+ executeHandler,
251
+ deps: { createCacheScope, resolveCacheTags },
252
+ });
253
+ if (cached !== undefined) return cached;
344
254
  }
345
255
 
346
256
  return executeHandler().then(finalizeResponse);