@rangojs/router 0.0.0-experimental.d20dd405 → 0.0.0-experimental.d68257e5

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 (910) hide show
  1. package/AGENTS.md +8 -4
  2. package/README.md +314 -882
  3. package/dist/bin/rango.js +927 -273
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/types/__internal.d.ts +127 -0
  6. package/dist/types/bin/rango.d.ts +1 -0
  7. package/dist/types/browser/action-coordinator.d.ts +57 -0
  8. package/dist/types/browser/action-fence.d.ts +33 -0
  9. package/dist/types/browser/app-shell.d.ts +34 -0
  10. package/dist/types/browser/app-version.d.ts +6 -0
  11. package/dist/types/browser/connection-warmup.d.ts +31 -0
  12. package/dist/types/browser/cookie-name.d.ts +66 -0
  13. package/dist/types/browser/dev-discovery.d.ts +11 -0
  14. package/dist/types/browser/event-controller.d.ts +231 -0
  15. package/dist/types/browser/history-state.d.ts +26 -0
  16. package/dist/types/browser/index.d.ts +1 -0
  17. package/dist/types/browser/intercept-utils.d.ts +30 -0
  18. package/dist/types/browser/invalidate-client-cache.d.ts +17 -0
  19. package/dist/types/browser/link-interceptor.d.ts +53 -0
  20. package/dist/types/browser/logging.d.ts +33 -0
  21. package/dist/types/browser/merge-segment-loaders.d.ts +38 -0
  22. package/dist/types/browser/navigation-bridge.d.ts +39 -0
  23. package/dist/types/browser/navigation-client.d.ts +17 -0
  24. package/dist/types/browser/navigation-store-handle.d.ts +25 -0
  25. package/dist/types/browser/navigation-store.d.ts +85 -0
  26. package/dist/types/browser/navigation-transaction.d.ts +75 -0
  27. package/dist/types/browser/network-error-handler.d.ts +35 -0
  28. package/dist/types/browser/notify-listeners.d.ts +2 -0
  29. package/dist/types/browser/partial-update.d.ts +61 -0
  30. package/dist/types/browser/prefetch/cache.d.ts +224 -0
  31. package/dist/types/browser/prefetch/default-strategy.d.ts +31 -0
  32. package/dist/types/browser/prefetch/fetch.d.ts +52 -0
  33. package/dist/types/browser/prefetch/invalidation.d.ts +6 -0
  34. package/dist/types/browser/prefetch/loader.d.ts +12 -0
  35. package/dist/types/browser/prefetch/observer.d.ts +24 -0
  36. package/dist/types/browser/prefetch/policy.d.ts +13 -0
  37. package/dist/types/browser/prefetch/queue.d.ts +48 -0
  38. package/dist/types/browser/prefetch/resource-ready.d.ts +28 -0
  39. package/dist/types/browser/prefetch/runtime.d.ts +2 -0
  40. package/dist/types/browser/rango-state.d.ts +56 -0
  41. package/dist/types/browser/react/Link.d.ts +132 -0
  42. package/dist/types/browser/react/NavigationProvider.d.ts +88 -0
  43. package/dist/types/browser/react/ScrollRestoration.d.ts +78 -0
  44. package/dist/types/browser/react/context.d.ts +57 -0
  45. package/dist/types/browser/react/filter-segment-order.d.ts +35 -0
  46. package/dist/types/browser/react/index.d.ts +1 -0
  47. package/dist/types/browser/react/location-state-shared.d.ts +162 -0
  48. package/dist/types/browser/react/location-state.d.ts +29 -0
  49. package/dist/types/browser/react/mount-context.d.ts +23 -0
  50. package/dist/types/browser/react/nonce-context.d.ts +14 -0
  51. package/dist/types/browser/react/shallow-equal.d.ts +5 -0
  52. package/dist/types/browser/react/use-action.d.ts +61 -0
  53. package/dist/types/browser/react/use-handle.d.ts +21 -0
  54. package/dist/types/browser/react/use-href.d.ts +32 -0
  55. package/dist/types/browser/react/use-link-status.d.ts +36 -0
  56. package/dist/types/browser/react/use-mount.d.ts +24 -0
  57. package/dist/types/browser/react/use-navigation.d.ts +15 -0
  58. package/dist/types/browser/react/use-params.d.ts +21 -0
  59. package/dist/types/browser/react/use-pathname.d.ts +13 -0
  60. package/dist/types/browser/react/use-reverse.d.ts +40 -0
  61. package/dist/types/browser/react/use-router.d.ts +30 -0
  62. package/dist/types/browser/react/use-search-params.d.ts +66 -0
  63. package/dist/types/browser/react/use-segments.d.ts +29 -0
  64. package/dist/types/browser/response-adapter.d.ts +58 -0
  65. package/dist/types/browser/rsc-router.d.ts +146 -0
  66. package/dist/types/browser/scroll-restoration.d.ts +103 -0
  67. package/dist/types/browser/segment-reconciler.d.ts +74 -0
  68. package/dist/types/browser/segment-structure-assert.d.ts +16 -0
  69. package/dist/types/browser/server-action-bridge.d.ts +29 -0
  70. package/dist/types/browser/types.d.ts +546 -0
  71. package/dist/types/browser/validate-redirect-origin.d.ts +28 -0
  72. package/dist/types/build/collect-fallback-refs.d.ts +5 -0
  73. package/dist/types/build/generate-manifest.d.ts +106 -0
  74. package/dist/types/build/generate-route-types.d.ts +8 -0
  75. package/dist/types/build/index.d.ts +21 -0
  76. package/dist/types/build/merge-full-manifests.d.ts +3 -0
  77. package/dist/types/build/prefix-tree-utils.d.ts +56 -0
  78. package/dist/types/build/route-trie.d.ts +20 -0
  79. package/dist/types/build/route-types/ast-helpers.d.ts +3 -0
  80. package/dist/types/build/route-types/ast-route-extraction.d.ts +13 -0
  81. package/dist/types/build/route-types/codegen.d.ts +16 -0
  82. package/dist/types/build/route-types/include-resolution.d.ts +74 -0
  83. package/dist/types/build/route-types/param-extraction.d.ts +13 -0
  84. package/dist/types/build/route-types/per-module-writer.d.ts +20 -0
  85. package/dist/types/build/route-types/router-processing.d.ts +81 -0
  86. package/dist/types/build/route-types/scan-filter.d.ts +17 -0
  87. package/dist/types/build/route-types/source-scan.d.ts +13 -0
  88. package/dist/types/build/runtime-discovery.d.ts +24 -0
  89. package/dist/types/cache/background-task.d.ts +21 -0
  90. package/dist/types/cache/cache-error.d.ts +71 -0
  91. package/dist/types/cache/cache-exec-scope.d.ts +31 -0
  92. package/dist/types/cache/cache-key-utils.d.ts +43 -0
  93. package/dist/types/cache/cache-policy.d.ts +59 -0
  94. package/dist/types/cache/cache-runtime.d.ts +51 -0
  95. package/dist/types/cache/cache-scope.d.ts +215 -0
  96. package/dist/types/cache/cache-tag.d.ts +79 -0
  97. package/dist/types/cache/cf/cf-base64.d.ts +4 -0
  98. package/dist/types/cache/cf/cf-cache-constants.d.ts +112 -0
  99. package/dist/types/cache/cf/cf-cache-store.d.ts +630 -0
  100. package/dist/types/cache/cf/cf-cache-types.d.ts +365 -0
  101. package/dist/types/cache/cf/cf-kv-utils.d.ts +43 -0
  102. package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +15 -0
  103. package/dist/types/cache/cf/cf-zone-purge.d.ts +31 -0
  104. package/dist/types/cache/cf/index.d.ts +4 -0
  105. package/dist/types/cache/document-cache.d.ts +71 -0
  106. package/dist/types/cache/handle-capture.d.ts +23 -0
  107. package/dist/types/cache/handle-snapshot.d.ts +39 -0
  108. package/dist/types/cache/index.d.ts +9 -0
  109. package/dist/types/cache/memory-segment-store.d.ts +163 -0
  110. package/dist/types/cache/profile-registry.d.ts +40 -0
  111. package/dist/types/cache/read-through-swr.d.ts +61 -0
  112. package/dist/types/cache/search-params-filter.d.ts +64 -0
  113. package/dist/types/cache/segment-codec.d.ts +78 -0
  114. package/dist/types/cache/shell-snapshot.d.ts +186 -0
  115. package/dist/types/cache/tag-invalidation.d.ts +74 -0
  116. package/dist/types/cache/taint.d.ts +77 -0
  117. package/dist/types/cache/types.d.ts +522 -0
  118. package/dist/types/cache/vercel/index.d.ts +1 -0
  119. package/dist/types/cache/vercel/vercel-cache-store.d.ts +268 -0
  120. package/dist/types/client-urls/client-root.d.ts +38 -0
  121. package/dist/types/client-urls/client-urls.d.ts +5 -0
  122. package/dist/types/client-urls/navigation.d.ts +38 -0
  123. package/dist/types/client-urls/revalidation-protocol.d.ts +25 -0
  124. package/dist/types/client-urls/server-projection.d.ts +71 -0
  125. package/dist/types/client-urls/types.d.ts +148 -0
  126. package/dist/types/client.d.ts +192 -0
  127. package/dist/types/client.rsc.d.ts +42 -0
  128. package/dist/types/cloudflare/index.d.ts +7 -0
  129. package/dist/types/cloudflare/tracing.d.ts +57 -0
  130. package/dist/types/component-utils.d.ts +46 -0
  131. package/dist/types/components/DefaultDocument.d.ts +13 -0
  132. package/dist/types/context-var.d.ts +84 -0
  133. package/dist/types/debug.d.ts +57 -0
  134. package/dist/types/decode-loader-results.d.ts +42 -0
  135. package/dist/types/default-error-boundary.d.ts +10 -0
  136. package/dist/types/defer.d.ts +89 -0
  137. package/dist/types/deps/browser.d.ts +1 -0
  138. package/dist/types/deps/html-stream-client.d.ts +1 -0
  139. package/dist/types/deps/html-stream-server.d.ts +1 -0
  140. package/dist/types/deps/rsc.d.ts +1 -0
  141. package/dist/types/deps/ssr.d.ts +1 -0
  142. package/dist/types/dev-discovery-protocol.d.ts +5 -0
  143. package/dist/types/encode-kv.d.ts +35 -0
  144. package/dist/types/errors.d.ts +227 -0
  145. package/dist/types/escape-script.d.ts +44 -0
  146. package/dist/types/handle.d.ts +93 -0
  147. package/dist/types/handles/MetaTags.d.ts +17 -0
  148. package/dist/types/handles/Scripts.d.ts +38 -0
  149. package/dist/types/handles/breadcrumbs.d.ts +43 -0
  150. package/dist/types/handles/deferred-resolution.d.ts +53 -0
  151. package/dist/types/handles/is-thenable.d.ts +10 -0
  152. package/dist/types/handles/meta.d.ts +43 -0
  153. package/dist/types/handles/script.d.ts +139 -0
  154. package/dist/types/host/cookie-handler.d.ts +8 -0
  155. package/dist/types/host/errors.d.ts +40 -0
  156. package/dist/types/host/index.d.ts +33 -0
  157. package/dist/types/host/pattern-matcher.d.ts +30 -0
  158. package/dist/types/host/router.d.ts +12 -0
  159. package/dist/types/host/testing.d.ts +41 -0
  160. package/dist/types/host/types.d.ts +148 -0
  161. package/dist/types/host/utils.d.ts +20 -0
  162. package/dist/types/href-client.d.ts +214 -0
  163. package/dist/types/index.d.ts +113 -0
  164. package/dist/types/index.rsc.d.ts +52 -0
  165. package/dist/types/internal-debug.d.ts +1 -0
  166. package/dist/types/loader-redirect.d.ts +27 -0
  167. package/dist/types/loader-store.d.ts +193 -0
  168. package/dist/types/loader.d.ts +18 -0
  169. package/dist/types/loader.rsc.d.ts +18 -0
  170. package/dist/types/missing-id-error.d.ts +1 -0
  171. package/dist/types/outlet-context.d.ts +32 -0
  172. package/dist/types/outlet-provider.d.ts +15 -0
  173. package/dist/types/prerender/build-shell-capture.d.ts +104 -0
  174. package/dist/types/prerender/param-hash.d.ts +6 -0
  175. package/dist/types/prerender/shell-manifest-key.d.ts +18 -0
  176. package/dist/types/prerender/store.d.ts +63 -0
  177. package/dist/types/prerender.d.ts +292 -0
  178. package/dist/types/redirect-origin.d.ts +71 -0
  179. package/dist/types/regex-escape.d.ts +6 -0
  180. package/dist/types/render-error-thrower.d.ts +13 -0
  181. package/dist/types/response-utils.d.ts +35 -0
  182. package/dist/types/reverse.d.ts +206 -0
  183. package/dist/types/root-error-boundary.d.ts +32 -0
  184. package/dist/types/route-content-wrapper.d.ts +84 -0
  185. package/dist/types/route-definition/dsl-helpers.d.ts +130 -0
  186. package/dist/types/route-definition/helper-factories.d.ts +22 -0
  187. package/dist/types/route-definition/helpers-types.d.ts +405 -0
  188. package/dist/types/route-definition/index.d.ts +7 -0
  189. package/dist/types/route-definition/redirect.d.ts +48 -0
  190. package/dist/types/route-definition/resolve-handler-use.d.ts +19 -0
  191. package/dist/types/route-definition/use-item-types.d.ts +1 -0
  192. package/dist/types/route-definition.d.ts +1 -0
  193. package/dist/types/route-map-builder.d.ts +102 -0
  194. package/dist/types/route-name.d.ts +27 -0
  195. package/dist/types/route-types.d.ts +172 -0
  196. package/dist/types/router/basename.d.ts +10 -0
  197. package/dist/types/router/content-negotiation.d.ts +91 -0
  198. package/dist/types/router/debug-manifest.d.ts +7 -0
  199. package/dist/types/router/error-handling.d.ts +110 -0
  200. package/dist/types/router/find-match.d.ts +19 -0
  201. package/dist/types/router/handler-context.d.ts +41 -0
  202. package/dist/types/router/instrument.d.ts +191 -0
  203. package/dist/types/router/intercept-resolution.d.ts +91 -0
  204. package/dist/types/router/lazy-includes.d.ts +26 -0
  205. package/dist/types/router/loader-resolution.d.ts +85 -0
  206. package/dist/types/router/logging.d.ts +41 -0
  207. package/dist/types/router/manifest.d.ts +8 -0
  208. package/dist/types/router/match-api.d.ts +19 -0
  209. package/dist/types/router/match-context.d.ts +184 -0
  210. package/dist/types/router/match-handlers.d.ts +48 -0
  211. package/dist/types/router/match-middleware/background-revalidation.d.ts +113 -0
  212. package/dist/types/router/match-middleware/cache-lookup.d.ts +126 -0
  213. package/dist/types/router/match-middleware/cache-store.d.ts +112 -0
  214. package/dist/types/router/match-middleware/index.d.ts +80 -0
  215. package/dist/types/router/match-middleware/intercept-resolution.d.ts +116 -0
  216. package/dist/types/router/match-middleware/segment-resolution.d.ts +94 -0
  217. package/dist/types/router/match-pipelines.d.ts +103 -0
  218. package/dist/types/router/match-result.d.ts +114 -0
  219. package/dist/types/router/metrics.d.ts +6 -0
  220. package/dist/types/router/middleware-types.d.ts +74 -0
  221. package/dist/types/router/middleware.d.ts +116 -0
  222. package/dist/types/router/navigation-snapshot.d.ts +51 -0
  223. package/dist/types/router/params-util.d.ts +8 -0
  224. package/dist/types/router/parse-pattern.d.ts +38 -0
  225. package/dist/types/router/pattern-matching.d.ts +169 -0
  226. package/dist/types/router/prefetch-cache-ttl.d.ts +27 -0
  227. package/dist/types/router/prefetch-default.d.ts +28 -0
  228. package/dist/types/router/prefetch-limits.d.ts +20 -0
  229. package/dist/types/router/prerender-match.d.ts +53 -0
  230. package/dist/types/router/preview-match.d.ts +22 -0
  231. package/dist/types/router/request-classification.d.ts +104 -0
  232. package/dist/types/router/revalidation.d.ts +64 -0
  233. package/dist/types/router/route-snapshot.d.ts +112 -0
  234. package/dist/types/router/route-trie-builder.d.ts +77 -0
  235. package/dist/types/router/router-context.d.ts +137 -0
  236. package/dist/types/router/router-interfaces.d.ts +461 -0
  237. package/dist/types/router/router-options.d.ts +792 -0
  238. package/dist/types/router/router-registry.d.ts +15 -0
  239. package/dist/types/router/segment-resolution/fresh.d.ts +55 -0
  240. package/dist/types/router/segment-resolution/helpers.d.ts +93 -0
  241. package/dist/types/router/segment-resolution/loader-cache.d.ts +33 -0
  242. package/dist/types/router/segment-resolution/loader-mask.d.ts +44 -0
  243. package/dist/types/router/segment-resolution/loader-snapshot.d.ts +90 -0
  244. package/dist/types/router/segment-resolution/mask-nested.d.ts +53 -0
  245. package/dist/types/router/segment-resolution/revalidation.d.ts +85 -0
  246. package/dist/types/router/segment-resolution/static-store.d.ts +17 -0
  247. package/dist/types/router/segment-resolution/streamed-handler-telemetry.d.ts +16 -0
  248. package/dist/types/router/segment-resolution/view-transition-default.d.ts +27 -0
  249. package/dist/types/router/segment-resolution.d.ts +3 -0
  250. package/dist/types/router/segment-wrappers.d.ts +53 -0
  251. package/dist/types/router/state-cookie-name.d.ts +1 -0
  252. package/dist/types/router/substitute-pattern-params.d.ts +23 -0
  253. package/dist/types/router/telemetry-otel.d.ts +113 -0
  254. package/dist/types/router/telemetry.d.ts +216 -0
  255. package/dist/types/router/timeout.d.ts +107 -0
  256. package/dist/types/router/tracing.d.ts +139 -0
  257. package/dist/types/router/transition-when.d.ts +13 -0
  258. package/dist/types/router/trie-matching.d.ts +32 -0
  259. package/dist/types/router/types.d.ts +98 -0
  260. package/dist/types/router/url-params.d.ts +26 -0
  261. package/dist/types/router.d.ts +7 -0
  262. package/dist/types/rsc/capture-queue.d.ts +49 -0
  263. package/dist/types/rsc/full-payload.d.ts +22 -0
  264. package/dist/types/rsc/handler-context.d.ts +32 -0
  265. package/dist/types/rsc/handler.d.ts +9 -0
  266. package/dist/types/rsc/helpers.d.ts +127 -0
  267. package/dist/types/rsc/index.d.ts +17 -0
  268. package/dist/types/rsc/json-route-result.d.ts +20 -0
  269. package/dist/types/rsc/loader-fetch.d.ts +14 -0
  270. package/dist/types/rsc/manifest-init.d.ts +18 -0
  271. package/dist/types/rsc/nonce.d.ts +38 -0
  272. package/dist/types/rsc/origin-guard.d.ts +50 -0
  273. package/dist/types/rsc/progressive-enhancement.d.ts +19 -0
  274. package/dist/types/rsc/redirect-guard.d.ts +37 -0
  275. package/dist/types/rsc/render-pipeline.d.ts +148 -0
  276. package/dist/types/rsc/response-cache-serve.d.ts +46 -0
  277. package/dist/types/rsc/response-error.d.ts +19 -0
  278. package/dist/types/rsc/response-route-handler.d.ts +29 -0
  279. package/dist/types/rsc/routine-plan.d.ts +124 -0
  280. package/dist/types/rsc/rsc-rendering.d.ts +18 -0
  281. package/dist/types/rsc/runtime-warnings.d.ts +22 -0
  282. package/dist/types/rsc/server-action.d.ts +68 -0
  283. package/dist/types/rsc/shell-build-manifest.d.ts +90 -0
  284. package/dist/types/rsc/shell-capture-constants.d.ts +44 -0
  285. package/dist/types/rsc/shell-capture.d.ts +425 -0
  286. package/dist/types/rsc/shell-serve.d.ts +200 -0
  287. package/dist/types/rsc/ssr-setup.d.ts +73 -0
  288. package/dist/types/rsc/stream-idle.d.ts +60 -0
  289. package/dist/types/rsc/transition-gate.d.ts +23 -0
  290. package/dist/types/rsc/types.d.ts +353 -0
  291. package/dist/types/runtime-env.d.ts +1 -0
  292. package/dist/types/search-params.d.ts +125 -0
  293. package/dist/types/segment-content-promise.d.ts +13 -0
  294. package/dist/types/segment-fragments.d.ts +79 -0
  295. package/dist/types/segment-loader-promise.d.ts +22 -0
  296. package/dist/types/segment-system.d.ts +86 -0
  297. package/dist/types/serialize.d.ts +164 -0
  298. package/dist/types/server/context.d.ts +520 -0
  299. package/dist/types/server/cookie-parse.d.ts +10 -0
  300. package/dist/types/server/cookie-store.d.ts +107 -0
  301. package/dist/types/server/fetchable-loader-store.d.ts +20 -0
  302. package/dist/types/server/handle-store.d.ts +131 -0
  303. package/dist/types/server/loader-registry.d.ts +32 -0
  304. package/dist/types/server/request-context.d.ts +717 -0
  305. package/dist/types/server/root-layout.d.ts +3 -0
  306. package/dist/types/server.d.ts +16 -0
  307. package/dist/types/ssr/index.d.ts +289 -0
  308. package/dist/types/ssr/inject-rsc-eager.d.ts +3 -0
  309. package/dist/types/ssr/preinit-client-references.d.ts +71 -0
  310. package/dist/types/ssr/ssr-root.d.ts +100 -0
  311. package/dist/types/ssr-suspension-warning.d.ts +19 -0
  312. package/dist/types/static-handler.d.ts +71 -0
  313. package/dist/types/testing/cache-status.d.ts +63 -0
  314. package/dist/types/testing/collect-handle.d.ts +20 -0
  315. package/dist/types/testing/dispatch.d.ts +127 -0
  316. package/dist/types/testing/dom.entry.d.ts +15 -0
  317. package/dist/types/testing/e2e/fixture.d.ts +37 -0
  318. package/dist/types/testing/e2e/index.d.ts +31 -0
  319. package/dist/types/testing/e2e/matchers.d.ts +17 -0
  320. package/dist/types/testing/e2e/page-helpers.d.ts +86 -0
  321. package/dist/types/testing/e2e/parity.d.ts +111 -0
  322. package/dist/types/testing/e2e/server.d.ts +35 -0
  323. package/dist/types/testing/flight-matchers.d.ts +55 -0
  324. package/dist/types/testing/flight-normalize.d.ts +1 -0
  325. package/dist/types/testing/flight-tree.d.ts +192 -0
  326. package/dist/types/testing/flight.d.ts +115 -0
  327. package/dist/types/testing/flight.entry.d.ts +27 -0
  328. package/dist/types/testing/generated-routes.d.ts +66 -0
  329. package/dist/types/testing/index.d.ts +54 -0
  330. package/dist/types/testing/internal/context.d.ts +225 -0
  331. package/dist/types/testing/internal/flight-client-globals.d.ts +1 -0
  332. package/dist/types/testing/internal/seed-vars.d.ts +30 -0
  333. package/dist/types/testing/render-handler.d.ts +160 -0
  334. package/dist/types/testing/render-route.d.ts +265 -0
  335. package/dist/types/testing/run-loader.d.ts +195 -0
  336. package/dist/types/testing/run-middleware.d.ts +132 -0
  337. package/dist/types/testing/run-transition-when.d.ts +78 -0
  338. package/dist/types/testing/shell-status.d.ts +81 -0
  339. package/dist/types/testing/vitest-stubs/cloudflare-email.d.ts +6 -0
  340. package/dist/types/testing/vitest-stubs/cloudflare-workers.d.ts +13 -0
  341. package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +7 -0
  342. package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
  343. package/dist/types/testing/vitest.d.ts +205 -0
  344. package/dist/types/theme/ThemeProvider.d.ts +13 -0
  345. package/dist/types/theme/ThemeScript.d.ts +45 -0
  346. package/dist/types/theme/constants.d.ts +39 -0
  347. package/dist/types/theme/index.d.ts +29 -0
  348. package/dist/types/theme/theme-context.d.ts +21 -0
  349. package/dist/types/theme/theme-script.d.ts +26 -0
  350. package/dist/types/theme/types.d.ts +162 -0
  351. package/dist/types/theme/use-theme.d.ts +8 -0
  352. package/dist/types/types/boundaries.d.ts +115 -0
  353. package/dist/types/types/cache-types.d.ts +191 -0
  354. package/dist/types/types/error-types.d.ts +114 -0
  355. package/dist/types/types/global-namespace.d.ts +90 -0
  356. package/dist/types/types/handler-context.d.ts +658 -0
  357. package/dist/types/types/index.d.ts +11 -0
  358. package/dist/types/types/loader-types.d.ts +240 -0
  359. package/dist/types/types/request-scope.d.ts +93 -0
  360. package/dist/types/types/route-config.d.ts +105 -0
  361. package/dist/types/types/route-entry.d.ts +98 -0
  362. package/dist/types/types/segments.d.ts +254 -0
  363. package/dist/types/types.d.ts +1 -0
  364. package/dist/types/urls/include-helper.d.ts +17 -0
  365. package/dist/types/urls/include-provider.d.ts +27 -0
  366. package/dist/types/urls/index.d.ts +6 -0
  367. package/dist/types/urls/path-helper-types.d.ts +207 -0
  368. package/dist/types/urls/path-helper.d.ts +12 -0
  369. package/dist/types/urls/pattern-types.d.ts +166 -0
  370. package/dist/types/urls/response-types.d.ts +67 -0
  371. package/dist/types/urls/type-extraction.d.ts +157 -0
  372. package/dist/types/urls/urls-function.d.ts +24 -0
  373. package/dist/types/urls.d.ts +1 -0
  374. package/dist/types/use-loader.d.ts +150 -0
  375. package/dist/types/vercel/index.d.ts +10 -0
  376. package/dist/types/vercel/tracing.d.ts +71 -0
  377. package/dist/types/vite/debug.d.ts +80 -0
  378. package/dist/types/vite/discovery/bundle-postprocess.d.ts +12 -0
  379. package/dist/types/vite/discovery/client-urls-projection.d.ts +53 -0
  380. package/dist/types/vite/discovery/dev-prerender-cache.d.ts +65 -0
  381. package/dist/types/vite/discovery/discover-routers.d.ts +17 -0
  382. package/dist/types/vite/discovery/discovery-errors.d.ts +113 -0
  383. package/dist/types/vite/discovery/gate-state.d.ts +79 -0
  384. package/dist/types/vite/discovery/prerender-collection.d.ts +24 -0
  385. package/dist/types/vite/discovery/route-types-writer.d.ts +32 -0
  386. package/dist/types/vite/discovery/self-gen-tracking.d.ts +22 -0
  387. package/dist/types/vite/discovery/shell-prerender-phase.d.ts +40 -0
  388. package/dist/types/vite/discovery/state.d.ts +176 -0
  389. package/dist/types/vite/discovery/virtual-module-codegen.d.ts +15 -0
  390. package/dist/types/vite/encryption-key.d.ts +2 -0
  391. package/dist/types/vite/index.d.ts +11 -0
  392. package/dist/types/vite/inject-client-debug.d.ts +56 -0
  393. package/dist/types/vite/plugin-types.d.ts +325 -0
  394. package/dist/types/vite/plugins/cjs-to-esm.d.ts +6 -0
  395. package/dist/types/vite/plugins/client-ref-dedup.d.ts +29 -0
  396. package/dist/types/vite/plugins/client-ref-hashing.d.ts +35 -0
  397. package/dist/types/vite/plugins/cloudflare-protocol-stub.d.ts +64 -0
  398. package/dist/types/vite/plugins/expose-action-id.d.ts +18 -0
  399. package/dist/types/vite/plugins/expose-id-utils.d.ts +37 -0
  400. package/dist/types/vite/plugins/expose-ids/export-analysis.d.ts +19 -0
  401. package/dist/types/vite/plugins/expose-ids/handler-transform.d.ts +10 -0
  402. package/dist/types/vite/plugins/expose-ids/loader-transform.d.ts +8 -0
  403. package/dist/types/vite/plugins/expose-ids/router-transform.d.ts +13 -0
  404. package/dist/types/vite/plugins/expose-ids/types.d.ts +29 -0
  405. package/dist/types/vite/plugins/expose-internal-ids.d.ts +16 -0
  406. package/dist/types/vite/plugins/performance-tracks.d.ts +25 -0
  407. package/dist/types/vite/plugins/refresh-cmd.d.ts +20 -0
  408. package/dist/types/vite/plugins/server-ref-hashing.d.ts +24 -0
  409. package/dist/types/vite/plugins/server-reference-pattern.d.ts +1 -0
  410. package/dist/types/vite/plugins/use-cache-transform.d.ts +20 -0
  411. package/dist/types/vite/plugins/vercel-output.d.ts +85 -0
  412. package/dist/types/vite/plugins/version-injector.d.ts +21 -0
  413. package/dist/types/vite/plugins/version-plugin.d.ts +19 -0
  414. package/dist/types/vite/plugins/virtual-entries.d.ts +36 -0
  415. package/dist/types/vite/plugins/virtual-stub-plugin.d.ts +7 -0
  416. package/dist/types/vite/rango.d.ts +29 -0
  417. package/dist/types/vite/router-discovery.d.ts +23 -0
  418. package/dist/types/vite/utils/ast-handler-extract.d.ts +64 -0
  419. package/dist/types/vite/utils/banner.d.ts +2 -0
  420. package/dist/types/vite/utils/bundle-analysis.d.ts +28 -0
  421. package/dist/types/vite/utils/client-chunks.d.ts +55 -0
  422. package/dist/types/vite/utils/directive-prologue.d.ts +16 -0
  423. package/dist/types/vite/utils/forward-user-plugins.d.ts +37 -0
  424. package/dist/types/vite/utils/manifest-utils.d.ts +7 -0
  425. package/dist/types/vite/utils/package-resolution.d.ts +6 -0
  426. package/dist/types/vite/utils/prerender-utils.d.ts +32 -0
  427. package/dist/types/vite/utils/shared-utils.d.ts +68 -0
  428. package/dist/vite/index.js +10195 -4376
  429. package/package.json +119 -38
  430. package/skills/api-client/SKILL.md +211 -0
  431. package/skills/breadcrumbs/SKILL.md +114 -7
  432. package/skills/bundle-analysis/SKILL.md +159 -0
  433. package/skills/cache-guide/SKILL.md +232 -34
  434. package/skills/caching/SKILL.md +375 -19
  435. package/skills/catalog.json +289 -0
  436. package/skills/client-urls/SKILL.md +339 -0
  437. package/skills/cloudflare/SKILL.md +153 -0
  438. package/skills/cloudflare/agents/openai.yaml +4 -0
  439. package/skills/cloudflare/references/d1-and-local-dev.md +131 -0
  440. package/skills/cloudflare/references/streaming-and-deploy.md +107 -0
  441. package/skills/cloudflare/references/webhooks-and-crypto.md +147 -0
  442. package/skills/comparison/SKILL.md +50 -0
  443. package/skills/comparison/agents/openai.yaml +4 -0
  444. package/skills/comparison/references/framework-comparison.md +858 -0
  445. package/skills/composability/SKILL.md +124 -4
  446. package/skills/css/SKILL.md +76 -0
  447. package/skills/debug-manifest/SKILL.md +5 -11
  448. package/skills/defer-hydration/SKILL.md +235 -0
  449. package/skills/deployment-caching/SKILL.md +176 -0
  450. package/skills/document-cache/SKILL.md +116 -58
  451. package/skills/fonts/SKILL.md +1 -1
  452. package/skills/handler-use/SKILL.md +10 -10
  453. package/skills/hooks/SKILL.md +73 -725
  454. package/skills/hooks/data.md +282 -0
  455. package/skills/hooks/handle-and-actions.md +110 -0
  456. package/skills/hooks/navigation.md +110 -0
  457. package/skills/hooks/outlets.md +62 -0
  458. package/skills/hooks/state.md +228 -0
  459. package/skills/hooks/urls.md +172 -0
  460. package/skills/host-router/SKILL.md +129 -27
  461. package/skills/i18n/SKILL.md +1 -1
  462. package/skills/intercept/SKILL.md +50 -19
  463. package/skills/layout/SKILL.md +38 -19
  464. package/skills/links/SKILL.md +59 -11
  465. package/skills/loader/SKILL.md +324 -25
  466. package/skills/middleware/SKILL.md +56 -13
  467. package/skills/migrate-nextjs/SKILL.md +334 -42
  468. package/skills/migrate-nextjs/backend-host-swap.md +120 -0
  469. package/skills/migrate-react-router/SKILL.md +95 -675
  470. package/skills/migrate-react-router/component-migration.md +201 -0
  471. package/skills/migrate-react-router/data-and-actions.md +236 -0
  472. package/skills/migrate-react-router/route-mapping.md +284 -0
  473. package/skills/mime-routes/SKILL.md +55 -18
  474. package/skills/observability/SKILL.md +231 -0
  475. package/skills/parallel/SKILL.md +63 -11
  476. package/skills/ppr/SKILL.md +918 -0
  477. package/skills/prerender/SKILL.md +137 -71
  478. package/skills/rango/SKILL.md +325 -28
  479. package/skills/react-compiler/SKILL.md +168 -0
  480. package/skills/response-routes/SKILL.md +172 -52
  481. package/skills/route/SKILL.md +102 -9
  482. package/skills/router-setup/SKILL.md +69 -11
  483. package/skills/scripts/SKILL.md +189 -0
  484. package/skills/server-actions/SKILL.md +81 -44
  485. package/skills/shell-manifest/SKILL.md +194 -0
  486. package/skills/streams-and-websockets/SKILL.md +1 -1
  487. package/skills/tailwind/SKILL.md +28 -4
  488. package/skills/testing/SKILL.md +131 -0
  489. package/skills/testing/bindings.md +103 -0
  490. package/skills/testing/cache-prerender.md +172 -0
  491. package/skills/testing/client-components.md +131 -0
  492. package/skills/testing/e2e-parity.md +125 -0
  493. package/skills/testing/flight.md +91 -0
  494. package/skills/testing/handles.md +153 -0
  495. package/skills/testing/loader.md +130 -0
  496. package/skills/testing/middleware.md +99 -0
  497. package/skills/testing/render-handler.md +122 -0
  498. package/skills/testing/response-routes.md +95 -0
  499. package/skills/testing/reverse-and-types.md +85 -0
  500. package/skills/testing/server-actions.md +107 -0
  501. package/skills/testing/server-tree.md +128 -0
  502. package/skills/testing/setup.md +123 -0
  503. package/skills/theme/SKILL.md +9 -6
  504. package/skills/typesafety/SKILL.md +45 -634
  505. package/skills/typesafety/env-and-bindings.md +254 -0
  506. package/skills/typesafety/generated-files-and-cli.md +342 -0
  507. package/skills/typesafety/params-and-search.md +153 -0
  508. package/skills/typesafety/route-types.md +213 -0
  509. package/skills/use-cache/SKILL.md +121 -15
  510. package/skills/vercel/SKILL.md +149 -0
  511. package/skills/view-transitions/SKILL.md +133 -4
  512. package/src/__augment-tests__/augment.ts +81 -0
  513. package/src/__augment-tests__/augmented.check.ts +116 -0
  514. package/src/__internal.ts +0 -65
  515. package/src/bin/rango.ts +7 -3
  516. package/src/browser/action-coordinator.ts +53 -36
  517. package/src/browser/action-fence.ts +47 -0
  518. package/src/browser/app-shell.ts +14 -27
  519. package/src/browser/connection-warmup.ts +134 -0
  520. package/src/browser/cookie-name.ts +140 -0
  521. package/src/browser/dev-discovery.ts +66 -0
  522. package/src/browser/event-controller.ts +359 -167
  523. package/src/browser/history-state.ts +21 -0
  524. package/src/browser/index.ts +3 -3
  525. package/src/browser/invalidate-client-cache.ts +52 -0
  526. package/src/browser/link-interceptor.ts +469 -20
  527. package/src/browser/logging.ts +28 -0
  528. package/src/browser/merge-segment-loaders.ts +6 -4
  529. package/src/browser/navigation-bridge.ts +159 -129
  530. package/src/browser/navigation-client.ts +199 -96
  531. package/src/browser/navigation-store-handle.ts +38 -0
  532. package/src/browser/navigation-store.ts +165 -345
  533. package/src/browser/navigation-transaction.ts +9 -59
  534. package/src/browser/network-error-handler.ts +34 -7
  535. package/src/browser/notify-listeners.ts +22 -0
  536. package/src/browser/partial-update.ts +226 -161
  537. package/src/browser/prefetch/cache.ts +240 -97
  538. package/src/browser/prefetch/default-strategy.ts +74 -0
  539. package/src/browser/prefetch/fetch.ts +317 -51
  540. package/src/browser/prefetch/invalidation.ts +30 -0
  541. package/src/browser/prefetch/loader.ts +111 -0
  542. package/src/browser/prefetch/observer.ts +50 -22
  543. package/src/browser/prefetch/queue.ts +25 -7
  544. package/src/browser/prefetch/runtime.ts +6 -0
  545. package/src/browser/rango-state.ts +177 -114
  546. package/src/browser/react/Link.tsx +142 -79
  547. package/src/browser/react/NavigationProvider.tsx +202 -163
  548. package/src/browser/react/ScrollRestoration.tsx +10 -6
  549. package/src/browser/react/context.ts +4 -0
  550. package/src/browser/react/filter-segment-order.ts +17 -2
  551. package/src/browser/react/index.ts +0 -51
  552. package/src/browser/react/location-state-shared.ts +178 -8
  553. package/src/browser/react/location-state.ts +39 -14
  554. package/src/browser/react/use-action.ts +6 -15
  555. package/src/browser/react/use-handle.ts +17 -14
  556. package/src/browser/react/use-href.tsx +8 -1
  557. package/src/browser/react/use-link-status.ts +33 -8
  558. package/src/browser/react/use-navigation.ts +10 -5
  559. package/src/browser/react/use-params.ts +3 -6
  560. package/src/browser/react/use-reverse.ts +19 -12
  561. package/src/browser/react/use-router.ts +61 -17
  562. package/src/browser/react/use-search-params.ts +140 -22
  563. package/src/browser/react/use-segments.ts +0 -13
  564. package/src/browser/response-adapter.ts +99 -8
  565. package/src/browser/rsc-router.tsx +230 -42
  566. package/src/browser/scroll-restoration.ts +45 -33
  567. package/src/browser/segment-reconciler.ts +31 -21
  568. package/src/browser/segment-structure-assert.ts +2 -2
  569. package/src/browser/server-action-bridge.ts +262 -65
  570. package/src/browser/types.ts +126 -47
  571. package/src/browser/validate-redirect-origin.ts +43 -16
  572. package/src/build/collect-fallback-refs.ts +107 -0
  573. package/src/build/generate-manifest.ts +213 -184
  574. package/src/build/generate-route-types.ts +3 -1
  575. package/src/build/index.ts +11 -3
  576. package/src/build/merge-full-manifests.ts +161 -0
  577. package/src/build/prefix-tree-utils.ts +123 -0
  578. package/src/build/route-trie.ts +43 -281
  579. package/src/build/route-types/ast-route-extraction.ts +15 -8
  580. package/src/build/route-types/codegen.ts +16 -5
  581. package/src/build/route-types/include-resolution.ts +513 -64
  582. package/src/build/route-types/param-extraction.ts +6 -3
  583. package/src/build/route-types/per-module-writer.ts +33 -12
  584. package/src/build/route-types/router-processing.ts +312 -204
  585. package/src/build/route-types/scan-filter.ts +1 -1
  586. package/src/build/route-types/source-scan.ts +216 -0
  587. package/src/build/runtime-discovery.ts +32 -29
  588. package/src/cache/cache-error.ts +104 -0
  589. package/src/cache/cache-exec-scope.ts +47 -0
  590. package/src/cache/cache-key-utils.ts +73 -15
  591. package/src/cache/cache-policy.ts +108 -34
  592. package/src/cache/cache-runtime.ts +566 -121
  593. package/src/cache/cache-scope.ts +383 -105
  594. package/src/cache/cache-tag.ts +149 -0
  595. package/src/cache/cf/cf-base64.ts +33 -0
  596. package/src/cache/cf/cf-cache-constants.ts +134 -0
  597. package/src/cache/cf/cf-cache-store.ts +3084 -391
  598. package/src/cache/cf/cf-cache-types.ts +417 -0
  599. package/src/cache/cf/cf-kv-utils.ts +84 -0
  600. package/src/cache/cf/cf-tag-marker-memo.ts +108 -0
  601. package/src/cache/cf/cf-zone-purge.ts +101 -0
  602. package/src/cache/cf/index.ts +11 -16
  603. package/src/cache/document-cache.ts +184 -53
  604. package/src/cache/handle-snapshot.ts +92 -1
  605. package/src/cache/index.ts +32 -20
  606. package/src/cache/memory-segment-store.ts +286 -37
  607. package/src/cache/profile-registry.ts +46 -31
  608. package/src/cache/read-through-swr.ts +66 -16
  609. package/src/cache/search-params-filter.ts +118 -0
  610. package/src/cache/segment-codec.ts +80 -25
  611. package/src/cache/shell-snapshot.ts +516 -0
  612. package/src/cache/tag-invalidation.ts +230 -0
  613. package/src/cache/taint.ts +28 -9
  614. package/src/cache/types.ts +343 -100
  615. package/src/cache/vercel/index.ts +11 -0
  616. package/src/cache/vercel/vercel-cache-store.ts +1264 -0
  617. package/src/client-urls/client-root.tsx +168 -0
  618. package/src/client-urls/client-urls.ts +779 -0
  619. package/src/client-urls/navigation.ts +237 -0
  620. package/src/client-urls/revalidation-protocol.ts +56 -0
  621. package/src/client-urls/server-projection.ts +670 -0
  622. package/src/client-urls/types.ts +202 -0
  623. package/src/client.rsc.tsx +51 -22
  624. package/src/client.tsx +79 -68
  625. package/src/cloudflare/index.ts +11 -0
  626. package/src/cloudflare/tracing.ts +112 -0
  627. package/src/component-utils.ts +19 -0
  628. package/src/components/DefaultDocument.tsx +8 -2
  629. package/src/context-var.ts +18 -6
  630. package/src/decode-loader-results.ts +165 -0
  631. package/src/defer.ts +185 -0
  632. package/src/deps/ssr.ts +4 -2
  633. package/src/dev-discovery-protocol.ts +11 -0
  634. package/src/encode-kv.ts +49 -0
  635. package/src/errors.ts +44 -4
  636. package/src/escape-script.ts +52 -0
  637. package/src/handle.ts +67 -37
  638. package/src/handles/MetaTags.tsx +24 -53
  639. package/src/handles/Scripts.tsx +183 -0
  640. package/src/handles/breadcrumbs.ts +35 -8
  641. package/src/handles/deferred-resolution.ts +134 -0
  642. package/src/handles/is-thenable.ts +16 -0
  643. package/src/handles/meta.ts +14 -40
  644. package/src/handles/script.ts +244 -0
  645. package/src/host/cookie-handler.ts +9 -60
  646. package/src/host/errors.ts +13 -22
  647. package/src/host/index.ts +9 -2
  648. package/src/host/pattern-matcher.ts +23 -52
  649. package/src/host/router.ts +107 -99
  650. package/src/host/testing.ts +40 -27
  651. package/src/host/types.ts +37 -4
  652. package/src/host/utils.ts +1 -1
  653. package/src/href-client.ts +136 -24
  654. package/src/index.rsc.ts +105 -12
  655. package/src/index.ts +103 -14
  656. package/src/internal-debug.ts +11 -10
  657. package/src/loader-redirect.tsx +64 -0
  658. package/src/loader-store.ts +500 -0
  659. package/src/loader.rsc.ts +20 -13
  660. package/src/loader.ts +12 -11
  661. package/src/missing-id-error.ts +68 -0
  662. package/src/outlet-context.ts +20 -0
  663. package/src/outlet-provider.tsx +20 -6
  664. package/src/prerender/build-shell-capture.ts +453 -0
  665. package/src/prerender/param-hash.ts +16 -16
  666. package/src/prerender/shell-manifest-key.ts +20 -0
  667. package/src/prerender/store.ts +47 -38
  668. package/src/prerender.ts +81 -13
  669. package/src/redirect-origin.ts +172 -0
  670. package/src/regex-escape.ts +8 -0
  671. package/src/render-error-thrower.tsx +20 -0
  672. package/src/response-utils.ts +34 -0
  673. package/src/reverse.ts +16 -13
  674. package/src/root-error-boundary.tsx +1 -19
  675. package/src/route-content-wrapper.tsx +120 -78
  676. package/src/route-definition/dsl-helpers.ts +331 -315
  677. package/src/route-definition/helper-factories.ts +28 -140
  678. package/src/route-definition/helpers-types.ts +100 -61
  679. package/src/route-definition/index.ts +1 -2
  680. package/src/route-definition/redirect.ts +60 -28
  681. package/src/route-definition/resolve-handler-use.ts +6 -1
  682. package/src/route-definition/use-item-types.ts +29 -0
  683. package/src/route-map-builder.ts +102 -74
  684. package/src/route-types.ts +19 -46
  685. package/src/router/basename.ts +14 -0
  686. package/src/router/content-negotiation.ts +120 -30
  687. package/src/router/error-handling.ts +110 -29
  688. package/src/router/find-match.ts +129 -30
  689. package/src/router/handler-context.ts +37 -16
  690. package/src/router/instrument.ts +401 -0
  691. package/src/router/intercept-resolution.ts +98 -21
  692. package/src/router/lazy-includes.ts +82 -58
  693. package/src/router/loader-resolution.ts +426 -85
  694. package/src/router/logging.ts +0 -6
  695. package/src/router/manifest.ts +74 -40
  696. package/src/router/match-api.ts +90 -55
  697. package/src/router/match-context.ts +0 -22
  698. package/src/router/match-handlers.ts +267 -171
  699. package/src/router/match-middleware/background-revalidation.ts +40 -24
  700. package/src/router/match-middleware/cache-lookup.ts +316 -302
  701. package/src/router/match-middleware/cache-store.ts +134 -52
  702. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  703. package/src/router/match-middleware/segment-resolution.ts +0 -22
  704. package/src/router/match-pipelines.ts +1 -42
  705. package/src/router/match-result.ts +72 -94
  706. package/src/router/metrics.ts +17 -36
  707. package/src/router/middleware-types.ts +15 -114
  708. package/src/router/middleware.ts +276 -193
  709. package/src/router/navigation-snapshot.ts +51 -60
  710. package/src/router/params-util.ts +23 -0
  711. package/src/router/parse-pattern.ts +115 -0
  712. package/src/router/pattern-matching.ts +99 -152
  713. package/src/router/prefetch-cache-ttl.ts +51 -0
  714. package/src/router/prefetch-default.ts +59 -0
  715. package/src/router/prefetch-limits.ts +37 -0
  716. package/src/router/prerender-match.ts +159 -69
  717. package/src/router/preview-match.ts +6 -2
  718. package/src/router/request-classification.ts +50 -69
  719. package/src/router/revalidation.ts +134 -85
  720. package/src/router/route-snapshot.ts +14 -3
  721. package/src/router/route-trie-builder.ts +334 -0
  722. package/src/router/router-context.ts +6 -29
  723. package/src/router/router-interfaces.ts +168 -38
  724. package/src/router/router-options.ts +235 -11
  725. package/src/router/router-registry.ts +2 -5
  726. package/src/router/segment-resolution/fresh.ts +211 -88
  727. package/src/router/segment-resolution/helpers.ts +96 -18
  728. package/src/router/segment-resolution/loader-cache.ts +208 -39
  729. package/src/router/segment-resolution/loader-mask.ts +60 -0
  730. package/src/router/segment-resolution/loader-snapshot.ts +259 -0
  731. package/src/router/segment-resolution/mask-nested.ts +99 -0
  732. package/src/router/segment-resolution/revalidation.ts +277 -308
  733. package/src/router/segment-resolution/static-store.ts +55 -15
  734. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  735. package/src/router/segment-resolution/view-transition-default.ts +60 -0
  736. package/src/router/segment-resolution.ts +5 -1
  737. package/src/router/segment-wrappers.ts +6 -5
  738. package/src/router/state-cookie-name.ts +33 -0
  739. package/src/router/substitute-pattern-params.ts +54 -35
  740. package/src/router/telemetry-otel.ts +171 -200
  741. package/src/router/telemetry.ts +106 -20
  742. package/src/router/timeout.ts +53 -22
  743. package/src/router/tracing.ts +235 -0
  744. package/src/router/transition-when.ts +76 -0
  745. package/src/router/trie-matching.ts +171 -64
  746. package/src/router/types.ts +9 -63
  747. package/src/router/url-params.ts +13 -5
  748. package/src/router.ts +248 -77
  749. package/src/rsc/capture-queue.ts +218 -0
  750. package/src/rsc/full-payload.ts +77 -0
  751. package/src/rsc/handler-context.ts +4 -2
  752. package/src/rsc/handler.ts +566 -288
  753. package/src/rsc/helpers.ts +179 -9
  754. package/src/rsc/index.ts +2 -5
  755. package/src/rsc/json-route-result.ts +38 -0
  756. package/src/rsc/loader-fetch.ts +116 -40
  757. package/src/rsc/manifest-init.ts +55 -56
  758. package/src/rsc/nonce.ts +26 -1
  759. package/src/rsc/origin-guard.ts +39 -25
  760. package/src/rsc/progressive-enhancement.ts +376 -85
  761. package/src/rsc/redirect-guard.ts +102 -0
  762. package/src/rsc/render-pipeline.ts +611 -0
  763. package/src/rsc/response-cache-serve.ts +259 -0
  764. package/src/rsc/response-error.ts +79 -12
  765. package/src/rsc/response-route-handler.ts +73 -212
  766. package/src/rsc/routine-plan.ts +359 -0
  767. package/src/rsc/rsc-rendering.ts +1645 -172
  768. package/src/rsc/runtime-warnings.ts +23 -10
  769. package/src/rsc/server-action.ts +419 -140
  770. package/src/rsc/shell-build-manifest.ts +343 -0
  771. package/src/rsc/shell-capture-constants.ts +45 -0
  772. package/src/rsc/shell-capture.ts +2135 -0
  773. package/src/rsc/shell-serve.ts +350 -0
  774. package/src/rsc/ssr-setup.ts +124 -16
  775. package/src/rsc/stream-idle.ts +137 -0
  776. package/src/rsc/transition-gate.ts +86 -0
  777. package/src/rsc/types.ts +119 -7
  778. package/src/runtime-env.ts +18 -0
  779. package/src/search-params.ts +35 -30
  780. package/src/segment-fragments.ts +165 -0
  781. package/src/segment-loader-promise.ts +49 -4
  782. package/src/segment-system.tsx +405 -146
  783. package/src/serialize.ts +243 -0
  784. package/src/server/context.ts +426 -55
  785. package/src/server/cookie-parse.ts +32 -0
  786. package/src/server/cookie-store.ts +162 -15
  787. package/src/server/handle-store.ts +190 -70
  788. package/src/server/loader-registry.ts +33 -42
  789. package/src/server/request-context.ts +818 -177
  790. package/src/server.ts +7 -2
  791. package/src/ssr/index.tsx +737 -187
  792. package/src/ssr/inject-rsc-eager.ts +167 -0
  793. package/src/ssr/preinit-client-references.ts +106 -0
  794. package/src/ssr/ssr-root.tsx +332 -0
  795. package/src/ssr-suspension-warning.ts +67 -0
  796. package/src/static-handler.ts +28 -15
  797. package/src/testing/cache-status.ts +162 -0
  798. package/src/testing/collect-handle.ts +46 -0
  799. package/src/testing/dispatch.ts +951 -0
  800. package/src/testing/dom.entry.ts +22 -0
  801. package/src/testing/e2e/fixture.ts +188 -0
  802. package/src/testing/e2e/index.ts +147 -0
  803. package/src/testing/e2e/matchers.ts +35 -0
  804. package/src/testing/e2e/page-helpers.ts +319 -0
  805. package/src/testing/e2e/parity.ts +400 -0
  806. package/src/testing/e2e/server.ts +195 -0
  807. package/src/testing/flight-matchers.ts +97 -0
  808. package/src/testing/flight-normalize.ts +11 -0
  809. package/src/testing/flight-runtime.d.ts +57 -0
  810. package/src/testing/flight-tree.ts +682 -0
  811. package/src/testing/flight.entry.ts +52 -0
  812. package/src/testing/flight.ts +257 -0
  813. package/src/testing/generated-routes.ts +199 -0
  814. package/src/testing/index.ts +121 -0
  815. package/src/testing/internal/context.ts +380 -0
  816. package/src/testing/internal/flight-client-globals.ts +30 -0
  817. package/src/testing/internal/seed-vars.ts +54 -0
  818. package/src/testing/render-handler.ts +371 -0
  819. package/src/testing/render-route.tsx +667 -0
  820. package/src/testing/run-loader.ts +423 -0
  821. package/src/testing/run-middleware.ts +219 -0
  822. package/src/testing/run-transition-when.ts +197 -0
  823. package/src/testing/shell-status.ts +206 -0
  824. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  825. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  826. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  827. package/src/testing/vitest-stubs/version.ts +5 -0
  828. package/src/testing/vitest.ts +305 -0
  829. package/src/theme/ThemeProvider.tsx +56 -84
  830. package/src/theme/ThemeScript.tsx +7 -9
  831. package/src/theme/constants.ts +52 -13
  832. package/src/theme/index.ts +0 -7
  833. package/src/theme/theme-context.ts +1 -5
  834. package/src/theme/theme-script.ts +22 -21
  835. package/src/theme/use-theme.ts +0 -3
  836. package/src/types/boundaries.ts +19 -35
  837. package/src/types/cache-types.ts +13 -4
  838. package/src/types/error-types.ts +30 -90
  839. package/src/types/global-namespace.ts +54 -41
  840. package/src/types/handler-context.ts +111 -25
  841. package/src/types/index.ts +4 -10
  842. package/src/types/loader-types.ts +71 -7
  843. package/src/types/request-scope.ts +8 -22
  844. package/src/types/route-config.ts +20 -52
  845. package/src/types/route-entry.ts +3 -6
  846. package/src/types/segments.ts +138 -14
  847. package/src/urls/include-helper.ts +38 -64
  848. package/src/urls/include-provider.ts +71 -0
  849. package/src/urls/index.ts +2 -11
  850. package/src/urls/path-helper-types.ts +88 -25
  851. package/src/urls/path-helper.ts +30 -110
  852. package/src/urls/pattern-types.ts +101 -19
  853. package/src/urls/response-types.ts +20 -19
  854. package/src/urls/type-extraction.ts +98 -154
  855. package/src/urls/urls-function.ts +1 -19
  856. package/src/use-loader.tsx +379 -110
  857. package/src/vercel/index.ts +11 -0
  858. package/src/vercel/tracing.ts +89 -0
  859. package/src/vite/debug.ts +1 -0
  860. package/src/vite/discovery/bundle-postprocess.ts +18 -14
  861. package/src/vite/discovery/client-urls-projection.ts +322 -0
  862. package/src/vite/discovery/dev-prerender-cache.ts +117 -0
  863. package/src/vite/discovery/discover-routers.ts +152 -153
  864. package/src/vite/discovery/discovery-errors.ts +255 -0
  865. package/src/vite/discovery/prerender-collection.ts +77 -69
  866. package/src/vite/discovery/route-types-writer.ts +40 -84
  867. package/src/vite/discovery/shell-prerender-phase.ts +402 -0
  868. package/src/vite/discovery/state.ts +110 -6
  869. package/src/vite/discovery/virtual-module-codegen.ts +226 -87
  870. package/src/vite/encryption-key.ts +29 -0
  871. package/src/vite/index.ts +12 -0
  872. package/src/vite/inject-client-debug.ts +88 -0
  873. package/src/vite/plugin-types.ts +271 -10
  874. package/src/vite/plugins/cjs-to-esm.ts +11 -19
  875. package/src/vite/plugins/client-ref-dedup.ts +281 -30
  876. package/src/vite/plugins/client-ref-hashing.ts +12 -11
  877. package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
  878. package/src/vite/plugins/expose-action-id.ts +51 -100
  879. package/src/vite/plugins/expose-id-utils.ts +88 -55
  880. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  881. package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
  882. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  883. package/src/vite/plugins/expose-ids/router-transform.ts +98 -26
  884. package/src/vite/plugins/expose-internal-ids.ts +103 -68
  885. package/src/vite/plugins/performance-tracks.ts +9 -16
  886. package/src/vite/plugins/refresh-cmd.ts +1 -1
  887. package/src/vite/plugins/server-ref-hashing.ts +74 -0
  888. package/src/vite/plugins/server-reference-pattern.ts +10 -0
  889. package/src/vite/plugins/use-cache-transform.ts +26 -49
  890. package/src/vite/plugins/vercel-output.ts +384 -0
  891. package/src/vite/plugins/version-injector.ts +24 -40
  892. package/src/vite/plugins/version-plugin.ts +45 -40
  893. package/src/vite/plugins/virtual-entries.ts +202 -30
  894. package/src/vite/rango.ts +241 -126
  895. package/src/vite/router-discovery.ts +1123 -143
  896. package/src/vite/utils/ast-handler-extract.ts +26 -35
  897. package/src/vite/utils/bundle-analysis.ts +10 -15
  898. package/src/vite/utils/client-chunks.ts +184 -0
  899. package/src/vite/utils/directive-prologue.ts +40 -0
  900. package/src/vite/utils/forward-user-plugins.ts +171 -0
  901. package/src/vite/utils/manifest-utils.ts +1 -59
  902. package/src/vite/utils/package-resolution.ts +2 -73
  903. package/src/vite/utils/prerender-utils.ts +96 -50
  904. package/src/vite/utils/shared-utils.ts +162 -43
  905. package/src/browser/action-response-classifier.ts +0 -99
  906. package/src/browser/react/use-client-cache.ts +0 -58
  907. package/src/browser/shallow.ts +0 -40
  908. package/src/handles/index.ts +0 -7
  909. package/src/network-error-thrower.tsx +0 -23
  910. package/src/router/middleware-cookies.ts +0 -55
@@ -7,13 +7,11 @@
7
7
  * and progressive enhancement (no-JS form submissions).
8
8
  */
9
9
 
10
- import { createElement } from "react";
11
- import { RouteNotFoundError } from "../errors.js";
10
+ import { isRouteNotFoundError } from "../errors.js";
12
11
  import { matchMiddleware, executeMiddleware } from "../router/middleware.js";
13
12
  import {
14
13
  runWithRequestContext,
15
14
  setRequestContextParams,
16
- requireRequestContext,
17
15
  getRequestContext,
18
16
  _getRequestContext,
19
17
  createRequestContext,
@@ -31,32 +29,47 @@ import {
31
29
  interceptRedirectForPartial,
32
30
  buildRouteMiddlewareEntries,
33
31
  } from "./helpers.js";
34
- import { isWebSocketUpgradeResponse } from "../response-utils.js";
32
+ import { renderRscFlightStage, renderRscResponse } from "./render-pipeline.js";
33
+ import { guardOutgoingRedirect } from "./redirect-guard.js";
34
+ import {
35
+ resolveSoftRedirectUrl,
36
+ resolveExternalRedirect,
37
+ safeSameOriginLanding,
38
+ } from "../redirect-origin.js";
39
+ import { resolvedHandleStream } from "../handles/deferred-resolution.js";
40
+ import {
41
+ isWebSocketUpgradeResponse,
42
+ appendVaryAccept,
43
+ } from "../response-utils.js";
35
44
  import {
36
45
  handleResponseRoute,
37
46
  type ResponseRouteMatch,
38
47
  } from "./response-route-handler.js";
39
- import { generateNonce, nonce as nonceToken } from "./nonce.js";
48
+ import { nonce as nonceToken, resolveProviderNonce } from "./nonce.js";
40
49
  import { VERSION } from "@rangojs/router:version";
41
50
  import type { ErrorPhase } from "../types.js";
42
51
  import type { RouterRequestInput } from "../router/router-interfaces.js";
43
- import { invokeOnError } from "../router/error-handling.js";
52
+ import {
53
+ invokeOnError,
54
+ resolveDefaultNotFound,
55
+ } from "../router/error-handling.js";
44
56
  import {
45
57
  createReverseFunction,
46
58
  stripInternalParams,
47
59
  } from "../router/handler-context.js";
48
- import { getRouterContext } from "../router/router-context.js";
49
- import { resolveSink, safeEmit } from "../router/telemetry.js";
50
60
  import { contextSet } from "../context-var.js";
51
61
  import {
52
62
  hasCachedManifest,
53
- getRouteTrie,
54
- getPrecomputedEntries,
55
63
  waitForManifestReady,
56
64
  getRouterManifest,
57
65
  getRouterTrie,
58
66
  } from "../route-map-builder.js";
59
67
  import type { HandlerContext } from "./handler-context.js";
68
+ import type { CacheErrorCategory } from "../cache/cache-error.js";
69
+ import {
70
+ compileSearchParamsFilter,
71
+ type SearchParamsFilter,
72
+ } from "../cache/search-params-filter.js";
60
73
  import type { SegmentCacheStore } from "../cache/types.js";
61
74
  import { buildRouterTrieFromUrlpatterns } from "./manifest-init.js";
62
75
  import { handleProgressiveEnhancement } from "./progressive-enhancement.js";
@@ -66,23 +79,32 @@ import {
66
79
  type ActionContinuation,
67
80
  } from "./server-action.js";
68
81
  import { handleLoaderFetch } from "./loader-fetch.js";
69
- import { checkRequestOrigin, type OriginCheckPhase } from "./origin-guard.js";
82
+ import { applyStreamIdleTimeout } from "./stream-idle.js";
83
+ import {
84
+ checkRequestOrigin,
85
+ ORIGIN_CHECK_PHASE_BY_MODE,
86
+ } from "./origin-guard.js";
70
87
  import { handleRscRendering } from "./rsc-rendering.js";
71
88
  import {
72
89
  withTimeout,
90
+ isTimeoutEnabled,
73
91
  RouterTimeoutError,
74
92
  createDefaultTimeoutResponse,
75
93
  type TimeoutPhase,
94
+ type RenderTimeoutContext,
76
95
  } from "../router/timeout.js";
77
96
  import {
78
97
  createMetricsStore,
79
98
  appendMetric,
80
99
  buildMetricsTiming,
81
100
  } from "../router/metrics.js";
101
+ import { observePhase, PHASES } from "../router/instrument.js";
102
+ import { safeEmit, resolveSink, getRequestId } from "../router/telemetry.js";
82
103
  import {
83
104
  startSSRSetup,
84
- getSSRSetup,
105
+ createSsrHtmlStage,
85
106
  mayNeedSSR,
107
+ isRscRequest,
86
108
  SSR_SETUP_VAR,
87
109
  } from "./ssr-setup.js";
88
110
  import {
@@ -90,6 +112,7 @@ import {
90
112
  type RequestPlan,
91
113
  type ExecutableRequestPlan,
92
114
  } from "../router/request-classification.js";
115
+ import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
93
116
 
94
117
  /**
95
118
  * Create an RSC request handler.
@@ -124,12 +147,35 @@ import {
124
147
  * });
125
148
  * ```
126
149
  */
150
+
151
+ /**
152
+ * Response that tells the client to do a full document navigation. Shared by
153
+ * the terminal reload plans (version-mismatch and app-switch): an empty 200
154
+ * carrying X-RSC-Reload, which the client turns into window.location.href.
155
+ */
156
+ function createReloadResponse(reloadUrl: string) {
157
+ return createResponseWithMergedHeaders(null, {
158
+ status: 200,
159
+ headers: {
160
+ "X-RSC-Reload": reloadUrl,
161
+ "content-type": "text/x-component;charset=utf-8",
162
+ },
163
+ });
164
+ }
165
+
127
166
  export function createRSCHandler<
128
167
  TEnv = unknown,
129
168
  TRoutes extends Record<string, string> = Record<string, string>,
130
169
  >(options: CreateRSCHandlerOptions<TEnv, TRoutes>) {
131
170
  const { router, version = VERSION, nonce: nonceProvider } = options;
132
171
 
172
+ // Handler-owned registry of explicit per-scope stores from cache({ store }).
173
+ // Lives in the closure so it is scoped per handler (multi-router deployments
174
+ // get separate registries) and accumulates every explicit store this handler
175
+ // resolves across requests. updateTag()/revalidateTag() iterate it to reach
176
+ // stores not covered by the app-level ctx._cacheStore.
177
+ const explicitTaggedStores = new Set<SegmentCacheStore>();
178
+
133
179
  // Use provided deps or default to @vitejs/plugin-rsc/rsc exports
134
180
  const deps = options.deps ?? rscDeps;
135
181
  const {
@@ -204,7 +250,44 @@ export function createRSCHandler<
204
250
  actionId?: string,
205
251
  ): Promise<Response> {
206
252
  const timeoutError = new RouterTimeoutError(phase, durationMs);
253
+ const requestContext = _getRequestContext<TEnv>();
254
+ const cursor = requestContext?._renderForeground;
255
+ const render: RenderTimeoutContext | undefined =
256
+ phase === "render-start" && cursor
257
+ ? {
258
+ mode: cursor.mode,
259
+ phase: cursor.phase,
260
+ state: cursor.state,
261
+ completed: cursor.completed,
262
+ total: cursor.total,
263
+ ...(cursor.phaseStartedAt !== undefined && {
264
+ phaseDurationMs: performance.now() - cursor.phaseStartedAt,
265
+ }),
266
+ }
267
+ : undefined;
268
+ const trace =
269
+ phase === "render-start" ? requestContext?._activeRoutine : undefined;
270
+ const activeEntries = trace?.active() ?? [];
271
+ const activeStep = activeEntries.at(-1);
272
+ const activeAt = performance.now();
273
+ const routineSnapshot =
274
+ trace && activeStep
275
+ ? {
276
+ name: trace.name,
277
+ path: activeEntries.map((entry) => entry.name),
278
+ durationMs: activeAt - activeStep.startedAt,
279
+ }
280
+ : undefined;
281
+
282
+ if (INTERNAL_RANGO_DEBUG && trace && activeStep) {
283
+ console.log(
284
+ `[routine] TIMEOUT ${request.method} ${url.pathname} (${trace.name})\n${trace.formatActive(activeEntries, activeAt)}`,
285
+ );
286
+ }
207
287
 
288
+ // Each surface gets its OWN shallow render snapshot. A consumer that mutates
289
+ // its copy must not corrupt what the other two observe. The internal-debug
290
+ // routine snapshot is bounded metadata sent only to onError.
208
291
  callOnError(timeoutError, phase === "action" ? "action" : "handler", {
209
292
  request,
210
293
  url,
@@ -212,26 +295,28 @@ export function createRSCHandler<
212
295
  routeKey,
213
296
  actionId,
214
297
  handledByBoundary: false,
215
- metadata: { timeout: true, phase, durationMs },
298
+ metadata: {
299
+ timeout: true,
300
+ phase,
301
+ durationMs,
302
+ ...(render && { render: { ...render } }),
303
+ ...(routineSnapshot && { routine: routineSnapshot }),
304
+ },
216
305
  });
217
306
 
218
- try {
219
- const routerCtx = getRouterContext();
220
- if (routerCtx?.telemetry) {
221
- safeEmit(resolveSink(routerCtx.telemetry), {
222
- type: "request.timeout" as const,
223
- timestamp: performance.now(),
224
- requestId: routerCtx.requestId,
225
- phase,
226
- pathname: url.pathname,
227
- routeKey,
228
- actionId,
229
- durationMs,
230
- customHandler: !!router.onTimeout,
231
- });
232
- }
233
- } catch {
234
- // Router context may not be available
307
+ if (router.telemetry) {
308
+ safeEmit(resolveSink(router.telemetry), {
309
+ type: "request.timeout",
310
+ timestamp: performance.now(),
311
+ requestId: getRequestId(request),
312
+ phase,
313
+ pathname: url.pathname,
314
+ routeKey,
315
+ actionId,
316
+ durationMs,
317
+ customHandler: !!router.onTimeout,
318
+ ...(render && { render: { ...render } }),
319
+ });
235
320
  }
236
321
 
237
322
  if (router.onTimeout) {
@@ -244,6 +329,7 @@ export function createRSCHandler<
244
329
  routeKey,
245
330
  actionId,
246
331
  durationMs,
332
+ ...(render && { render: { ...render } }),
247
333
  });
248
334
  } catch (e) {
249
335
  if (process.env.NODE_ENV !== "production") {
@@ -260,20 +346,66 @@ export function createRSCHandler<
260
346
  * Build a 200 Flight response that carries a redirect URL and optional state.
261
347
  * Used when a partial/action request results in a redirect -- fetch
262
348
  * auto-follows 3xx so we send the redirect as payload metadata instead.
349
+ *
350
+ * The redirect URL is resolved with {@link resolveSoftRedirectUrl} against
351
+ * the current request origin so an unsafe target never leaves as Flight
352
+ * metadata (client validators remain defense-in-depth).
263
353
  */
264
354
  function createRedirectFlightResponse(
265
355
  redirectUrl: string,
266
356
  locationState?: Record<string, unknown>,
357
+ external?: boolean,
267
358
  ): Response {
359
+ const reqCtx = _getRequestContext<TEnv>();
360
+ const requestOrigin =
361
+ reqCtx?.url.origin ?? new URL("http://localhost").origin;
362
+ // Resolve with the same policy as 3xx guardOutgoingRedirect. Keep
363
+ // external:true only when the external scheme check passed; a neutralized
364
+ // landing (javascript:/blocked) must not advertise external.
365
+ let resolvedUrl: string;
366
+ let resolvedExternal = false;
367
+ if (external) {
368
+ const ext = resolveExternalRedirect(redirectUrl, requestOrigin);
369
+ if (ext !== null) {
370
+ resolvedUrl = ext;
371
+ resolvedExternal = true;
372
+ } else {
373
+ resolvedUrl = safeSameOriginLanding(router.basename);
374
+ }
375
+ } else {
376
+ resolvedUrl = resolveSoftRedirectUrl(
377
+ redirectUrl,
378
+ requestOrigin,
379
+ router.basename,
380
+ false,
381
+ );
382
+ }
268
383
  const redirectPayload: RscPayload = {
269
384
  metadata: {
270
- pathname: redirectUrl,
385
+ pathname: resolvedUrl,
271
386
  segments: [],
272
- redirect: { url: redirectUrl },
387
+ redirect: {
388
+ url: resolvedUrl,
389
+ ...(resolvedExternal && { external: true }),
390
+ },
273
391
  ...(locationState && { locationState }),
274
392
  },
275
393
  };
276
- const rscStream = renderToReadableStream<RscPayload>(redirectPayload);
394
+ const rscStream = reqCtx
395
+ ? renderRscFlightStage({
396
+ ctx: { renderToReadableStream, callOnError },
397
+ request: reqCtx.request,
398
+ url: reqCtx.url,
399
+ env: reqCtx.env,
400
+ payload: redirectPayload,
401
+ tracking: {
402
+ mode: reqCtx.url.searchParams.has("_rsc_action")
403
+ ? "action-revalidation"
404
+ : "partial",
405
+ routeKey: reqCtx._routeName,
406
+ },
407
+ }).stream
408
+ : renderToReadableStream<RscPayload>(redirectPayload);
277
409
  return createResponseWithMergedHeaders(rscStream, {
278
410
  status: 200,
279
411
  headers: { "content-type": "text/x-component;charset=utf-8" },
@@ -285,6 +417,7 @@ export function createRSCHandler<
285
417
  const handlerCtx: HandlerContext<TEnv> = {
286
418
  router,
287
419
  version,
420
+ devDiscoveryEpoch: router.__devDiscoveryEpoch,
288
421
  renderToReadableStream,
289
422
  decodeReply,
290
423
  createTemporaryReferenceSet,
@@ -323,12 +456,12 @@ export function createRSCHandler<
323
456
  }
324
457
  }
325
458
 
326
- // Resolve nonce if provider is set
459
+ // Resolve nonce if provider is set. false/"" normalize to undefined —
460
+ // the per-request opt-out (resolveProviderNonce).
327
461
  const nonceStart = performance.now();
328
462
  let nonce: string | undefined;
329
463
  if (nonceProvider) {
330
- const result = await nonceProvider(request, env);
331
- nonce = result === true ? generateNonce() : result;
464
+ nonce = resolveProviderNonce(await nonceProvider(request, env));
332
465
  }
333
466
  const nonceDur = performance.now() - nonceStart;
334
467
 
@@ -355,6 +488,7 @@ export function createRSCHandler<
355
488
  // Priority: options.cache (handler override) > router.cache (router default)
356
489
  // Store is enabled only if: config provided, enabled, and no ?__no_cache query param
357
490
  let cacheStore: SegmentCacheStore | undefined;
491
+ let searchParamsFilter: SearchParamsFilter | undefined;
358
492
  const cacheOption = options.cache ?? router.cache;
359
493
  if (cacheOption && !url.searchParams.has("__no_cache")) {
360
494
  const cacheConfig =
@@ -364,6 +498,9 @@ export function createRSCHandler<
364
498
 
365
499
  if (cacheConfig.enabled !== false) {
366
500
  cacheStore = cacheConfig.store;
501
+ searchParamsFilter = compileSearchParamsFilter(
502
+ cacheConfig.searchParams,
503
+ );
367
504
  }
368
505
  }
369
506
 
@@ -421,10 +558,25 @@ export function createRSCHandler<
421
558
  url,
422
559
  variables,
423
560
  cacheStore,
561
+ searchParamsFilter,
562
+ explicitTaggedStores,
424
563
  cacheProfiles: router.cacheProfiles,
425
564
  executionContext: executionCtx,
426
565
  themeConfig: router.themeConfig,
566
+ stateCookieName: router.resolvedStateCookieName,
567
+ version,
427
568
  });
569
+ // Gate on the SAME enabled-semantics withTimeout uses (isTimeoutEnabled):
570
+ // a `renderStartMs: 0` / negative opt-out disables the timeout, so the
571
+ // driver's cursor bookkeeping (which only the timeout reads) must be off too.
572
+ requestContext._renderDiagnosticsEnabled = isTimeoutEnabled(
573
+ router.timeouts.renderStartMs,
574
+ );
575
+ // Thread the true request entry timestamp onto the context so a metrics
576
+ // store created MID-request (ctx.debugPerformance() / getMetricsStore) anchors
577
+ // to the real start, not the opt-in moment — phases that began earlier then
578
+ // report non-negative offsets. Set unconditionally: debug may be enabled later.
579
+ requestContext._handlerStart = handlerStart;
428
580
  if (earlyMetricsStore) {
429
581
  requestContext._debugPerformance = true;
430
582
  requestContext._metricsStore = earlyMetricsStore;
@@ -433,7 +585,7 @@ export function createRSCHandler<
433
585
  // can surface non-fatal errors through the router's onError callback.
434
586
  requestContext._reportBackgroundError = (
435
587
  error: unknown,
436
- category: string,
588
+ category: CacheErrorCategory,
437
589
  ) => {
438
590
  callOnError(error, "cache", {
439
591
  request,
@@ -465,82 +617,206 @@ export function createRSCHandler<
465
617
  // - Streaming
466
618
  // Store basename on request context (scoped per-request via existing ALS)
467
619
  requestContext._basename = router.basename;
620
+ requestContext._routerId = router.id;
621
+
622
+ // Resolved span tracing for this request (read at each traced phase).
623
+ requestContext._tracing = router.tracing;
624
+
625
+ // The "rango.request" span is opened inside the request context so the
626
+ // Cloudflare runner can read executionContext.tracing, and so every nested
627
+ // phase span (and the platform's automatic KV/D1/fetch spans) nests under
628
+ // it. Construction-bound: the span ends when the Response is built, never
629
+ // wrapping the streamed body. metric:false — handler:total is metered
630
+ // directly below (a grand total incl. the pre-context bootstrap timings).
631
+ // When tracing is off this is a direct pass-through.
632
+ return runWithRequestContext(requestContext, () =>
633
+ observePhase(PHASES.request, async (span) => {
634
+ span.setAttribute("http.method", request.method);
635
+ // The matched route template is not known until match() runs later, so
636
+ // emit the concrete path as url.path (low-level), NOT http.route — the
637
+ // latter is reserved for the low-cardinality template (OTel convention).
638
+ span.setAttribute("url.path", url.pathname);
639
+
640
+ // Core handler logic (wrapped by middleware)
641
+ const coreHandler = async (): Promise<Response> => {
642
+ return coreRequestHandler(request, env, url, variables, nonce);
643
+ };
468
644
 
469
- return runWithRequestContext(requestContext, async () => {
470
- // Core handler logic (wrapped by middleware)
471
- const coreHandler = async (): Promise<Response> => {
472
- return coreRequestHandler(request, env, url, variables, nonce);
473
- };
645
+ // Execute middleware chain if any, otherwise call core handler
646
+ // directly; the response is finalized below, inside the response span.
647
+ const hasMiddleware = matchedMiddleware.length > 0;
648
+ const downstream = hasMiddleware
649
+ ? await executeMiddleware(
650
+ matchedMiddleware,
651
+ request,
652
+ env,
653
+ variables,
654
+ coreHandler,
655
+ createReverseFunction(getRequiredRouteMap()),
656
+ )
657
+ : await coreHandler();
658
+
659
+ // Final response construction + host handoff, wrapped in rango.response
660
+ // — the explicit stream-handoff marker. The callback is synchronous, so
661
+ // the span ends immediately before the handler returns the response to
662
+ // the host; it never reads or wraps response.body. A downstream throw
663
+ // skips it entirely (no response exists to hand off).
664
+ return observePhase(PHASES.response, (responseSpan) => {
665
+ let response: Response;
666
+ if (hasMiddleware) {
667
+ if (
668
+ url.searchParams.has("_rsc_partial") ||
669
+ url.searchParams.has("_rsc_action")
670
+ ) {
671
+ const intercepted = interceptRedirectForPartial(
672
+ downstream,
673
+ createRedirectFlightResponse,
674
+ { requestOrigin: url.origin, basename: router.basename },
675
+ );
676
+ response = intercepted ?? finalizeResponse(downstream);
677
+ } else {
678
+ response = finalizeResponse(downstream);
679
+ }
680
+ } else {
681
+ response = downstream;
682
+ }
474
683
 
475
- // Execute middleware chain if any, otherwise call core handler directly
476
- let response: Response;
477
- if (matchedMiddleware.length > 0) {
478
- const mwResponse = await executeMiddleware(
479
- matchedMiddleware,
480
- request,
481
- env,
482
- variables,
483
- coreHandler,
484
- createReverseFunction(getRequiredRouteMap()),
485
- );
684
+ // Finalize metrics after all middleware (including post-next work)
685
+ // has completed so :post spans are captured in the timeline.
686
+ // Handler timing parts are always emitted (even without debug metrics)
687
+ // so non-debug requests still get bootstrap Server-Timing entries.
688
+ const handlerTimingArr: string[] = variables.__handlerTiming || [];
689
+ // Preserve any existing Server-Timing set by response routes or middleware
690
+ const existingTiming = response.headers.get("Server-Timing");
691
+ const timingParts = existingTiming
692
+ ? [existingTiming, ...handlerTimingArr]
693
+ : [...handlerTimingArr];
694
+
695
+ const metricsStore = requestContext._metricsStore;
696
+ if (metricsStore) {
697
+ // When the store was created at handler start (earlyMetricsStore),
698
+ // handler:total covers the full request. When ctx.debugPerformance()
699
+ // created the store mid-request its requestStart is now the threaded
700
+ // _handlerStart (== handlerStart), so both branches yield the true
701
+ // request entry; reading the store's own anchor keeps this correct even
702
+ // if a store ever lands without the threading (falls back to its start).
703
+ const totalStart = earlyMetricsStore
704
+ ? handlerStart
705
+ : metricsStore.requestStart;
706
+ appendMetric(
707
+ metricsStore,
708
+ "handler:total",
709
+ totalStart,
710
+ performance.now() - totalStart,
711
+ );
712
+ const metricsTiming = buildMetricsTiming(
713
+ request.method,
714
+ url.pathname,
715
+ metricsStore,
716
+ );
717
+ if (metricsTiming) timingParts.push(metricsTiming);
718
+ }
486
719
 
487
- if (
488
- url.searchParams.has("_rsc_partial") ||
489
- url.searchParams.has("_rsc_action")
490
- ) {
491
- const intercepted = interceptRedirectForPartial(
492
- mwResponse,
493
- createRedirectFlightResponse,
494
- );
495
- response = intercepted ?? finalizeResponse(mwResponse);
496
- } else {
497
- response = finalizeResponse(mwResponse);
498
- }
499
- } else {
500
- response = await coreHandler();
501
- }
720
+ const fullTiming = timingParts.join(", ");
721
+ if (fullTiming && !isWebSocketUpgradeResponse(response)) {
722
+ try {
723
+ response.headers.set("Server-Timing", fullTiming);
724
+ } catch {
725
+ // Immutable headers (e.g. a passed-through platform Response) — drop
726
+ // the timing header, never the response. Instrumentation must not
727
+ // 500 a request.
728
+ }
729
+ }
502
730
 
503
- // Finalize metrics after all middleware (including post-next work)
504
- // has completed so :post spans are captured in the timeline.
505
- // Handler timing parts are always emitted (even without debug metrics)
506
- // so non-debug requests still get bootstrap Server-Timing entries.
507
- const handlerTimingArr: string[] = variables.__handlerTiming || [];
508
- // Preserve any existing Server-Timing set by response routes or middleware
509
- const existingTiming = response.headers.get("Server-Timing");
510
- const timingParts = existingTiming
511
- ? [existingTiming, ...handlerTimingArr]
512
- : [...handlerTimingArr];
513
-
514
- const metricsStore = requestContext._metricsStore;
515
- if (metricsStore) {
516
- // When the store was created at handler start (earlyMetricsStore),
517
- // handler:total covers the full request. When ctx.debugPerformance()
518
- // created the store mid-request, use its requestStart to avoid a
519
- // negative startTime offset.
520
- const totalStart = earlyMetricsStore
521
- ? handlerStart
522
- : metricsStore.requestStart;
523
- appendMetric(
524
- metricsStore,
525
- "handler:total",
526
- totalStart,
527
- performance.now() - totalStart,
528
- );
529
- const metricsTiming = buildMetricsTiming(
530
- request.method,
531
- url.pathname,
532
- metricsStore,
533
- );
534
- if (metricsTiming) timingParts.push(metricsTiming);
535
- }
731
+ // Single open-redirect chokepoint: every response (PE, full-page,
732
+ // middleware short-circuit, response-route) funnels through here, so
733
+ // guarding browser-followed (3xx) redirects once covers them all and any
734
+ // future redirect exit. Soft SPA/Flight redirects are 200/204 and pass
735
+ // through untouched (validated client-side instead).
736
+ const guarded = guardOutgoingRedirect(
737
+ response,
738
+ url.origin,
739
+ router.basename,
740
+ );
536
741
 
537
- const fullTiming = timingParts.join(", ");
538
- if (fullTiming && !isWebSocketUpgradeResponse(response)) {
539
- response.headers.set("Server-Timing", fullTiming);
540
- }
742
+ // Stream-idle watchdog (opt-in via timeouts.streamIdleMs): bounds
743
+ // end-to-end idle flow on the streamed body — see rsc/stream-idle.ts
744
+ // for the semantics. Applied at this finalization chokepoint so every
745
+ // streaming exit is covered; websocket upgrades must never be
746
+ // reconstructed and bodiless responses have nothing to bound. The
747
+ // trip fires POST-handoff (the request ALS may be gone), so it
748
+ // reports via the eagerly captured surfaces — callOnError +
749
+ // router.telemetry directly — mirroring handleStore.onError.
750
+ // onTimeout does NOT apply: the response already left the handler,
751
+ // so no replacement Response can be served mid-stream.
752
+ let finalResponse = guarded;
753
+ const streamIdleMs = router.timeouts.streamIdleMs;
754
+ // Websocket check FIRST: a workerd upgrade response must never have
755
+ // its body getter poked (same invariant as the body_kind attribute
756
+ // below).
757
+ if (
758
+ isTimeoutEnabled(streamIdleMs) &&
759
+ !isWebSocketUpgradeResponse(guarded) &&
760
+ guarded.body
761
+ ) {
762
+ const routeKey = requestContext._routeName;
763
+ finalResponse = applyStreamIdleTimeout(
764
+ guarded,
765
+ streamIdleMs!,
766
+ (tripInfo) => {
767
+ callOnError(tripInfo.error, "handler", {
768
+ request,
769
+ url,
770
+ env,
771
+ routeKey,
772
+ handledByBoundary: false,
773
+ metadata: {
774
+ timeout: true,
775
+ phase: "stream-idle",
776
+ durationMs: tripInfo.totalMs,
777
+ },
778
+ });
779
+ if (router.telemetry) {
780
+ safeEmit(resolveSink(router.telemetry), {
781
+ type: "request.timeout",
782
+ timestamp: performance.now(),
783
+ requestId: getRequestId(request),
784
+ phase: "stream-idle",
785
+ pathname: url.pathname,
786
+ routeKey,
787
+ durationMs: tripInfo.totalMs,
788
+ customHandler: false,
789
+ });
790
+ }
791
+ },
792
+ );
793
+ }
541
794
 
542
- return response;
543
- });
795
+ // Attributes describe the response actually handed to the host (after
796
+ // unsafe-redirect replacement), low-cardinality only. body_kind checks
797
+ // the websocket marker before the body getter so a workerd upgrade
798
+ // Response is never poked; `.body` is a getter access, not a read of
799
+ // the stream.
800
+ responseSpan.setAttribute(
801
+ "http.response.status_code",
802
+ finalResponse.status,
803
+ );
804
+ responseSpan.setAttribute(
805
+ "rango.response.mode",
806
+ requestContext._requestMode ?? "middleware-short-circuit",
807
+ );
808
+ responseSpan.setAttribute(
809
+ "rango.response.body_kind",
810
+ isWebSocketUpgradeResponse(finalResponse)
811
+ ? "websocket"
812
+ : finalResponse.body === null
813
+ ? "empty"
814
+ : "stream",
815
+ );
816
+ return finalResponse;
817
+ });
818
+ }),
819
+ );
544
820
  };
545
821
 
546
822
  // Core request handling logic (separated for middleware wrapping).
@@ -555,35 +831,6 @@ export function createRSCHandler<
555
831
  ): Promise<Response> {
556
832
  const handlerTiming: string[] = variables.__handlerTiming || [];
557
833
 
558
- // Debug manifest endpoint: handled before classification since it
559
- // doesn't need a route match and needs trie access from the closure.
560
- const isDev = process.env.NODE_ENV !== "production";
561
- if (
562
- url.searchParams.has("__debug_manifest") &&
563
- (isDev || router.allowDebugManifest)
564
- ) {
565
- const trie = getRouterTrie(router.id) ?? getRouteTrie();
566
- const routeManifest = getRequiredRouteMap();
567
- const { extractAncestryFromTrie } =
568
- await import("../build/route-trie.js");
569
- return new Response(
570
- JSON.stringify(
571
- {
572
- routerId: router.id,
573
- routeManifest,
574
- routeAncestry: trie ? extractAncestryFromTrie(trie) : {},
575
- routeTrie: trie,
576
- precomputedEntries: getPrecomputedEntries(),
577
- },
578
- null,
579
- 2,
580
- ),
581
- {
582
- headers: { "Content-Type": "application/json" },
583
- },
584
- );
585
- }
586
-
587
834
  // ---- 1. Classify ----
588
835
  // classifyRequest may throw RouteNotFoundError for unknown routes.
589
836
  // In that case, fall through to a full-render plan so the pipeline
@@ -597,10 +844,7 @@ export function createRSCHandler<
597
844
  routerId: router.id,
598
845
  });
599
846
  } catch (error) {
600
- if (
601
- error instanceof RouteNotFoundError ||
602
- (error instanceof Error && error.name === "RouteNotFoundError")
603
- ) {
847
+ if (isRouteNotFoundError(error)) {
604
848
  // Let the render path handle 404 — match()/matchPartial() will
605
849
  // re-throw RouteNotFoundError and the catch block in
606
850
  // executeRenderWithMiddleware renders the not-found page.
@@ -626,6 +870,12 @@ export function createRSCHandler<
626
870
  const classifyDur = performance.now() - classifyStart;
627
871
  handlerTiming.push(`handler-classify;dur=${classifyDur.toFixed(2)}`);
628
872
 
873
+ // Stash the classified mode for the rango.response span (rango.response.mode)
874
+ // — the outer handler tail cannot see the plan. Stays unset when middleware
875
+ // short-circuits before core execution runs (reported as
876
+ // "middleware-short-circuit").
877
+ getRequestContext()._requestMode = plan.mode;
878
+
629
879
  // ---- 2. Terminal plans (no execution needed) ----
630
880
  if (plan.mode === "redirect") {
631
881
  // Redirects are handled by the pipeline (match/matchPartial),
@@ -641,24 +891,18 @@ export function createRSCHandler<
641
891
  console.log(
642
892
  `[RSC] Version mismatch: client=${url.searchParams.get("_rsc_v")}, server=${version}. Forcing reload.`,
643
893
  );
644
- return createResponseWithMergedHeaders(null, {
645
- status: 200,
646
- headers: {
647
- "X-RSC-Reload": plan.reloadUrl,
648
- "content-type": "text/x-component;charset=utf-8",
649
- },
650
- });
894
+ return createReloadResponse(plan.reloadUrl);
895
+ }
896
+
897
+ if (plan.mode === "app-switch") {
898
+ // Cross-app SPA navigation crossed a host-router app boundary. Force a
899
+ // real document navigation so the target app's document is re-established
900
+ // (stylesheets, theme, warmup, prefetch-TTL). See request-classification.
901
+ return createReloadResponse(plan.reloadUrl);
651
902
  }
652
903
 
653
904
  // ---- 3. Origin guard (gate for action/loader/PE modes) ----
654
- const originPhase: OriginCheckPhase | null =
655
- plan.mode === "action"
656
- ? "action"
657
- : plan.mode === "loader"
658
- ? "loader"
659
- : plan.mode === "pe-render"
660
- ? "pe-form"
661
- : null;
905
+ const originPhase = ORIGIN_CHECK_PHASE_BY_MODE[plan.mode];
662
906
  if (originPhase) {
663
907
  const originResult = await checkRequestOrigin(
664
908
  request,
@@ -686,22 +930,17 @@ export function createRSCHandler<
686
930
  },
687
931
  });
688
932
 
689
- try {
690
- const routerCtx = getRouterContext();
691
- if (routerCtx?.telemetry) {
692
- safeEmit(resolveSink(routerCtx.telemetry), {
693
- type: "request.origin-rejected" as const,
694
- timestamp: performance.now(),
695
- requestId: routerCtx.requestId,
696
- method: request.method,
697
- pathname: url.pathname,
698
- phase: originPhase,
699
- origin: request.headers.get("origin"),
700
- host: request.headers.get("host"),
701
- });
702
- }
703
- } catch {
704
- // Router context may not be available
933
+ if (router.telemetry) {
934
+ safeEmit(resolveSink(router.telemetry), {
935
+ type: "request.origin-rejected",
936
+ timestamp: performance.now(),
937
+ requestId: getRequestId(request),
938
+ method: request.method,
939
+ pathname: url.pathname,
940
+ phase: originPhase,
941
+ origin: request.headers.get("origin"),
942
+ host: request.headers.get("host"),
943
+ });
705
944
  }
706
945
 
707
946
  return originResult;
@@ -732,11 +971,11 @@ export function createRSCHandler<
732
971
  nonce: string | undefined,
733
972
  ): Promise<Response> {
734
973
  // Common setup
735
- const handleStore = requireRequestContext()._handleStore;
974
+ const handleStore = getRequestContext()._handleStore;
736
975
 
737
976
  // Wire up error reporting for late streaming-handle failures
738
977
  handleStore.onError = (error: Error) => {
739
- const reqCtx = requireRequestContext();
978
+ const reqCtx = getRequestContext();
740
979
  callOnError(error, "handler", {
741
980
  request,
742
981
  url,
@@ -744,22 +983,17 @@ export function createRSCHandler<
744
983
  params: reqCtx.params as Record<string, string>,
745
984
  handledByBoundary: true,
746
985
  });
747
- try {
748
- const routerCtx = getRouterContext();
749
- if (routerCtx?.telemetry) {
750
- safeEmit(resolveSink(routerCtx.telemetry), {
751
- type: "handler.error" as const,
752
- timestamp: performance.now(),
753
- requestId: routerCtx.requestId,
754
- error,
755
- handledByBoundary: true,
756
- pathname: url.pathname,
757
- routeKey: reqCtx._routeName,
758
- params: reqCtx.params as Record<string, string>,
759
- });
760
- }
761
- } catch {
762
- // Router context may not be available (e.g. prerender path)
986
+ if (router.telemetry) {
987
+ safeEmit(resolveSink(router.telemetry), {
988
+ type: "handler.error",
989
+ timestamp: performance.now(),
990
+ requestId: getRequestId(request),
991
+ error,
992
+ handledByBoundary: true,
993
+ pathname: url.pathname,
994
+ routeKey: reqCtx._routeName,
995
+ params: reqCtx.params as Record<string, string>,
996
+ });
763
997
  }
764
998
  };
765
999
 
@@ -768,7 +1002,7 @@ export function createRSCHandler<
768
1002
  // instead of calling resolveRoute again.
769
1003
  if (plan.mode !== "redirect") {
770
1004
  setRequestContextParams(plan.route.params, plan.route.routeKey);
771
- requireRequestContext()._classifiedRoute = plan.route;
1005
+ getRequestContext()._classifiedRoute = plan.route;
772
1006
  }
773
1007
 
774
1008
  const routeReverse = createReverseFunction(getRequiredRouteMap());
@@ -809,7 +1043,9 @@ export function createRSCHandler<
809
1043
  }
810
1044
  const response = responseOutcome.result;
811
1045
  if (plan.negotiated && !isWebSocketUpgradeResponse(response)) {
812
- response.headers.append("Vary", "Accept");
1046
+ // handleResponseRoute (callHandlerWithVary) already appends Vary: Accept
1047
+ // for negotiated responses; dedup so we don't emit Vary: Accept, Accept.
1048
+ appendVaryAccept(response);
813
1049
  }
814
1050
  return response;
815
1051
  }
@@ -817,16 +1053,41 @@ export function createRSCHandler<
817
1053
  // SSR setup: kick off in parallel for modes that need HTML rendering.
818
1054
  // Placed after response-route short-circuit so response/mime routes
819
1055
  // never pay for SSR work.
820
- if (plan.mode !== "loader" && mayNeedSSR(request, url)) {
821
- variables[SSR_SETUP_VAR] = startSSRSetup(
1056
+ //
1057
+ // Only kick off when the request will actually render HTML, so the
1058
+ // eager loadSSRModule() + user resolveStreaming() are not started (and
1059
+ // never consumed) for a request that returns an RSC stream — that wasted
1060
+ // work also leaves an orphaned Promise.all that can reject (D7). PE form
1061
+ // submissions always render HTML (handleProgressiveEnhancement renders via
1062
+ // getSSRSetup regardless of Accept). For full/partial-render and action,
1063
+ // the render-time HTML decision is exactly !isRscRequest — mayNeedSSR is
1064
+ // the coarse transport pre-filter, isRscRequest adds the partial/__rsc
1065
+ // flags; both share the same Accept rule (acceptsFlightExplicitly in
1066
+ // ssr-setup.ts), so the Accept call cannot drift between them. Both must
1067
+ // pass.
1068
+ const willRenderHtml =
1069
+ plan.mode === "pe-render" ||
1070
+ (mayNeedSSR(request, url) &&
1071
+ !isRscRequest(request, url, plan.mode === "partial-render"));
1072
+ if (plan.mode !== "loader" && willRenderHtml) {
1073
+ const ssrSetup = startSSRSetup(
822
1074
  handlerCtx,
823
1075
  request,
824
1076
  env,
825
1077
  url,
826
1078
  router.debugPerformance
827
- ? () => requireRequestContext()._metricsStore
1079
+ ? () => getRequestContext()._metricsStore
828
1080
  : undefined,
829
1081
  );
1082
+ variables[SSR_SETUP_VAR] = ssrSetup;
1083
+
1084
+ // A handler can short-circuit before HTML rendering consumes this promise
1085
+ // (for example, by returning a redirect). Workerd cancels untracked dynamic
1086
+ // imports at the request boundary; retaining that cancelled promise in the
1087
+ // production SSR module memo makes every later document request hang.
1088
+ // Extending the request lifetime lets the shared setup settle without
1089
+ // delaying the short-circuit response.
1090
+ getRequestContext().executionContext?.waitUntil(ssrSetup);
830
1091
  }
831
1092
 
832
1093
  // ---- Loader fetch ----
@@ -865,14 +1126,20 @@ export function createRSCHandler<
865
1126
  if (plan.mode === "action") {
866
1127
  let actionContinuation: ActionContinuation | undefined;
867
1128
  try {
1129
+ // Instrument the action execution as its own phase (action:<actionId> +
1130
+ // rango.action), so a POST shows the mutation time AND which action ran,
1131
+ // not just the downstream revalidation render. The action's own
1132
+ // loaders/fetches nest under rango.action.
868
1133
  const actionOutcome = await withTimeout(
869
- executeServerAction(
870
- handlerCtx,
871
- request,
872
- env,
873
- url,
874
- plan.actionId,
875
- handleStore,
1134
+ observePhase(PHASES.action(plan.actionId), () =>
1135
+ executeServerAction(
1136
+ handlerCtx,
1137
+ request,
1138
+ env,
1139
+ url,
1140
+ plan.actionId,
1141
+ handleStore,
1142
+ ),
876
1143
  ),
877
1144
  router.timeouts.actionMs,
878
1145
  "action",
@@ -925,47 +1192,17 @@ export function createRSCHandler<
925
1192
  );
926
1193
  }
927
1194
 
928
- // ---- Full render / Partial render (or PE that fell through) ----
929
- if (plan.mode === "full-render" || plan.mode === "partial-render") {
930
- const isPartial = plan.mode === "partial-render";
931
- return executeRenderWithMiddleware(
932
- plan.route.routeMiddleware,
933
- plan.negotiated,
934
- plan.route.routeKey,
935
- routeReverse,
936
- request,
937
- env,
938
- url,
939
- variables,
940
- nonce,
941
- handleStore,
942
- isPartial,
943
- );
944
- }
945
-
946
- // PE that fell through (handleProgressiveEnhancement returned null)
947
- // falls back to full render
948
- if (plan.mode === "pe-render") {
949
- return executeRenderWithMiddleware(
950
- plan.route.routeMiddleware,
951
- false,
952
- plan.route.routeKey,
953
- routeReverse,
954
- request,
955
- env,
956
- url,
957
- variables,
958
- nonce,
959
- handleStore,
960
- false,
961
- );
962
- }
963
-
964
- // Redirect plan that wasn't handled above (full-page redirect — let
965
- // the pipeline handle it via match() which returns { redirect: url })
1195
+ // Full render, partial render, fallen-through PE, and full-page redirect all
1196
+ // render through the same middleware-wrapped path. Only full/partial-render
1197
+ // carry negotiation + the partial flag; pe/redirect render plainly.
1198
+ const isPartial = plan.mode === "partial-render";
1199
+ const negotiated =
1200
+ plan.mode === "full-render" || plan.mode === "partial-render"
1201
+ ? plan.negotiated
1202
+ : false;
966
1203
  return executeRenderWithMiddleware(
967
1204
  plan.route.routeMiddleware,
968
- false,
1205
+ negotiated,
969
1206
  plan.route.routeKey,
970
1207
  routeReverse,
971
1208
  request,
@@ -974,7 +1211,7 @@ export function createRSCHandler<
974
1211
  variables,
975
1212
  nonce,
976
1213
  handleStore,
977
- false,
1214
+ isPartial,
978
1215
  );
979
1216
  }
980
1217
 
@@ -991,7 +1228,7 @@ export function createRSCHandler<
991
1228
  url: URL,
992
1229
  variables: Record<string, any>,
993
1230
  nonce: string | undefined,
994
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
1231
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
995
1232
  isPartial: boolean,
996
1233
  actionContinuation?: ActionContinuation,
997
1234
  ): Promise<Response> {
@@ -1019,16 +1256,27 @@ export function createRSCHandler<
1019
1256
  );
1020
1257
  }
1021
1258
  if (negotiated && !isWebSocketUpgradeResponse(response)) {
1022
- response.headers.append("Vary", "Accept");
1259
+ // handleRscRendering bakes `accept` into the RSC response's Vary list;
1260
+ // dedup so the negotiated append does not list accept twice.
1261
+ appendVaryAccept(response);
1023
1262
  }
1024
1263
  return response;
1025
1264
  } catch (error) {
1026
1265
  // Check if middleware/handler returned Response
1027
1266
  if (error instanceof Response) {
1267
+ // An action revalidation render is delivered to the client over the
1268
+ // same Flight-parsing path as a partial navigation, so a Response
1269
+ // thrown during it must be converted exactly like a partial one
1270
+ // (raw 200 -> hard-nav hint, 3xx -> Flight redirect). Without this,
1271
+ // the no-middleware path returns the raw Response (the with-middleware
1272
+ // path is already covered by the isPartial || actionContinuation
1273
+ // guard below).
1274
+ const treatAsPartial = isPartial || actionContinuation != null;
1275
+
1028
1276
  // During partial (client-side navigation), a 200 Response from a handler
1029
1277
  // means the route serves raw content (JSON, text, etc.), not JSX.
1030
1278
  // Signal the browser to hard-navigate so it renders the raw response.
1031
- if (isPartial && error.status === 200) {
1279
+ if (treatAsPartial && error.status === 200) {
1032
1280
  console.warn(
1033
1281
  `[RSC] Route handler at ${url.pathname} returned a Response during client-side navigation. ` +
1034
1282
  `Falling back to hard navigation. Use data-external on the <Link> to avoid the extra round-trip.`,
@@ -1042,10 +1290,11 @@ export function createRSCHandler<
1042
1290
  });
1043
1291
  }
1044
1292
 
1045
- if (isPartial) {
1293
+ if (treatAsPartial) {
1046
1294
  const intercepted = interceptRedirectForPartial(
1047
1295
  error,
1048
1296
  createRedirectFlightResponse,
1297
+ { requestOrigin: url.origin, basename: router.basename },
1049
1298
  );
1050
1299
  if (intercepted) return intercepted;
1051
1300
  }
@@ -1054,10 +1303,7 @@ export function createRSCHandler<
1054
1303
  }
1055
1304
 
1056
1305
  // Render 404 page for unmatched routes
1057
- const isRouteNotFound =
1058
- error instanceof RouteNotFoundError ||
1059
- (error instanceof Error && error.name === "RouteNotFoundError");
1060
- if (isRouteNotFound) {
1306
+ if (isRouteNotFoundError(error)) {
1061
1307
  callOnError(error, "routing", {
1062
1308
  request,
1063
1309
  url,
@@ -1065,11 +1311,12 @@ export function createRSCHandler<
1065
1311
  handledByBoundary: true,
1066
1312
  });
1067
1313
 
1068
- const notFoundOption = router.notFound;
1069
- const notFoundComponent =
1070
- typeof notFoundOption === "function"
1071
- ? notFoundOption({ pathname: url.pathname })
1072
- : (notFoundOption ?? createElement("h1", null, "Not Found"));
1314
+ // No boundary to consult: an unmatched route has no entry chain, so
1315
+ // this always lands on the router option or the shared default.
1316
+ const notFoundComponent = resolveDefaultNotFound(
1317
+ router.notFound,
1318
+ url.pathname,
1319
+ );
1073
1320
 
1074
1321
  const notFoundSegment = {
1075
1322
  id: "notFound",
@@ -1088,51 +1335,81 @@ export function createRSCHandler<
1088
1335
  segments: [notFoundSegment],
1089
1336
  matched: [],
1090
1337
  diff: [],
1338
+ // Shape parity with buildFullPayload (rsc-rendering.ts): the 404
1339
+ // payload carries params/resolvedIds/prefetchCacheTTL the same way a
1340
+ // matched full render does. resolvedIds mirrors the rendered segment
1341
+ // list (the single notFound segment) like the error-boundary path
1342
+ // (match-api.ts) does for its boundary segment.
1343
+ resolvedIds: [notFoundSegment.id],
1344
+ params: {},
1091
1345
  isPartial: false,
1092
1346
  rootLayout: router.rootLayout,
1093
- handles: handleStore.stream(),
1347
+ // Full (404) render: resolve deferred handle values server-side.
1348
+ handles: resolvedHandleStream(handleStore),
1094
1349
  version,
1350
+ prefetchCacheTTL: router.prefetchCacheTTL,
1351
+ prefetchCacheSize: router.prefetchCacheSize,
1352
+ prefetchConcurrency: router.prefetchConcurrency,
1353
+ defaultPrefetch: router.defaultPrefetch,
1354
+ stateCookieName: router.resolvedStateCookieName,
1095
1355
  themeConfig: router.themeConfig,
1096
1356
  warmupEnabled: router.warmupEnabled,
1097
- initialTheme: requireRequestContext().theme,
1357
+ strictMode: router.strictMode,
1358
+ initialTheme: getRequestContext().theme,
1098
1359
  },
1099
1360
  };
1100
1361
 
1101
- const rscStream = renderToReadableStream(payload, {
1102
- onError: (error: unknown) => {
1103
- callOnError(error, "rendering", { request, url, env });
1104
- },
1105
- });
1106
-
1107
- const isRscRequest =
1108
- isPartial ||
1109
- (!request.headers.get("accept")?.includes("text/html") &&
1110
- !url.searchParams.has("__html")) ||
1111
- url.searchParams.has("__rsc");
1112
-
1113
- if (isRscRequest) {
1114
- return createResponseWithMergedHeaders(rscStream, {
1115
- status: 404,
1116
- headers: { "content-type": "text/x-component;charset=utf-8" },
1117
- });
1118
- }
1119
-
1120
- const [ssrModule, streamMode] = await getSSRSetup(
1121
- handlerCtx,
1362
+ const isNotFoundFlightResponse = isRscRequest(
1122
1363
  request,
1123
- env,
1124
1364
  url,
1125
- requireRequestContext()._metricsStore,
1365
+ isPartial,
1366
+ );
1367
+ const notFoundStageTracking = {
1368
+ mode: isPartial ? ("partial" as const) : ("full" as const),
1369
+ routeKey,
1370
+ };
1371
+ return renderRscResponse(
1372
+ {
1373
+ ctx: handlerCtx,
1374
+ request,
1375
+ url,
1376
+ env,
1377
+ payload,
1378
+ // The 404 path historically records no rsc-serialize metric (it
1379
+ // used the standalone Flight constructor, whose gate was opt-in);
1380
+ // opt out explicitly since renderRscResponse defaults the gate on.
1381
+ recordSerializeMetric: false,
1382
+ init: isNotFoundFlightResponse
1383
+ ? {
1384
+ status: 404,
1385
+ headers: {
1386
+ "content-type": "text/x-component;charset=utf-8",
1387
+ // Router identity for the client's pre-decode integrity
1388
+ // check; a same-app 404 applies in place.
1389
+ "X-RSC-Router-Id": router.id,
1390
+ },
1391
+ }
1392
+ : {
1393
+ status: 404,
1394
+ headers: {
1395
+ "content-type": "text/html;charset=utf-8",
1396
+ },
1397
+ },
1398
+ tracking: notFoundStageTracking,
1399
+ },
1400
+ isNotFoundFlightResponse
1401
+ ? undefined
1402
+ : {
1403
+ html: createSsrHtmlStage({
1404
+ ctx: handlerCtx,
1405
+ request,
1406
+ env,
1407
+ url,
1408
+ metricsStore: getRequestContext()._metricsStore,
1409
+ render: { nonce },
1410
+ }),
1411
+ },
1126
1412
  );
1127
- const htmlStream = await ssrModule.renderHTML(rscStream, {
1128
- nonce,
1129
- streamMode,
1130
- });
1131
-
1132
- return createResponseWithMergedHeaders(htmlStream, {
1133
- status: 404,
1134
- headers: { "content-type": "text/html;charset=utf-8" },
1135
- });
1136
1413
  }
1137
1414
 
1138
1415
  // Report unhandled errors
@@ -1163,6 +1440,7 @@ export function createRSCHandler<
1163
1440
  const intercepted = interceptRedirectForPartial(
1164
1441
  mwResponse,
1165
1442
  createRedirectFlightResponse,
1443
+ { requestOrigin: url.origin, basename: router.basename },
1166
1444
  );
1167
1445
  if (intercepted) return intercepted;
1168
1446
  }