@rangojs/router 0.0.0-experimental.f2d1a2f1 → 0.0.0-experimental.f4a8e8de

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 (1301) hide show
  1. package/AGENTS.md +8 -4
  2. package/README.md +318 -821
  3. package/dist/bin/rango.js +925 -271
  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 +23 -0
  62. package/dist/types/browser/react/use-search-params.d.ts +19 -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 +616 -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 +503 -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 +57 -0
  125. package/dist/types/client-urls/types.d.ts +132 -0
  126. package/dist/types/client.d.ts +191 -0
  127. package/dist/types/client.rsc.d.ts +41 -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 +18 -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 +24 -0
  172. package/dist/types/outlet-provider.d.ts +14 -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 +67 -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 +81 -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 +393 -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 +28 -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 +406 -0
  286. package/dist/types/rsc/shell-serve.d.ts +189 -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 +328 -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 +510 -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 +707 -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 +233 -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 +69 -0
  311. package/dist/types/static-handler.d.ts +71 -0
  312. package/dist/types/testing/cache-status.d.ts +63 -0
  313. package/dist/types/testing/collect-handle.d.ts +20 -0
  314. package/dist/types/testing/dispatch.d.ts +127 -0
  315. package/dist/types/testing/dom.entry.d.ts +15 -0
  316. package/dist/types/testing/e2e/fixture.d.ts +37 -0
  317. package/dist/types/testing/e2e/index.d.ts +31 -0
  318. package/dist/types/testing/e2e/matchers.d.ts +17 -0
  319. package/dist/types/testing/e2e/page-helpers.d.ts +86 -0
  320. package/dist/types/testing/e2e/parity.d.ts +111 -0
  321. package/dist/types/testing/e2e/server.d.ts +35 -0
  322. package/dist/types/testing/flight-matchers.d.ts +55 -0
  323. package/dist/types/testing/flight-normalize.d.ts +1 -0
  324. package/dist/types/testing/flight-tree.d.ts +192 -0
  325. package/dist/types/testing/flight.d.ts +115 -0
  326. package/dist/types/testing/flight.entry.d.ts +27 -0
  327. package/dist/types/testing/generated-routes.d.ts +66 -0
  328. package/dist/types/testing/index.d.ts +54 -0
  329. package/dist/types/testing/internal/context.d.ts +225 -0
  330. package/dist/types/testing/internal/flight-client-globals.d.ts +1 -0
  331. package/dist/types/testing/internal/seed-vars.d.ts +30 -0
  332. package/dist/types/testing/render-handler.d.ts +160 -0
  333. package/dist/types/testing/render-route.d.ts +265 -0
  334. package/dist/types/testing/run-loader.d.ts +195 -0
  335. package/dist/types/testing/run-middleware.d.ts +132 -0
  336. package/dist/types/testing/run-transition-when.d.ts +78 -0
  337. package/dist/types/testing/shell-status.d.ts +81 -0
  338. package/dist/types/testing/vitest-stubs/cloudflare-email.d.ts +6 -0
  339. package/dist/types/testing/vitest-stubs/cloudflare-workers.d.ts +13 -0
  340. package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +7 -0
  341. package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
  342. package/dist/types/testing/vitest.d.ts +205 -0
  343. package/dist/types/theme/ThemeProvider.d.ts +13 -0
  344. package/dist/types/theme/ThemeScript.d.ts +45 -0
  345. package/dist/types/theme/constants.d.ts +39 -0
  346. package/dist/types/theme/index.d.ts +29 -0
  347. package/dist/types/theme/theme-context.d.ts +21 -0
  348. package/dist/types/theme/theme-script.d.ts +26 -0
  349. package/dist/types/theme/types.d.ts +162 -0
  350. package/dist/types/theme/use-theme.d.ts +8 -0
  351. package/dist/types/types/boundaries.d.ts +110 -0
  352. package/dist/types/types/cache-types.d.ts +191 -0
  353. package/dist/types/types/error-types.d.ts +114 -0
  354. package/dist/types/types/global-namespace.d.ts +90 -0
  355. package/dist/types/types/handler-context.d.ts +658 -0
  356. package/dist/types/types/index.d.ts +11 -0
  357. package/dist/types/types/loader-types.d.ts +208 -0
  358. package/dist/types/types/request-scope.d.ts +93 -0
  359. package/dist/types/types/route-config.d.ts +105 -0
  360. package/dist/types/types/route-entry.d.ts +98 -0
  361. package/dist/types/types/segments.d.ts +246 -0
  362. package/dist/types/types.d.ts +1 -0
  363. package/dist/types/urls/include-helper.d.ts +17 -0
  364. package/dist/types/urls/include-provider.d.ts +27 -0
  365. package/dist/types/urls/index.d.ts +6 -0
  366. package/dist/types/urls/path-helper-types.d.ts +198 -0
  367. package/dist/types/urls/path-helper.d.ts +12 -0
  368. package/dist/types/urls/pattern-types.d.ts +166 -0
  369. package/dist/types/urls/response-types.d.ts +67 -0
  370. package/dist/types/urls/type-extraction.d.ts +157 -0
  371. package/dist/types/urls/urls-function.d.ts +24 -0
  372. package/dist/types/urls.d.ts +1 -0
  373. package/dist/types/use-loader.d.ts +150 -0
  374. package/dist/types/vercel/index.d.ts +10 -0
  375. package/dist/types/vercel/tracing.d.ts +71 -0
  376. package/dist/types/vite/debug.d.ts +80 -0
  377. package/dist/types/vite/discovery/bundle-postprocess.d.ts +12 -0
  378. package/dist/types/vite/discovery/client-urls-projection.d.ts +53 -0
  379. package/dist/types/vite/discovery/dev-prerender-cache.d.ts +65 -0
  380. package/dist/types/vite/discovery/discover-routers.d.ts +17 -0
  381. package/dist/types/vite/discovery/discovery-errors.d.ts +113 -0
  382. package/dist/types/vite/discovery/gate-state.d.ts +79 -0
  383. package/dist/types/vite/discovery/prerender-collection.d.ts +24 -0
  384. package/dist/types/vite/discovery/route-types-writer.d.ts +32 -0
  385. package/dist/types/vite/discovery/self-gen-tracking.d.ts +22 -0
  386. package/dist/types/vite/discovery/shell-prerender-phase.d.ts +40 -0
  387. package/dist/types/vite/discovery/state.d.ts +170 -0
  388. package/dist/types/vite/discovery/virtual-module-codegen.d.ts +15 -0
  389. package/dist/types/vite/encryption-key.d.ts +2 -0
  390. package/dist/types/vite/index.d.ts +11 -0
  391. package/dist/types/vite/inject-client-debug.d.ts +56 -0
  392. package/dist/types/vite/plugin-types.d.ts +298 -0
  393. package/dist/types/vite/plugins/cjs-to-esm.d.ts +6 -0
  394. package/dist/types/vite/plugins/client-ref-dedup.d.ts +40 -0
  395. package/dist/types/vite/plugins/client-ref-hashing.d.ts +35 -0
  396. package/dist/types/vite/plugins/cloudflare-protocol-stub.d.ts +64 -0
  397. package/dist/types/vite/plugins/expose-action-id.d.ts +18 -0
  398. package/dist/types/vite/plugins/expose-id-utils.d.ts +37 -0
  399. package/dist/types/vite/plugins/expose-ids/export-analysis.d.ts +19 -0
  400. package/dist/types/vite/plugins/expose-ids/handler-transform.d.ts +10 -0
  401. package/dist/types/vite/plugins/expose-ids/loader-transform.d.ts +8 -0
  402. package/dist/types/vite/plugins/expose-ids/router-transform.d.ts +13 -0
  403. package/dist/types/vite/plugins/expose-ids/types.d.ts +29 -0
  404. package/dist/types/vite/plugins/expose-internal-ids.d.ts +16 -0
  405. package/dist/types/vite/plugins/performance-tracks.d.ts +25 -0
  406. package/dist/types/vite/plugins/refresh-cmd.d.ts +20 -0
  407. package/dist/types/vite/plugins/server-ref-hashing.d.ts +24 -0
  408. package/dist/types/vite/plugins/server-reference-pattern.d.ts +1 -0
  409. package/dist/types/vite/plugins/use-cache-transform.d.ts +20 -0
  410. package/dist/types/vite/plugins/vercel-output.d.ts +85 -0
  411. package/dist/types/vite/plugins/version-injector.d.ts +21 -0
  412. package/dist/types/vite/plugins/version-plugin.d.ts +19 -0
  413. package/dist/types/vite/plugins/virtual-entries.d.ts +36 -0
  414. package/dist/types/vite/plugins/virtual-stub-plugin.d.ts +7 -0
  415. package/dist/types/vite/rango.d.ts +29 -0
  416. package/dist/types/vite/router-discovery.d.ts +23 -0
  417. package/dist/types/vite/utils/ast-handler-extract.d.ts +64 -0
  418. package/dist/types/vite/utils/banner.d.ts +2 -0
  419. package/dist/types/vite/utils/bundle-analysis.d.ts +28 -0
  420. package/dist/types/vite/utils/client-chunks.d.ts +55 -0
  421. package/dist/types/vite/utils/directive-prologue.d.ts +16 -0
  422. package/dist/types/vite/utils/forward-user-plugins.d.ts +37 -0
  423. package/dist/types/vite/utils/manifest-utils.d.ts +7 -0
  424. package/dist/types/vite/utils/package-resolution.d.ts +6 -0
  425. package/dist/types/vite/utils/prerender-utils.d.ts +32 -0
  426. package/dist/types/vite/utils/shared-utils.d.ts +67 -0
  427. package/dist/types.backup/__internal.d.ts +127 -0
  428. package/dist/types.backup/bin/rango.d.ts +1 -0
  429. package/dist/types.backup/browser/action-coordinator.d.ts +57 -0
  430. package/dist/types.backup/browser/action-fence.d.ts +33 -0
  431. package/dist/types.backup/browser/app-shell.d.ts +34 -0
  432. package/dist/types.backup/browser/app-version.d.ts +6 -0
  433. package/dist/types.backup/browser/connection-warmup.d.ts +31 -0
  434. package/dist/types.backup/browser/cookie-name.d.ts +66 -0
  435. package/dist/types.backup/browser/event-controller.d.ts +221 -0
  436. package/dist/types.backup/browser/history-state.d.ts +26 -0
  437. package/dist/types.backup/browser/index.d.ts +1 -0
  438. package/dist/types.backup/browser/intercept-utils.d.ts +30 -0
  439. package/dist/types.backup/browser/invalidate-client-cache.d.ts +17 -0
  440. package/dist/types.backup/browser/link-interceptor.d.ts +43 -0
  441. package/dist/types.backup/browser/logging.d.ts +33 -0
  442. package/dist/types.backup/browser/merge-segment-loaders.d.ts +38 -0
  443. package/dist/types.backup/browser/navigation-bridge.d.ts +27 -0
  444. package/dist/types.backup/browser/navigation-client.d.ts +17 -0
  445. package/dist/types.backup/browser/navigation-store-handle.d.ts +25 -0
  446. package/dist/types.backup/browser/navigation-store.d.ts +95 -0
  447. package/dist/types.backup/browser/navigation-transaction.d.ts +75 -0
  448. package/dist/types.backup/browser/network-error-handler.d.ts +35 -0
  449. package/dist/types.backup/browser/partial-update.d.ts +61 -0
  450. package/dist/types.backup/browser/prefetch/cache.d.ts +183 -0
  451. package/dist/types.backup/browser/prefetch/fetch.d.ts +52 -0
  452. package/dist/types.backup/browser/prefetch/observer.d.ts +27 -0
  453. package/dist/types.backup/browser/prefetch/policy.d.ts +13 -0
  454. package/dist/types.backup/browser/prefetch/queue.d.ts +48 -0
  455. package/dist/types.backup/browser/prefetch/resource-ready.d.ts +28 -0
  456. package/dist/types.backup/browser/rango-state.d.ts +52 -0
  457. package/dist/types.backup/browser/react/Link.d.ts +140 -0
  458. package/dist/types.backup/browser/react/NavigationProvider.d.ts +88 -0
  459. package/dist/types.backup/browser/react/ScrollRestoration.d.ts +78 -0
  460. package/dist/types.backup/browser/react/context.d.ts +54 -0
  461. package/dist/types.backup/browser/react/filter-segment-order.d.ts +35 -0
  462. package/dist/types.backup/browser/react/index.d.ts +1 -0
  463. package/dist/types.backup/browser/react/location-state-shared.d.ts +162 -0
  464. package/dist/types.backup/browser/react/location-state.d.ts +29 -0
  465. package/dist/types.backup/browser/react/mount-context.d.ts +23 -0
  466. package/dist/types.backup/browser/react/nonce-context.d.ts +14 -0
  467. package/dist/types.backup/browser/react/shallow-equal.d.ts +5 -0
  468. package/dist/types.backup/browser/react/use-action.d.ts +61 -0
  469. package/dist/types.backup/browser/react/use-handle.d.ts +21 -0
  470. package/dist/types.backup/browser/react/use-href.d.ts +32 -0
  471. package/dist/types.backup/browser/react/use-link-status.d.ts +36 -0
  472. package/dist/types.backup/browser/react/use-mount.d.ts +24 -0
  473. package/dist/types.backup/browser/react/use-navigation.d.ts +15 -0
  474. package/dist/types.backup/browser/react/use-params.d.ts +21 -0
  475. package/dist/types.backup/browser/react/use-pathname.d.ts +13 -0
  476. package/dist/types.backup/browser/react/use-reverse.d.ts +40 -0
  477. package/dist/types.backup/browser/react/use-router.d.ts +23 -0
  478. package/dist/types.backup/browser/react/use-search-params.d.ts +19 -0
  479. package/dist/types.backup/browser/react/use-segments.d.ts +29 -0
  480. package/dist/types.backup/browser/response-adapter.d.ts +58 -0
  481. package/dist/types.backup/browser/rsc-router.d.ts +141 -0
  482. package/dist/types.backup/browser/scroll-restoration.d.ts +103 -0
  483. package/dist/types.backup/browser/segment-reconciler.d.ts +74 -0
  484. package/dist/types.backup/browser/segment-structure-assert.d.ts +16 -0
  485. package/dist/types.backup/browser/server-action-bridge.d.ts +29 -0
  486. package/dist/types.backup/browser/types.d.ts +530 -0
  487. package/dist/types.backup/browser/validate-redirect-origin.d.ts +28 -0
  488. package/dist/types.backup/build/collect-fallback-refs.d.ts +5 -0
  489. package/dist/types.backup/build/generate-manifest.d.ts +100 -0
  490. package/dist/types.backup/build/generate-route-types.d.ts +8 -0
  491. package/dist/types.backup/build/index.d.ts +21 -0
  492. package/dist/types.backup/build/prefix-tree-utils.d.ts +56 -0
  493. package/dist/types.backup/build/route-trie.d.ts +89 -0
  494. package/dist/types.backup/build/route-types/ast-helpers.d.ts +3 -0
  495. package/dist/types.backup/build/route-types/ast-route-extraction.d.ts +13 -0
  496. package/dist/types.backup/build/route-types/codegen.d.ts +16 -0
  497. package/dist/types.backup/build/route-types/include-resolution.d.ts +74 -0
  498. package/dist/types.backup/build/route-types/param-extraction.d.ts +13 -0
  499. package/dist/types.backup/build/route-types/per-module-writer.d.ts +18 -0
  500. package/dist/types.backup/build/route-types/router-processing.d.ts +82 -0
  501. package/dist/types.backup/build/route-types/scan-filter.d.ts +17 -0
  502. package/dist/types.backup/build/route-types/source-scan.d.ts +13 -0
  503. package/dist/types.backup/build/runtime-discovery.d.ts +24 -0
  504. package/dist/types.backup/cache/background-task.d.ts +21 -0
  505. package/dist/types.backup/cache/cache-error.d.ts +71 -0
  506. package/dist/types.backup/cache/cache-key-utils.d.ts +35 -0
  507. package/dist/types.backup/cache/cache-policy.d.ts +59 -0
  508. package/dist/types.backup/cache/cache-runtime.d.ts +51 -0
  509. package/dist/types.backup/cache/cache-scope.d.ts +134 -0
  510. package/dist/types.backup/cache/cache-tag.d.ts +79 -0
  511. package/dist/types.backup/cache/cf/cf-base64.d.ts +4 -0
  512. package/dist/types.backup/cache/cf/cf-cache-constants.d.ts +105 -0
  513. package/dist/types.backup/cache/cf/cf-cache-store.d.ts +481 -0
  514. package/dist/types.backup/cache/cf/cf-cache-types.d.ts +300 -0
  515. package/dist/types.backup/cache/cf/cf-kv-utils.d.ts +22 -0
  516. package/dist/types.backup/cache/cf/cf-tag-marker-memo.d.ts +15 -0
  517. package/dist/types.backup/cache/cf/index.d.ts +3 -0
  518. package/dist/types.backup/cache/document-cache.d.ts +69 -0
  519. package/dist/types.backup/cache/handle-capture.d.ts +23 -0
  520. package/dist/types.backup/cache/handle-snapshot.d.ts +39 -0
  521. package/dist/types.backup/cache/index.d.ts +7 -0
  522. package/dist/types.backup/cache/memory-segment-store.d.ts +163 -0
  523. package/dist/types.backup/cache/profile-registry.d.ts +40 -0
  524. package/dist/types.backup/cache/read-through-swr.d.ts +60 -0
  525. package/dist/types.backup/cache/segment-codec.d.ts +78 -0
  526. package/dist/types.backup/cache/shell-snapshot.d.ts +162 -0
  527. package/dist/types.backup/cache/tag-invalidation.d.ts +74 -0
  528. package/dist/types.backup/cache/taint.d.ts +71 -0
  529. package/dist/types.backup/cache/types.d.ts +407 -0
  530. package/dist/types.backup/cache/vercel/index.d.ts +1 -0
  531. package/dist/types.backup/cache/vercel/vercel-cache-store.d.ts +267 -0
  532. package/dist/types.backup/client.d.ts +184 -0
  533. package/dist/types.backup/client.rsc.d.ts +39 -0
  534. package/dist/types.backup/cloudflare/index.d.ts +7 -0
  535. package/dist/types.backup/cloudflare/tracing.d.ts +53 -0
  536. package/dist/types.backup/component-utils.d.ts +46 -0
  537. package/dist/types.backup/components/DefaultDocument.d.ts +13 -0
  538. package/dist/types.backup/context-var.d.ts +84 -0
  539. package/dist/types.backup/debug.d.ts +57 -0
  540. package/dist/types.backup/decode-loader-results.d.ts +5 -0
  541. package/dist/types.backup/default-error-boundary.d.ts +10 -0
  542. package/dist/types.backup/defer.d.ts +89 -0
  543. package/dist/types.backup/deps/browser.d.ts +1 -0
  544. package/dist/types.backup/deps/html-stream-client.d.ts +1 -0
  545. package/dist/types.backup/deps/html-stream-server.d.ts +1 -0
  546. package/dist/types.backup/deps/rsc.d.ts +1 -0
  547. package/dist/types.backup/deps/ssr.d.ts +1 -0
  548. package/dist/types.backup/encode-kv.d.ts +35 -0
  549. package/dist/types.backup/errors.d.ts +226 -0
  550. package/dist/types.backup/escape-script.d.ts +44 -0
  551. package/dist/types.backup/handle.d.ts +93 -0
  552. package/dist/types.backup/handles/MetaTags.d.ts +17 -0
  553. package/dist/types.backup/handles/Scripts.d.ts +38 -0
  554. package/dist/types.backup/handles/breadcrumbs.d.ts +43 -0
  555. package/dist/types.backup/handles/deferred-resolution.d.ts +53 -0
  556. package/dist/types.backup/handles/is-thenable.d.ts +12 -0
  557. package/dist/types.backup/handles/meta.d.ts +43 -0
  558. package/dist/types.backup/handles/script.d.ts +139 -0
  559. package/dist/types.backup/host/cookie-handler.d.ts +8 -0
  560. package/dist/types.backup/host/errors.d.ts +40 -0
  561. package/dist/types.backup/host/index.d.ts +33 -0
  562. package/dist/types.backup/host/pattern-matcher.d.ts +30 -0
  563. package/dist/types.backup/host/router.d.ts +12 -0
  564. package/dist/types.backup/host/testing.d.ts +41 -0
  565. package/dist/types.backup/host/types.d.ts +148 -0
  566. package/dist/types.backup/host/utils.d.ts +20 -0
  567. package/dist/types.backup/href-client.d.ts +214 -0
  568. package/dist/types.backup/index.d.ts +112 -0
  569. package/dist/types.backup/index.rsc.d.ts +51 -0
  570. package/dist/types.backup/internal-debug.d.ts +1 -0
  571. package/dist/types.backup/loader-store.d.ts +193 -0
  572. package/dist/types.backup/loader.d.ts +18 -0
  573. package/dist/types.backup/loader.rsc.d.ts +18 -0
  574. package/dist/types.backup/missing-id-error.d.ts +1 -0
  575. package/dist/types.backup/outlet-context.d.ts +12 -0
  576. package/dist/types.backup/outlet-provider.d.ts +12 -0
  577. package/dist/types.backup/prerender/build-shell-capture.d.ts +104 -0
  578. package/dist/types.backup/prerender/param-hash.d.ts +6 -0
  579. package/dist/types.backup/prerender/shell-manifest-key.d.ts +18 -0
  580. package/dist/types.backup/prerender/store.d.ts +62 -0
  581. package/dist/types.backup/prerender.d.ts +292 -0
  582. package/dist/types.backup/redirect-origin.d.ts +55 -0
  583. package/dist/types.backup/regex-escape.d.ts +6 -0
  584. package/dist/types.backup/render-error-thrower.d.ts +13 -0
  585. package/dist/types.backup/response-utils.d.ts +35 -0
  586. package/dist/types.backup/reverse.d.ts +206 -0
  587. package/dist/types.backup/root-error-boundary.d.ts +32 -0
  588. package/dist/types.backup/route-content-wrapper.d.ts +40 -0
  589. package/dist/types.backup/route-definition/dsl-helpers.d.ts +130 -0
  590. package/dist/types.backup/route-definition/helper-factories.d.ts +22 -0
  591. package/dist/types.backup/route-definition/helpers-types.d.ts +392 -0
  592. package/dist/types.backup/route-definition/index.d.ts +7 -0
  593. package/dist/types.backup/route-definition/redirect.d.ts +48 -0
  594. package/dist/types.backup/route-definition/resolve-handler-use.d.ts +19 -0
  595. package/dist/types.backup/route-definition/use-item-types.d.ts +1 -0
  596. package/dist/types.backup/route-definition.d.ts +1 -0
  597. package/dist/types.backup/route-map-builder.d.ts +127 -0
  598. package/dist/types.backup/route-name.d.ts +27 -0
  599. package/dist/types.backup/route-types.d.ts +172 -0
  600. package/dist/types.backup/router/basename.d.ts +10 -0
  601. package/dist/types.backup/router/content-negotiation.d.ts +91 -0
  602. package/dist/types.backup/router/debug-manifest.d.ts +7 -0
  603. package/dist/types.backup/router/error-handling.d.ts +76 -0
  604. package/dist/types.backup/router/find-match.d.ts +19 -0
  605. package/dist/types.backup/router/handler-context.d.ts +41 -0
  606. package/dist/types.backup/router/instrument.d.ts +161 -0
  607. package/dist/types.backup/router/intercept-resolution.d.ts +79 -0
  608. package/dist/types.backup/router/lazy-includes.d.ts +26 -0
  609. package/dist/types.backup/router/loader-resolution.d.ts +63 -0
  610. package/dist/types.backup/router/logging.d.ts +41 -0
  611. package/dist/types.backup/router/manifest.d.ts +8 -0
  612. package/dist/types.backup/router/match-api.d.ts +19 -0
  613. package/dist/types.backup/router/match-context.d.ts +184 -0
  614. package/dist/types.backup/router/match-handlers.d.ts +49 -0
  615. package/dist/types.backup/router/match-middleware/background-revalidation.d.ts +113 -0
  616. package/dist/types.backup/router/match-middleware/cache-lookup.d.ts +113 -0
  617. package/dist/types.backup/router/match-middleware/cache-store.d.ts +112 -0
  618. package/dist/types.backup/router/match-middleware/index.d.ts +80 -0
  619. package/dist/types.backup/router/match-middleware/intercept-resolution.d.ts +116 -0
  620. package/dist/types.backup/router/match-middleware/segment-resolution.d.ts +94 -0
  621. package/dist/types.backup/router/match-pipelines.d.ts +103 -0
  622. package/dist/types.backup/router/match-result.d.ts +114 -0
  623. package/dist/types.backup/router/metrics.d.ts +6 -0
  624. package/dist/types.backup/router/middleware-types.d.ts +74 -0
  625. package/dist/types.backup/router/middleware.d.ts +116 -0
  626. package/dist/types.backup/router/navigation-snapshot.d.ts +22 -0
  627. package/dist/types.backup/router/params-util.d.ts +8 -0
  628. package/dist/types.backup/router/parse-pattern.d.ts +38 -0
  629. package/dist/types.backup/router/pattern-matching.d.ts +169 -0
  630. package/dist/types.backup/router/prefetch-cache-ttl.d.ts +27 -0
  631. package/dist/types.backup/router/prefetch-limits.d.ts +20 -0
  632. package/dist/types.backup/router/prerender-match.d.ts +50 -0
  633. package/dist/types.backup/router/preview-match.d.ts +22 -0
  634. package/dist/types.backup/router/request-classification.d.ts +104 -0
  635. package/dist/types.backup/router/revalidation.d.ts +57 -0
  636. package/dist/types.backup/router/route-snapshot.d.ts +112 -0
  637. package/dist/types.backup/router/router-context.d.ts +137 -0
  638. package/dist/types.backup/router/router-interfaces.d.ts +432 -0
  639. package/dist/types.backup/router/router-options.d.ts +738 -0
  640. package/dist/types.backup/router/router-registry.d.ts +15 -0
  641. package/dist/types.backup/router/segment-resolution/fresh.d.ts +55 -0
  642. package/dist/types.backup/router/segment-resolution/helpers.d.ts +93 -0
  643. package/dist/types.backup/router/segment-resolution/loader-cache.d.ts +33 -0
  644. package/dist/types.backup/router/segment-resolution/loader-mask.d.ts +44 -0
  645. package/dist/types.backup/router/segment-resolution/loader-snapshot.d.ts +90 -0
  646. package/dist/types.backup/router/segment-resolution/mask-nested.d.ts +53 -0
  647. package/dist/types.backup/router/segment-resolution/revalidation.d.ts +85 -0
  648. package/dist/types.backup/router/segment-resolution/static-store.d.ts +17 -0
  649. package/dist/types.backup/router/segment-resolution/streamed-handler-telemetry.d.ts +16 -0
  650. package/dist/types.backup/router/segment-resolution/view-transition-default.d.ts +28 -0
  651. package/dist/types.backup/router/segment-resolution.d.ts +3 -0
  652. package/dist/types.backup/router/segment-wrappers.d.ts +53 -0
  653. package/dist/types.backup/router/state-cookie-name.d.ts +1 -0
  654. package/dist/types.backup/router/substitute-pattern-params.d.ts +23 -0
  655. package/dist/types.backup/router/telemetry-otel.d.ts +113 -0
  656. package/dist/types.backup/router/telemetry.d.ts +215 -0
  657. package/dist/types.backup/router/timeout.d.ts +68 -0
  658. package/dist/types.backup/router/tracing.d.ts +125 -0
  659. package/dist/types.backup/router/trie-matching.d.ts +32 -0
  660. package/dist/types.backup/router/types.d.ts +98 -0
  661. package/dist/types.backup/router/url-params.d.ts +26 -0
  662. package/dist/types.backup/router.d.ts +7 -0
  663. package/dist/types.backup/rsc/capture-queue.d.ts +6 -0
  664. package/dist/types.backup/rsc/full-payload.d.ts +22 -0
  665. package/dist/types.backup/rsc/handler-context.d.ts +31 -0
  666. package/dist/types.backup/rsc/handler.d.ts +9 -0
  667. package/dist/types.backup/rsc/helpers.d.ts +213 -0
  668. package/dist/types.backup/rsc/index.d.ts +17 -0
  669. package/dist/types.backup/rsc/json-route-result.d.ts +20 -0
  670. package/dist/types.backup/rsc/loader-fetch.d.ts +14 -0
  671. package/dist/types.backup/rsc/manifest-init.d.ts +18 -0
  672. package/dist/types.backup/rsc/nonce.d.ts +28 -0
  673. package/dist/types.backup/rsc/origin-guard.d.ts +50 -0
  674. package/dist/types.backup/rsc/progressive-enhancement.d.ts +19 -0
  675. package/dist/types.backup/rsc/redirect-guard.d.ts +35 -0
  676. package/dist/types.backup/rsc/response-cache-serve.d.ts +46 -0
  677. package/dist/types.backup/rsc/response-error.d.ts +19 -0
  678. package/dist/types.backup/rsc/response-route-handler.d.ts +29 -0
  679. package/dist/types.backup/rsc/rsc-rendering.d.ts +23 -0
  680. package/dist/types.backup/rsc/runtime-warnings.d.ts +22 -0
  681. package/dist/types.backup/rsc/server-action.d.ts +68 -0
  682. package/dist/types.backup/rsc/shell-build-manifest.d.ts +84 -0
  683. package/dist/types.backup/rsc/shell-capture-constants.d.ts +27 -0
  684. package/dist/types.backup/rsc/shell-capture.d.ts +374 -0
  685. package/dist/types.backup/rsc/shell-serve.d.ts +136 -0
  686. package/dist/types.backup/rsc/ssr-setup.d.ts +48 -0
  687. package/dist/types.backup/rsc/transition-gate.d.ts +27 -0
  688. package/dist/types.backup/rsc/types.d.ts +290 -0
  689. package/dist/types.backup/runtime-env.d.ts +1 -0
  690. package/dist/types.backup/search-params.d.ts +125 -0
  691. package/dist/types.backup/segment-content-promise.d.ts +13 -0
  692. package/dist/types.backup/segment-fragments.d.ts +56 -0
  693. package/dist/types.backup/segment-loader-promise.d.ts +22 -0
  694. package/dist/types.backup/segment-system.d.ts +84 -0
  695. package/dist/types.backup/serialize.d.ts +164 -0
  696. package/dist/types.backup/server/context.d.ts +494 -0
  697. package/dist/types.backup/server/cookie-parse.d.ts +10 -0
  698. package/dist/types.backup/server/cookie-store.d.ts +107 -0
  699. package/dist/types.backup/server/fetchable-loader-store.d.ts +20 -0
  700. package/dist/types.backup/server/handle-store.d.ts +100 -0
  701. package/dist/types.backup/server/loader-registry.d.ts +32 -0
  702. package/dist/types.backup/server/request-context.d.ts +596 -0
  703. package/dist/types.backup/server/root-layout.d.ts +3 -0
  704. package/dist/types.backup/server.d.ts +15 -0
  705. package/dist/types.backup/ssr/index.d.ts +233 -0
  706. package/dist/types.backup/ssr/inject-rsc-eager.d.ts +3 -0
  707. package/dist/types.backup/ssr/preinit-client-references.d.ts +71 -0
  708. package/dist/types.backup/ssr/ssr-root.d.ts +69 -0
  709. package/dist/types.backup/static-handler.d.ts +57 -0
  710. package/dist/types.backup/testing/cache-status.d.ts +63 -0
  711. package/dist/types.backup/testing/collect-handle.d.ts +20 -0
  712. package/dist/types.backup/testing/dispatch.d.ts +123 -0
  713. package/dist/types.backup/testing/dom.entry.d.ts +15 -0
  714. package/dist/types.backup/testing/e2e/fixture.d.ts +37 -0
  715. package/dist/types.backup/testing/e2e/index.d.ts +30 -0
  716. package/dist/types.backup/testing/e2e/matchers.d.ts +17 -0
  717. package/dist/types.backup/testing/e2e/page-helpers.d.ts +62 -0
  718. package/dist/types.backup/testing/e2e/parity.d.ts +111 -0
  719. package/dist/types.backup/testing/e2e/server.d.ts +35 -0
  720. package/dist/types.backup/testing/flight-matchers.d.ts +55 -0
  721. package/dist/types.backup/testing/flight-normalize.d.ts +1 -0
  722. package/dist/types.backup/testing/flight-tree.d.ts +192 -0
  723. package/dist/types.backup/testing/flight.d.ts +115 -0
  724. package/dist/types.backup/testing/flight.entry.d.ts +27 -0
  725. package/dist/types.backup/testing/generated-routes.d.ts +66 -0
  726. package/dist/types.backup/testing/index.d.ts +52 -0
  727. package/dist/types.backup/testing/internal/context.d.ts +225 -0
  728. package/dist/types.backup/testing/internal/flight-client-globals.d.ts +1 -0
  729. package/dist/types.backup/testing/internal/seed-vars.d.ts +30 -0
  730. package/dist/types.backup/testing/render-handler.d.ts +160 -0
  731. package/dist/types.backup/testing/render-route.d.ts +246 -0
  732. package/dist/types.backup/testing/run-loader.d.ts +186 -0
  733. package/dist/types.backup/testing/run-middleware.d.ts +132 -0
  734. package/dist/types.backup/testing/run-transition-when.d.ts +77 -0
  735. package/dist/types.backup/testing/vitest-stubs/cloudflare-email.d.ts +6 -0
  736. package/dist/types.backup/testing/vitest-stubs/cloudflare-workers.d.ts +13 -0
  737. package/dist/types.backup/testing/vitest-stubs/plugin-rsc.d.ts +7 -0
  738. package/dist/types.backup/testing/vitest-stubs/version.d.ts +1 -0
  739. package/dist/types.backup/testing/vitest.d.ts +205 -0
  740. package/dist/types.backup/theme/ThemeProvider.d.ts +13 -0
  741. package/dist/types.backup/theme/ThemeScript.d.ts +45 -0
  742. package/dist/types.backup/theme/constants.d.ts +39 -0
  743. package/dist/types.backup/theme/index.d.ts +29 -0
  744. package/dist/types.backup/theme/theme-context.d.ts +21 -0
  745. package/dist/types.backup/theme/theme-script.d.ts +26 -0
  746. package/dist/types.backup/theme/types.d.ts +162 -0
  747. package/dist/types.backup/theme/use-theme.d.ts +8 -0
  748. package/dist/types.backup/types/boundaries.d.ts +93 -0
  749. package/dist/types.backup/types/cache-types.d.ts +191 -0
  750. package/dist/types.backup/types/error-types.d.ts +114 -0
  751. package/dist/types.backup/types/global-namespace.d.ts +90 -0
  752. package/dist/types.backup/types/handler-context.d.ts +658 -0
  753. package/dist/types.backup/types/index.d.ts +11 -0
  754. package/dist/types.backup/types/loader-types.d.ts +182 -0
  755. package/dist/types.backup/types/request-scope.d.ts +93 -0
  756. package/dist/types.backup/types/route-config.d.ts +105 -0
  757. package/dist/types.backup/types/route-entry.d.ts +95 -0
  758. package/dist/types.backup/types/segments.d.ts +234 -0
  759. package/dist/types.backup/types.d.ts +1 -0
  760. package/dist/types.backup/urls/include-helper.d.ts +17 -0
  761. package/dist/types.backup/urls/include-provider.d.ts +27 -0
  762. package/dist/types.backup/urls/index.d.ts +6 -0
  763. package/dist/types.backup/urls/path-helper-types.d.ts +197 -0
  764. package/dist/types.backup/urls/path-helper.d.ts +12 -0
  765. package/dist/types.backup/urls/pattern-types.d.ts +166 -0
  766. package/dist/types.backup/urls/response-types.d.ts +67 -0
  767. package/dist/types.backup/urls/type-extraction.d.ts +157 -0
  768. package/dist/types.backup/urls/urls-function.d.ts +24 -0
  769. package/dist/types.backup/urls.d.ts +1 -0
  770. package/dist/types.backup/use-loader.d.ts +150 -0
  771. package/dist/types.backup/vercel/index.d.ts +10 -0
  772. package/dist/types.backup/vercel/tracing.d.ts +70 -0
  773. package/dist/types.backup/vite/debug.d.ts +80 -0
  774. package/dist/types.backup/vite/discovery/bundle-postprocess.d.ts +12 -0
  775. package/dist/types.backup/vite/discovery/dev-prerender-cache.d.ts +65 -0
  776. package/dist/types.backup/vite/discovery/discover-routers.d.ts +17 -0
  777. package/dist/types.backup/vite/discovery/discovery-errors.d.ts +113 -0
  778. package/dist/types.backup/vite/discovery/gate-state.d.ts +79 -0
  779. package/dist/types.backup/vite/discovery/prerender-collection.d.ts +24 -0
  780. package/dist/types.backup/vite/discovery/route-types-writer.d.ts +32 -0
  781. package/dist/types.backup/vite/discovery/self-gen-tracking.d.ts +22 -0
  782. package/dist/types.backup/vite/discovery/shell-prerender-phase.d.ts +40 -0
  783. package/dist/types.backup/vite/discovery/state.d.ts +162 -0
  784. package/dist/types.backup/vite/discovery/virtual-module-codegen.d.ts +15 -0
  785. package/dist/types.backup/vite/index.d.ts +11 -0
  786. package/dist/types.backup/vite/inject-client-debug.d.ts +56 -0
  787. package/dist/types.backup/vite/plugin-types.d.ts +298 -0
  788. package/dist/types.backup/vite/plugins/cjs-to-esm.d.ts +6 -0
  789. package/dist/types.backup/vite/plugins/client-ref-dedup.d.ts +40 -0
  790. package/dist/types.backup/vite/plugins/client-ref-hashing.d.ts +35 -0
  791. package/dist/types.backup/vite/plugins/cloudflare-protocol-stub.d.ts +64 -0
  792. package/dist/types.backup/vite/plugins/expose-action-id.d.ts +18 -0
  793. package/dist/types.backup/vite/plugins/expose-id-utils.d.ts +37 -0
  794. package/dist/types.backup/vite/plugins/expose-ids/export-analysis.d.ts +19 -0
  795. package/dist/types.backup/vite/plugins/expose-ids/handler-transform.d.ts +10 -0
  796. package/dist/types.backup/vite/plugins/expose-ids/loader-transform.d.ts +8 -0
  797. package/dist/types.backup/vite/plugins/expose-ids/router-transform.d.ts +13 -0
  798. package/dist/types.backup/vite/plugins/expose-ids/types.d.ts +29 -0
  799. package/dist/types.backup/vite/plugins/expose-internal-ids.d.ts +6 -0
  800. package/dist/types.backup/vite/plugins/performance-tracks.d.ts +25 -0
  801. package/dist/types.backup/vite/plugins/refresh-cmd.d.ts +20 -0
  802. package/dist/types.backup/vite/plugins/use-cache-transform.d.ts +20 -0
  803. package/dist/types.backup/vite/plugins/vercel-output.d.ts +85 -0
  804. package/dist/types.backup/vite/plugins/version-injector.d.ts +21 -0
  805. package/dist/types.backup/vite/plugins/version-plugin.d.ts +19 -0
  806. package/dist/types.backup/vite/plugins/virtual-entries.d.ts +36 -0
  807. package/dist/types.backup/vite/plugins/virtual-stub-plugin.d.ts +7 -0
  808. package/dist/types.backup/vite/rango.d.ts +29 -0
  809. package/dist/types.backup/vite/router-discovery.d.ts +23 -0
  810. package/dist/types.backup/vite/utils/ast-handler-extract.d.ts +64 -0
  811. package/dist/types.backup/vite/utils/banner.d.ts +2 -0
  812. package/dist/types.backup/vite/utils/bundle-analysis.d.ts +28 -0
  813. package/dist/types.backup/vite/utils/client-chunks.d.ts +55 -0
  814. package/dist/types.backup/vite/utils/directive-prologue.d.ts +16 -0
  815. package/dist/types.backup/vite/utils/forward-user-plugins.d.ts +37 -0
  816. package/dist/types.backup/vite/utils/manifest-utils.d.ts +7 -0
  817. package/dist/types.backup/vite/utils/package-resolution.d.ts +6 -0
  818. package/dist/types.backup/vite/utils/prerender-utils.d.ts +32 -0
  819. package/dist/types.backup/vite/utils/shared-utils.d.ts +55 -0
  820. package/dist/vite/index.js +9695 -3592
  821. package/package.json +119 -39
  822. package/skills/api-client/SKILL.md +211 -0
  823. package/skills/breadcrumbs/SKILL.md +82 -5
  824. package/skills/bundle-analysis/SKILL.md +159 -0
  825. package/skills/cache-guide/SKILL.md +232 -34
  826. package/skills/caching/SKILL.md +375 -19
  827. package/skills/catalog.json +283 -0
  828. package/skills/cloudflare/SKILL.md +151 -0
  829. package/skills/cloudflare/agents/openai.yaml +4 -0
  830. package/skills/cloudflare/references/d1-and-local-dev.md +131 -0
  831. package/skills/cloudflare/references/streaming-and-deploy.md +107 -0
  832. package/skills/cloudflare/references/webhooks-and-crypto.md +147 -0
  833. package/skills/comparison/SKILL.md +50 -0
  834. package/skills/comparison/agents/openai.yaml +4 -0
  835. package/skills/comparison/references/framework-comparison.md +844 -0
  836. package/skills/composability/SKILL.md +124 -4
  837. package/skills/css/SKILL.md +76 -0
  838. package/skills/debug-manifest/SKILL.md +5 -11
  839. package/skills/defer-hydration/SKILL.md +235 -0
  840. package/skills/deployment-caching/SKILL.md +176 -0
  841. package/skills/document-cache/SKILL.md +116 -58
  842. package/skills/fonts/SKILL.md +1 -1
  843. package/skills/handler-use/SKILL.md +12 -10
  844. package/skills/hooks/SKILL.md +73 -699
  845. package/skills/hooks/data.md +273 -0
  846. package/skills/hooks/handle-and-actions.md +103 -0
  847. package/skills/hooks/navigation.md +110 -0
  848. package/skills/hooks/outlets.md +62 -0
  849. package/skills/hooks/state.md +228 -0
  850. package/skills/hooks/urls.md +135 -0
  851. package/skills/host-router/SKILL.md +129 -27
  852. package/skills/i18n/SKILL.md +276 -0
  853. package/skills/intercept/SKILL.md +75 -19
  854. package/skills/layout/SKILL.md +40 -19
  855. package/skills/links/SKILL.md +211 -17
  856. package/skills/loader/SKILL.md +230 -25
  857. package/skills/middleware/SKILL.md +58 -13
  858. package/skills/migrate-nextjs/SKILL.md +267 -33
  859. package/skills/migrate-nextjs/backend-host-swap.md +120 -0
  860. package/skills/migrate-react-router/SKILL.md +59 -671
  861. package/skills/migrate-react-router/component-migration.md +196 -0
  862. package/skills/migrate-react-router/data-and-actions.md +225 -0
  863. package/skills/migrate-react-router/route-mapping.md +271 -0
  864. package/skills/mime-routes/SKILL.md +55 -18
  865. package/skills/observability/SKILL.md +231 -0
  866. package/skills/parallel/SKILL.md +50 -10
  867. package/skills/ppr/SKILL.md +904 -0
  868. package/skills/prerender/SKILL.md +130 -68
  869. package/skills/rango/SKILL.md +321 -26
  870. package/skills/react-compiler/SKILL.md +168 -0
  871. package/skills/response-routes/SKILL.md +172 -52
  872. package/skills/route/SKILL.md +123 -9
  873. package/skills/router-setup/SKILL.md +53 -9
  874. package/skills/scripts/SKILL.md +179 -0
  875. package/skills/server-actions/SKILL.md +776 -0
  876. package/skills/shell-manifest/SKILL.md +185 -0
  877. package/skills/streams-and-websockets/SKILL.md +1 -1
  878. package/skills/tailwind/SKILL.md +28 -4
  879. package/skills/testing/SKILL.md +131 -0
  880. package/skills/testing/bindings.md +103 -0
  881. package/skills/testing/cache-prerender.md +172 -0
  882. package/skills/testing/client-components.md +131 -0
  883. package/skills/testing/e2e-parity.md +125 -0
  884. package/skills/testing/flight.md +91 -0
  885. package/skills/testing/handles.md +131 -0
  886. package/skills/testing/loader.md +128 -0
  887. package/skills/testing/middleware.md +99 -0
  888. package/skills/testing/render-handler.md +122 -0
  889. package/skills/testing/response-routes.md +95 -0
  890. package/skills/testing/reverse-and-types.md +85 -0
  891. package/skills/testing/server-actions.md +107 -0
  892. package/skills/testing/server-tree.md +128 -0
  893. package/skills/testing/setup.md +123 -0
  894. package/skills/theme/SKILL.md +1 -1
  895. package/skills/typesafety/SKILL.md +45 -628
  896. package/skills/typesafety/env-and-bindings.md +254 -0
  897. package/skills/typesafety/generated-files-and-cli.md +342 -0
  898. package/skills/typesafety/params-and-search.md +153 -0
  899. package/skills/typesafety/route-types.md +213 -0
  900. package/skills/use-cache/SKILL.md +121 -15
  901. package/skills/vercel/SKILL.md +149 -0
  902. package/skills/view-transitions/SKILL.md +341 -0
  903. package/src/__augment-tests__/augment.ts +81 -0
  904. package/src/__augment-tests__/augmented.check.ts +116 -0
  905. package/src/__internal.ts +0 -65
  906. package/src/browser/action-coordinator.ts +53 -36
  907. package/src/browser/action-fence.ts +47 -0
  908. package/src/browser/app-shell.ts +14 -27
  909. package/src/browser/connection-warmup.ts +134 -0
  910. package/src/browser/cookie-name.ts +140 -0
  911. package/src/browser/dev-discovery.ts +66 -0
  912. package/src/browser/event-controller.ts +400 -168
  913. package/src/browser/history-state.ts +21 -0
  914. package/src/browser/index.ts +3 -3
  915. package/src/browser/invalidate-client-cache.ts +52 -0
  916. package/src/browser/link-interceptor.ts +469 -20
  917. package/src/browser/logging.ts +28 -0
  918. package/src/browser/merge-segment-loaders.ts +6 -4
  919. package/src/browser/navigation-bridge.ts +164 -69
  920. package/src/browser/navigation-client.ts +199 -96
  921. package/src/browser/navigation-store-handle.ts +38 -0
  922. package/src/browser/navigation-store.ts +165 -345
  923. package/src/browser/navigation-transaction.ts +9 -59
  924. package/src/browser/network-error-handler.ts +34 -7
  925. package/src/browser/notify-listeners.ts +22 -0
  926. package/src/browser/partial-update.ts +219 -163
  927. package/src/browser/prefetch/cache.ts +240 -97
  928. package/src/browser/prefetch/default-strategy.ts +74 -0
  929. package/src/browser/prefetch/fetch.ts +317 -51
  930. package/src/browser/prefetch/invalidation.ts +30 -0
  931. package/src/browser/prefetch/loader.ts +111 -0
  932. package/src/browser/prefetch/observer.ts +50 -22
  933. package/src/browser/prefetch/queue.ts +25 -7
  934. package/src/browser/prefetch/runtime.ts +6 -0
  935. package/src/browser/rango-state.ts +177 -114
  936. package/src/browser/react/Link.tsx +115 -75
  937. package/src/browser/react/NavigationProvider.tsx +194 -143
  938. package/src/browser/react/ScrollRestoration.tsx +10 -6
  939. package/src/browser/react/context.ts +4 -0
  940. package/src/browser/react/filter-segment-order.ts +66 -7
  941. package/src/browser/react/index.ts +0 -48
  942. package/src/browser/react/location-state-shared.ts +178 -8
  943. package/src/browser/react/location-state.ts +39 -14
  944. package/src/browser/react/use-action.ts +6 -15
  945. package/src/browser/react/use-handle.ts +17 -14
  946. package/src/browser/react/use-href.tsx +8 -1
  947. package/src/browser/react/use-link-status.ts +33 -8
  948. package/src/browser/react/use-navigation.ts +10 -5
  949. package/src/browser/react/use-params.ts +11 -11
  950. package/src/browser/react/use-reverse.ts +106 -0
  951. package/src/browser/react/use-router.ts +21 -6
  952. package/src/browser/react/use-search-params.ts +0 -5
  953. package/src/browser/react/use-segments.ts +11 -21
  954. package/src/browser/response-adapter.ts +99 -8
  955. package/src/browser/rsc-router.tsx +230 -42
  956. package/src/browser/scroll-restoration.ts +37 -22
  957. package/src/browser/segment-reconciler.ts +31 -21
  958. package/src/browser/segment-structure-assert.ts +2 -2
  959. package/src/browser/server-action-bridge.ts +262 -65
  960. package/src/browser/types.ts +132 -47
  961. package/src/browser/validate-redirect-origin.ts +43 -16
  962. package/src/build/collect-fallback-refs.ts +107 -0
  963. package/src/build/generate-manifest.ts +213 -184
  964. package/src/build/generate-route-types.ts +3 -1
  965. package/src/build/index.ts +11 -3
  966. package/src/build/merge-full-manifests.ts +161 -0
  967. package/src/build/prefix-tree-utils.ts +123 -0
  968. package/src/build/route-trie.ts +43 -280
  969. package/src/build/route-types/ast-route-extraction.ts +15 -8
  970. package/src/build/route-types/codegen.ts +16 -5
  971. package/src/build/route-types/include-resolution.ts +513 -64
  972. package/src/build/route-types/param-extraction.ts +6 -3
  973. package/src/build/route-types/per-module-writer.ts +33 -12
  974. package/src/build/route-types/router-processing.ts +312 -204
  975. package/src/build/route-types/scan-filter.ts +1 -1
  976. package/src/build/route-types/source-scan.ts +216 -0
  977. package/src/build/runtime-discovery.ts +32 -29
  978. package/src/cache/cache-error.ts +104 -0
  979. package/src/cache/cache-exec-scope.ts +47 -0
  980. package/src/cache/cache-key-utils.ts +73 -15
  981. package/src/cache/cache-policy.ts +108 -34
  982. package/src/cache/cache-runtime.ts +566 -121
  983. package/src/cache/cache-scope.ts +383 -105
  984. package/src/cache/cache-tag.ts +149 -0
  985. package/src/cache/cf/cf-base64.ts +33 -0
  986. package/src/cache/cf/cf-cache-constants.ts +134 -0
  987. package/src/cache/cf/cf-cache-store.ts +3028 -391
  988. package/src/cache/cf/cf-cache-types.ts +417 -0
  989. package/src/cache/cf/cf-kv-utils.ts +84 -0
  990. package/src/cache/cf/cf-tag-marker-memo.ts +108 -0
  991. package/src/cache/cf/cf-zone-purge.ts +101 -0
  992. package/src/cache/cf/index.ts +11 -16
  993. package/src/cache/document-cache.ts +184 -53
  994. package/src/cache/handle-snapshot.ts +92 -1
  995. package/src/cache/index.ts +32 -20
  996. package/src/cache/memory-segment-store.ts +286 -37
  997. package/src/cache/profile-registry.ts +46 -31
  998. package/src/cache/read-through-swr.ts +66 -16
  999. package/src/cache/search-params-filter.ts +118 -0
  1000. package/src/cache/segment-codec.ts +80 -25
  1001. package/src/cache/shell-snapshot.ts +516 -0
  1002. package/src/cache/tag-invalidation.ts +230 -0
  1003. package/src/cache/taint.ts +28 -9
  1004. package/src/cache/types.ts +323 -100
  1005. package/src/cache/vercel/index.ts +11 -0
  1006. package/src/cache/vercel/vercel-cache-store.ts +1264 -0
  1007. package/src/client-urls/client-root.tsx +161 -0
  1008. package/src/client-urls/client-urls.ts +665 -0
  1009. package/src/client-urls/navigation.ts +237 -0
  1010. package/src/client-urls/revalidation-protocol.ts +56 -0
  1011. package/src/client-urls/server-projection.ts +563 -0
  1012. package/src/client-urls/types.ts +178 -0
  1013. package/src/client.rsc.tsx +48 -21
  1014. package/src/client.tsx +77 -67
  1015. package/src/cloudflare/index.ts +11 -0
  1016. package/src/cloudflare/tracing.ts +112 -0
  1017. package/src/component-utils.ts +19 -0
  1018. package/src/components/DefaultDocument.tsx +8 -2
  1019. package/src/context-var.ts +18 -6
  1020. package/src/decode-loader-results.ts +160 -0
  1021. package/src/defer.ts +185 -0
  1022. package/src/deps/ssr.ts +4 -2
  1023. package/src/dev-discovery-protocol.ts +11 -0
  1024. package/src/encode-kv.ts +49 -0
  1025. package/src/errors.ts +44 -4
  1026. package/src/escape-script.ts +52 -0
  1027. package/src/handle.ts +67 -37
  1028. package/src/handles/MetaTags.tsx +24 -53
  1029. package/src/handles/Scripts.tsx +183 -0
  1030. package/src/handles/breadcrumbs.ts +35 -8
  1031. package/src/handles/deferred-resolution.ts +134 -0
  1032. package/src/handles/is-thenable.ts +16 -0
  1033. package/src/handles/meta.ts +14 -40
  1034. package/src/handles/script.ts +244 -0
  1035. package/src/host/cookie-handler.ts +9 -60
  1036. package/src/host/errors.ts +13 -22
  1037. package/src/host/index.ts +9 -2
  1038. package/src/host/pattern-matcher.ts +23 -52
  1039. package/src/host/router.ts +107 -99
  1040. package/src/host/testing.ts +40 -27
  1041. package/src/host/types.ts +37 -4
  1042. package/src/host/utils.ts +1 -1
  1043. package/src/href-client.ts +137 -22
  1044. package/src/index.rsc.ts +105 -12
  1045. package/src/index.ts +102 -14
  1046. package/src/internal-debug.ts +11 -10
  1047. package/src/loader-redirect.tsx +47 -0
  1048. package/src/loader-store.ts +500 -0
  1049. package/src/loader.rsc.ts +20 -13
  1050. package/src/loader.ts +12 -11
  1051. package/src/missing-id-error.ts +68 -0
  1052. package/src/outlet-context.ts +12 -0
  1053. package/src/outlet-provider.tsx +16 -6
  1054. package/src/prerender/build-shell-capture.ts +453 -0
  1055. package/src/prerender/param-hash.ts +16 -16
  1056. package/src/prerender/shell-manifest-key.ts +20 -0
  1057. package/src/prerender/store.ts +47 -38
  1058. package/src/prerender.ts +81 -13
  1059. package/src/redirect-origin.ts +143 -0
  1060. package/src/regex-escape.ts +8 -0
  1061. package/src/render-error-thrower.tsx +20 -0
  1062. package/src/response-utils.ts +34 -0
  1063. package/src/reverse.ts +65 -40
  1064. package/src/root-error-boundary.tsx +1 -19
  1065. package/src/route-content-wrapper.tsx +112 -78
  1066. package/src/route-definition/dsl-helpers.ts +300 -313
  1067. package/src/route-definition/helper-factories.ts +28 -140
  1068. package/src/route-definition/helpers-types.ts +92 -62
  1069. package/src/route-definition/index.ts +1 -2
  1070. package/src/route-definition/redirect.ts +44 -11
  1071. package/src/route-definition/resolve-handler-use.ts +6 -1
  1072. package/src/route-definition/use-item-types.ts +29 -0
  1073. package/src/route-map-builder.ts +102 -74
  1074. package/src/route-types.ts +19 -46
  1075. package/src/router/basename.ts +14 -0
  1076. package/src/router/content-negotiation.ts +120 -30
  1077. package/src/router/error-handling.ts +110 -29
  1078. package/src/router/find-match.ts +129 -30
  1079. package/src/router/handler-context.ts +41 -57
  1080. package/src/router/instrument.ts +401 -0
  1081. package/src/router/intercept-resolution.ts +98 -21
  1082. package/src/router/lazy-includes.ts +82 -58
  1083. package/src/router/loader-resolution.ts +401 -85
  1084. package/src/router/logging.ts +0 -6
  1085. package/src/router/manifest.ts +74 -40
  1086. package/src/router/match-api.ts +91 -55
  1087. package/src/router/match-context.ts +0 -22
  1088. package/src/router/match-handlers.ts +268 -171
  1089. package/src/router/match-middleware/background-revalidation.ts +40 -24
  1090. package/src/router/match-middleware/cache-lookup.ts +316 -302
  1091. package/src/router/match-middleware/cache-store.ts +134 -52
  1092. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  1093. package/src/router/match-middleware/segment-resolution.ts +0 -22
  1094. package/src/router/match-pipelines.ts +1 -42
  1095. package/src/router/match-result.ts +76 -79
  1096. package/src/router/metrics.ts +17 -36
  1097. package/src/router/middleware-types.ts +20 -110
  1098. package/src/router/middleware.ts +275 -173
  1099. package/src/router/navigation-snapshot.ts +51 -60
  1100. package/src/router/params-util.ts +23 -0
  1101. package/src/router/parse-pattern.ts +115 -0
  1102. package/src/router/pattern-matching.ts +134 -154
  1103. package/src/router/prefetch-cache-ttl.ts +51 -0
  1104. package/src/router/prefetch-default.ts +59 -0
  1105. package/src/router/prefetch-limits.ts +37 -0
  1106. package/src/router/prerender-match.ts +159 -69
  1107. package/src/router/preview-match.ts +6 -2
  1108. package/src/router/request-classification.ts +50 -69
  1109. package/src/router/revalidation.ts +146 -83
  1110. package/src/router/route-snapshot.ts +14 -3
  1111. package/src/router/route-trie-builder.ts +334 -0
  1112. package/src/router/router-context.ts +6 -29
  1113. package/src/router/router-interfaces.ts +168 -38
  1114. package/src/router/router-options.ts +235 -11
  1115. package/src/router/router-registry.ts +2 -5
  1116. package/src/router/segment-resolution/fresh.ts +163 -88
  1117. package/src/router/segment-resolution/helpers.ts +96 -18
  1118. package/src/router/segment-resolution/loader-cache.ts +187 -39
  1119. package/src/router/segment-resolution/loader-mask.ts +60 -0
  1120. package/src/router/segment-resolution/loader-snapshot.ts +259 -0
  1121. package/src/router/segment-resolution/mask-nested.ts +99 -0
  1122. package/src/router/segment-resolution/revalidation.ts +316 -321
  1123. package/src/router/segment-resolution/static-store.ts +55 -15
  1124. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  1125. package/src/router/segment-resolution/view-transition-default.ts +60 -0
  1126. package/src/router/segment-resolution.ts +5 -1
  1127. package/src/router/segment-wrappers.ts +6 -5
  1128. package/src/router/state-cookie-name.ts +33 -0
  1129. package/src/router/substitute-pattern-params.ts +75 -0
  1130. package/src/router/telemetry-otel.ts +171 -200
  1131. package/src/router/telemetry.ts +106 -20
  1132. package/src/router/timeout.ts +53 -22
  1133. package/src/router/tracing.ts +235 -0
  1134. package/src/router/transition-when.ts +76 -0
  1135. package/src/router/trie-matching.ts +170 -64
  1136. package/src/router/types.ts +9 -63
  1137. package/src/router/url-params.ts +13 -5
  1138. package/src/router.ts +248 -77
  1139. package/src/rsc/capture-queue.ts +218 -0
  1140. package/src/rsc/full-payload.ts +77 -0
  1141. package/src/rsc/handler-context.ts +4 -2
  1142. package/src/rsc/handler.ts +562 -284
  1143. package/src/rsc/helpers.ts +179 -9
  1144. package/src/rsc/index.ts +2 -5
  1145. package/src/rsc/json-route-result.ts +38 -0
  1146. package/src/rsc/loader-fetch.ts +116 -40
  1147. package/src/rsc/manifest-init.ts +55 -56
  1148. package/src/rsc/nonce.ts +10 -1
  1149. package/src/rsc/origin-guard.ts +39 -25
  1150. package/src/rsc/progressive-enhancement.ts +377 -84
  1151. package/src/rsc/redirect-guard.ts +102 -0
  1152. package/src/rsc/render-pipeline.ts +611 -0
  1153. package/src/rsc/response-cache-serve.ts +259 -0
  1154. package/src/rsc/response-error.ts +79 -12
  1155. package/src/rsc/response-route-handler.ts +73 -212
  1156. package/src/rsc/routine-plan.ts +359 -0
  1157. package/src/rsc/rsc-rendering.ts +1624 -171
  1158. package/src/rsc/runtime-warnings.ts +23 -10
  1159. package/src/rsc/server-action.ts +420 -139
  1160. package/src/rsc/shell-build-manifest.ts +336 -0
  1161. package/src/rsc/shell-capture-constants.ts +45 -0
  1162. package/src/rsc/shell-capture.ts +2063 -0
  1163. package/src/rsc/shell-serve.ts +337 -0
  1164. package/src/rsc/ssr-setup.ts +111 -16
  1165. package/src/rsc/stream-idle.ts +137 -0
  1166. package/src/rsc/transition-gate.ts +86 -0
  1167. package/src/rsc/types.ts +91 -5
  1168. package/src/runtime-env.ts +18 -0
  1169. package/src/search-params.ts +35 -30
  1170. package/src/segment-fragments.ts +165 -0
  1171. package/src/segment-loader-promise.ts +49 -4
  1172. package/src/segment-system.tsx +441 -153
  1173. package/src/serialize.ts +243 -0
  1174. package/src/server/context.ts +416 -55
  1175. package/src/server/cookie-parse.ts +32 -0
  1176. package/src/server/cookie-store.ts +162 -15
  1177. package/src/server/handle-store.ts +190 -70
  1178. package/src/server/loader-registry.ts +33 -42
  1179. package/src/server/request-context.ts +805 -177
  1180. package/src/server.ts +7 -2
  1181. package/src/ssr/index.tsx +631 -183
  1182. package/src/ssr/inject-rsc-eager.ts +167 -0
  1183. package/src/ssr/preinit-client-references.ts +106 -0
  1184. package/src/ssr/ssr-root.tsx +262 -0
  1185. package/src/static-handler.ts +28 -15
  1186. package/src/testing/cache-status.ts +162 -0
  1187. package/src/testing/collect-handle.ts +46 -0
  1188. package/src/testing/dispatch.ts +951 -0
  1189. package/src/testing/dom.entry.ts +22 -0
  1190. package/src/testing/e2e/fixture.ts +188 -0
  1191. package/src/testing/e2e/index.ts +147 -0
  1192. package/src/testing/e2e/matchers.ts +35 -0
  1193. package/src/testing/e2e/page-helpers.ts +319 -0
  1194. package/src/testing/e2e/parity.ts +400 -0
  1195. package/src/testing/e2e/server.ts +195 -0
  1196. package/src/testing/flight-matchers.ts +97 -0
  1197. package/src/testing/flight-normalize.ts +11 -0
  1198. package/src/testing/flight-runtime.d.ts +57 -0
  1199. package/src/testing/flight-tree.ts +682 -0
  1200. package/src/testing/flight.entry.ts +52 -0
  1201. package/src/testing/flight.ts +257 -0
  1202. package/src/testing/generated-routes.ts +199 -0
  1203. package/src/testing/index.ts +121 -0
  1204. package/src/testing/internal/context.ts +380 -0
  1205. package/src/testing/internal/flight-client-globals.ts +30 -0
  1206. package/src/testing/internal/seed-vars.ts +54 -0
  1207. package/src/testing/render-handler.ts +371 -0
  1208. package/src/testing/render-route.tsx +667 -0
  1209. package/src/testing/run-loader.ts +423 -0
  1210. package/src/testing/run-middleware.ts +219 -0
  1211. package/src/testing/run-transition-when.ts +197 -0
  1212. package/src/testing/shell-status.ts +206 -0
  1213. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  1214. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  1215. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  1216. package/src/testing/vitest-stubs/version.ts +5 -0
  1217. package/src/testing/vitest.ts +305 -0
  1218. package/src/theme/ThemeProvider.tsx +56 -84
  1219. package/src/theme/ThemeScript.tsx +7 -9
  1220. package/src/theme/constants.ts +52 -13
  1221. package/src/theme/index.ts +0 -7
  1222. package/src/theme/theme-context.ts +1 -5
  1223. package/src/theme/theme-script.ts +22 -21
  1224. package/src/theme/use-theme.ts +0 -3
  1225. package/src/types/boundaries.ts +15 -35
  1226. package/src/types/cache-types.ts +13 -4
  1227. package/src/types/error-types.ts +30 -90
  1228. package/src/types/global-namespace.ts +54 -41
  1229. package/src/types/handler-context.ts +121 -30
  1230. package/src/types/index.ts +3 -10
  1231. package/src/types/loader-types.ts +38 -7
  1232. package/src/types/request-scope.ts +8 -22
  1233. package/src/types/route-config.ts +20 -52
  1234. package/src/types/route-entry.ts +3 -6
  1235. package/src/types/segments.ts +147 -14
  1236. package/src/urls/include-helper.ts +38 -64
  1237. package/src/urls/include-provider.ts +71 -0
  1238. package/src/urls/index.ts +2 -11
  1239. package/src/urls/path-helper-types.ts +76 -24
  1240. package/src/urls/path-helper.ts +30 -110
  1241. package/src/urls/pattern-types.ts +101 -19
  1242. package/src/urls/response-types.ts +20 -19
  1243. package/src/urls/type-extraction.ts +98 -154
  1244. package/src/urls/urls-function.ts +1 -19
  1245. package/src/use-loader.tsx +355 -109
  1246. package/src/vercel/index.ts +11 -0
  1247. package/src/vercel/tracing.ts +89 -0
  1248. package/src/vite/debug.ts +102 -3
  1249. package/src/vite/discovery/bundle-postprocess.ts +18 -14
  1250. package/src/vite/discovery/client-urls-projection.ts +322 -0
  1251. package/src/vite/discovery/dev-prerender-cache.ts +117 -0
  1252. package/src/vite/discovery/discover-routers.ts +178 -151
  1253. package/src/vite/discovery/discovery-errors.ts +255 -0
  1254. package/src/vite/discovery/gate-state.ts +171 -0
  1255. package/src/vite/discovery/prerender-collection.ts +125 -70
  1256. package/src/vite/discovery/route-types-writer.ts +40 -84
  1257. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  1258. package/src/vite/discovery/shell-prerender-phase.ts +397 -0
  1259. package/src/vite/discovery/state.ts +104 -6
  1260. package/src/vite/discovery/virtual-module-codegen.ts +226 -87
  1261. package/src/vite/encryption-key.ts +29 -0
  1262. package/src/vite/index.ts +12 -0
  1263. package/src/vite/inject-client-debug.ts +88 -0
  1264. package/src/vite/plugin-types.ts +243 -10
  1265. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  1266. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  1267. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  1268. package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
  1269. package/src/vite/plugins/expose-action-id.ts +50 -97
  1270. package/src/vite/plugins/expose-id-utils.ts +88 -55
  1271. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  1272. package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
  1273. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  1274. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  1275. package/src/vite/plugins/expose-internal-ids.ts +551 -486
  1276. package/src/vite/plugins/performance-tracks.ts +25 -22
  1277. package/src/vite/plugins/refresh-cmd.ts +1 -1
  1278. package/src/vite/plugins/server-ref-hashing.ts +74 -0
  1279. package/src/vite/plugins/server-reference-pattern.ts +10 -0
  1280. package/src/vite/plugins/use-cache-transform.ts +73 -83
  1281. package/src/vite/plugins/vercel-output.ts +384 -0
  1282. package/src/vite/plugins/version-injector.ts +39 -29
  1283. package/src/vite/plugins/version-plugin.ts +45 -40
  1284. package/src/vite/plugins/virtual-entries.ts +193 -30
  1285. package/src/vite/rango.ts +240 -128
  1286. package/src/vite/router-discovery.ts +1518 -174
  1287. package/src/vite/utils/ast-handler-extract.ts +26 -35
  1288. package/src/vite/utils/bundle-analysis.ts +10 -15
  1289. package/src/vite/utils/client-chunks.ts +184 -0
  1290. package/src/vite/utils/directive-prologue.ts +40 -0
  1291. package/src/vite/utils/forward-user-plugins.ts +171 -0
  1292. package/src/vite/utils/manifest-utils.ts +1 -59
  1293. package/src/vite/utils/package-resolution.ts +2 -73
  1294. package/src/vite/utils/prerender-utils.ts +96 -49
  1295. package/src/vite/utils/shared-utils.ts +156 -43
  1296. package/src/browser/action-response-classifier.ts +0 -99
  1297. package/src/browser/react/use-client-cache.ts +0 -58
  1298. package/src/browser/shallow.ts +0 -40
  1299. package/src/handles/index.ts +0 -7
  1300. package/src/network-error-thrower.tsx +0 -23
  1301. package/src/router/middleware-cookies.ts +0 -55
@@ -7,247 +7,1700 @@
7
7
  */
8
8
 
9
9
  import {
10
- requireRequestContext,
10
+ getRequestContext,
11
11
  setRequestContextParams,
12
- getLocationState,
12
+ runWithRequestContext,
13
+ wireRenderBarrier,
13
14
  } from "../server/request-context.js";
14
- import { resolveLocationStateEntries } from "../browser/react/location-state-shared.js";
15
+ import {
16
+ SeededShellStore,
17
+ buildShellLoaderSeed,
18
+ } from "../cache/shell-snapshot.js";
15
19
  import { appendMetric } from "../router/metrics.js";
16
- import { getSSRSetup } from "./ssr-setup.js";
20
+ import { observePhase, PHASES } from "../router/instrument.js";
21
+ import type { TraceSpan } from "../router/tracing.js";
22
+ import { getSSRSetup, createSsrHtmlStage, isRscRequest } from "./ssr-setup.js";
17
23
  import type { RscPayload } from "./types.js";
24
+ import type { SSRModule } from "./types.js";
25
+ import type { RequestContext } from "../server/request-context.js";
18
26
  import {
19
27
  createResponseWithMergedHeaders,
20
28
  createSimpleRedirectResponse,
29
+ attachLocationStateIfPresent,
30
+ matchAndRecordParams,
21
31
  } from "./helpers.js";
32
+ import {
33
+ createRenderStageTraceBridge,
34
+ renderRscFlightStage,
35
+ renderRscResponse,
36
+ } from "./render-pipeline.js";
37
+ import {
38
+ createRoutineTrace,
39
+ handoff,
40
+ runRoutine,
41
+ scope,
42
+ step,
43
+ type RoutinePlan,
44
+ } from "./routine-plan.js";
22
45
  import type { HandlerContext } from "./handler-context.js";
46
+ import { gateTransitions } from "./transition-gate.js";
47
+ import { buildFullPayload } from "./full-payload.js";
48
+ import {
49
+ scheduleShellCapture,
50
+ resolveShellCaptureDebugSink,
51
+ takeCaptureDebugEventForTiming,
52
+ describeShellCaptureEvent,
53
+ type ShellCaptureDescriptor,
54
+ } from "./shell-capture.js";
55
+ import {
56
+ PPR_REPLAY_STATUS_HEADER,
57
+ SHELL_STATUS_HEADER,
58
+ resolvePprConfig,
59
+ buildShellKey,
60
+ isValidShellHit,
61
+ hasIntactShellPayload,
62
+ base64ToBytes,
63
+ hasShellFamily,
64
+ warnShellStoreMissingOnce,
65
+ warnPprNonceActiveOnce,
66
+ describeShellTailTiming,
67
+ publishShellTailTiming,
68
+ takeShellTailTimingForServerTiming,
69
+ type ResolvedPprConfig,
70
+ type ShellTailTiming,
71
+ } from "./shell-serve.js";
72
+ import {
73
+ lookupBuildShell,
74
+ type DevShellLookup,
75
+ } from "./shell-build-manifest.js";
76
+ import { contextGet } from "../context-var.js";
77
+ import {
78
+ getNavigationContextHeader,
79
+ prerenderStoreShortCircuits,
80
+ } from "../router/navigation-snapshot.js";
81
+ import {
82
+ ensureFullRouteSnapshot,
83
+ type RouteSnapshot,
84
+ } from "../router/route-snapshot.js";
85
+ import { prerenderEntryExists } from "../router/match-middleware/cache-lookup.js";
86
+ import {
87
+ resolveSameOriginRedirect,
88
+ safeSameOriginLanding,
89
+ } from "../redirect-origin.js";
90
+ import { nonce as nonceToken } from "./nonce.js";
91
+ import { reportCacheError } from "../cache/cache-error.js";
92
+ import type { SearchParamsFilter } from "../cache/search-params-filter.js";
93
+ import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
94
+ import type {
95
+ DocumentShellCacheEntry,
96
+ SegmentCacheStore,
97
+ ShellCacheEntry,
98
+ ShellSnapshotRecord,
99
+ } from "../cache/types.js";
100
+ import {
101
+ SEGMENT_FRAGMENT_CAPABILITY_HEADER,
102
+ SEGMENT_FRAGMENT_RECOVERY_HEADER,
103
+ } from "../segment-fragments.js";
104
+
105
+ type PprReplayBypassReason =
106
+ | "method"
107
+ | "dynamic"
108
+ | "nonce"
109
+ | "store-unavailable"
110
+ | "passive-read-unsupported"
111
+ | "no-navigation-context"
112
+ | "prerender-store"
113
+ | "intercept"
114
+ | "cache-disabled"
115
+ | "read-error"
116
+ | "no-entry"
117
+ | "invalid-version"
118
+ | "corrupt-entry"
119
+ | "handler-live-holes"
120
+ | "transition-when"
121
+ | "no-segment-snapshot"
122
+ | "snapshot-miss"
123
+ | "explicit-cache-hit"
124
+ | "stale-build-entry";
125
+
126
+ type PprReplayStatus =
127
+ | { outcome: "HIT"; freshness: "fresh" | "stale" }
128
+ | { outcome: "BYPASS"; reason: PprReplayBypassReason };
129
+
130
+ type ShellReplayDecision =
131
+ | { snapshot: ShellSnapshotRecord[] }
132
+ | { reason: PprReplayBypassReason };
133
+
134
+ function serializePprReplayStatus(status: PprReplayStatus): string {
135
+ return status.outcome === "HIT"
136
+ ? `HIT; freshness=${status.freshness}`
137
+ : `BYPASS; reason=${status.reason}`;
138
+ }
139
+
140
+ function describePprReplayStatus(status: PprReplayStatus): string {
141
+ return status.outcome === "HIT"
142
+ ? status.freshness
143
+ : `bypass:${status.reason}`;
144
+ }
145
+
146
+ function buildNavigationShellKey(
147
+ url: URL,
148
+ filter?: SearchParamsFilter,
149
+ ): string {
150
+ return `${buildShellKey(url, filter)}:navigation`;
151
+ }
152
+
153
+ function createShellCaptureDescriptor(
154
+ ctx: HandlerContext<any>,
155
+ key: string,
156
+ pprConfig: ResolvedPprConfig,
157
+ store: SegmentCacheStore<any>,
158
+ navigationOnly?: true,
159
+ ): ShellCaptureDescriptor {
160
+ return {
161
+ key,
162
+ buildVersion: ctx.version,
163
+ ttl: pprConfig.ttl,
164
+ swr: pprConfig.swr,
165
+ tags: pprConfig.tags,
166
+ captureTimeout: pprConfig.captureTimeout,
167
+ store,
168
+ debug: INTERNAL_RANGO_DEBUG,
169
+ maxSnapshotBytes: pprConfig.maxSnapshotBytes,
170
+ debugSink: resolveShellCaptureDebugSink(ctx.router.debugShellCapture),
171
+ navigationOnly,
172
+ };
173
+ }
174
+
175
+ function shouldHealReplayMiss(
176
+ reason: PprReplayBypassReason | undefined,
177
+ ): boolean {
178
+ return (
179
+ reason === undefined ||
180
+ reason === "invalid-version" ||
181
+ reason === "corrupt-entry" ||
182
+ reason === "stale-build-entry"
183
+ );
184
+ }
185
+
186
+ /**
187
+ * Post-match truth override for a pre-match BYPASS classification. The gate
188
+ * decides before matchPartial runs, but two facts only the match can settle:
189
+ * whether the prerender store ACTUALLY served (either artifact variant — the
190
+ * gate's probe reads only the non-intercept one), and whether the navigation
191
+ * resolved to an intercept (findInterceptForRoute runs during the match; the
192
+ * intercept-source header proves nothing in either direction). The resulting
193
+ * reason is stamped on the request context by withCacheLookup. A replay HIT is
194
+ * never overridden — the seeded record was demonstrably consumed, so neither
195
+ * fact can be true.
196
+ */
197
+ function reclassifyReplayStatus(
198
+ reqCtx: RequestContext<any>,
199
+ status: PprReplayStatus,
200
+ ): PprReplayStatus {
201
+ if (status.outcome === "HIT") return status;
202
+ const reason = reqCtx._pprReplayPostMatchReason;
203
+ return reason ? { outcome: "BYPASS", reason } : status;
204
+ }
205
+
206
+ function resolveDevShellLookup(
207
+ reqCtx: RequestContext<any>,
208
+ pprConfig: ResolvedPprConfig,
209
+ ): DevShellLookup | undefined {
210
+ if (process.env.NODE_ENV === "production") return undefined;
211
+ return {
212
+ isPrerenderRoute: reqCtx._classifiedRoute?.matched?.pr === true,
213
+ routeName: reqCtx._classifiedRoute?.routeKey,
214
+ ttl: pprConfig.ttl,
215
+ swr: pprConfig.swr,
216
+ tags: pprConfig.tags,
217
+ maxSnapshotBytes: pprConfig.maxSnapshotBytes,
218
+ captureTimeout: pprConfig.captureTimeout,
219
+ };
220
+ }
221
+
222
+ function replayableShellSnapshot(
223
+ entry: ShellCacheEntry,
224
+ buildVersion: string,
225
+ ): ShellReplayDecision {
226
+ if (!isValidShellHit(entry, buildVersion)) {
227
+ return { reason: "invalid-version" };
228
+ }
229
+ // navigationOnly entries store no document half (prelude/postponed absent),
230
+ // so the payload gate applies to document-snapshot entries alone. Replay
231
+ // consumes only the snapshot; fragment corruption inside it is caught by the
232
+ // consumer-side Flight decoders (SegmentFragmentDecodeError →
233
+ // segmentReplayCorrupt → healing capture at the document key).
234
+ if (!entry.navigationOnly && !hasIntactShellPayload(entry)) {
235
+ return { reason: "corrupt-entry" };
236
+ }
237
+ if (entry.handlerLiveHoles) return { reason: "handler-live-holes" };
238
+ if (entry.transitionWhen) return { reason: "transition-when" };
239
+ // Eligibility requires the CANONICAL doc segment record (`docKey`), not just
240
+ // any segment record: captures under an explicit cache() scope also record
241
+ // that tier's reads/writes under keys a partial lookup can never resolve,
242
+ // and counting those declared entries "replayable" that then always missed
243
+ // (a timing-dependent snapshot-miss/no-segment-snapshot flip-flop). Entries
244
+ // captured before the field existed read as no-segment-snapshot and heal on
245
+ // recapture (pre-release, same treatment as the buildVersion field).
246
+ const docKey = entry.docKey;
247
+ const snapshot = entry.snapshot;
248
+ const hasDocRecord =
249
+ docKey !== undefined &&
250
+ snapshot?.some((record) => {
251
+ if (
252
+ !record ||
253
+ typeof record !== "object" ||
254
+ record.family !== "segment" ||
255
+ record.key !== docKey ||
256
+ typeof record.value !== "object" ||
257
+ record.value === null
258
+ ) {
259
+ return false;
260
+ }
261
+ const segments = (record.value as { segments?: unknown }).segments;
262
+ return Array.isArray(segments) && segments.length > 0;
263
+ });
264
+ return hasDocRecord && snapshot
265
+ ? { snapshot }
266
+ : { reason: "no-segment-snapshot" };
267
+ }
268
+
269
+ export function handleRscRendering<TEnv>(
270
+ ctx: HandlerContext<TEnv>,
271
+ request: Request,
272
+ env: TEnv,
273
+ url: URL,
274
+ isPartial: boolean,
275
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
276
+ nonce: string | undefined,
277
+ ): Promise<Response> {
278
+ // Instrument the whole render phase once through the unified API: it records
279
+ // the "render:total" perf metric AND opens the "rango.render" span from the
280
+ // same boundary (match -> serialize -> SSR), so the two surfaces agree.
281
+ // Loaders kicked off during matching nest under the span; the SSR HTML pass
282
+ // below opens "rango.ssr" the same way.
283
+ return observePhase(PHASES.render, (span) =>
284
+ handleRscRenderingInner(
285
+ ctx,
286
+ request,
287
+ env,
288
+ url,
289
+ isPartial,
290
+ handleStore,
291
+ nonce,
292
+ span,
293
+ ),
294
+ );
295
+ }
296
+
297
+ interface RequestRenderInput<TEnv> {
298
+ ctx: HandlerContext<TEnv>;
299
+ request: Request;
300
+ env: TEnv;
301
+ url: URL;
302
+ isPartial: boolean;
303
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"];
304
+ nonce: string | undefined;
305
+ renderSpan: TraceSpan;
306
+ reqCtx: ReturnType<typeof getRequestContext>;
307
+ }
23
308
 
24
- export async function handleRscRendering<TEnv>(
309
+ type ShellServeOutcome =
310
+ | { kind: "serve"; response: Response }
311
+ | { kind: "miss"; descriptor: ShellCaptureDescriptor; ssrModule: SSRModule }
312
+ | { kind: "pass" };
313
+
314
+ type PreparedRender =
315
+ | { kind: "control"; response: Response }
316
+ | {
317
+ kind: "payload";
318
+ payload: RscPayload;
319
+ hasInterceptSlots: boolean;
320
+ pprReplayStatus?: PprReplayStatus;
321
+ partialCaptureNeeded: boolean;
322
+ partialCaptureKey?: string;
323
+ };
324
+
325
+ async function handleRscRenderingInner<TEnv>(
25
326
  ctx: HandlerContext<TEnv>,
26
327
  request: Request,
27
328
  env: TEnv,
28
329
  url: URL,
29
330
  isPartial: boolean,
30
- handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
331
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
31
332
  nonce: string | undefined,
333
+ renderSpan: TraceSpan,
32
334
  ): Promise<Response> {
33
- const reqCtx = requireRequestContext();
335
+ // Flow trace rides the internal debug surface (INTERNAL_RANGO_DEBUG=1): the
336
+ // Vite pipeline bakes the flag at build/dev-server start (inject-client-debug),
337
+ // so trace allocation and output fold out of ordinary production builds while
338
+ // an explicit debug build keeps them. The routine itself remains the executor.
339
+ const mode = isPartial ? "partial" : "document";
340
+ const trace = INTERNAL_RANGO_DEBUG ? createRoutineTrace(mode) : undefined;
341
+ const reqCtx = getRequestContext();
342
+ const input: RequestRenderInput<TEnv> = {
343
+ ctx,
344
+ request,
345
+ env,
346
+ url,
347
+ isPartial,
348
+ handleStore,
349
+ nonce,
350
+ renderSpan,
351
+ reqCtx,
352
+ };
353
+ try {
354
+ return await runRoutine(requestRenderPlan(input), {
355
+ trace,
356
+ owner: reqCtx,
357
+ });
358
+ } finally {
359
+ if (trace) {
360
+ console.log(
361
+ `[routine] ${request.method} ${url.pathname} (${trace.name})\n${trace.format()}`,
362
+ );
363
+ }
364
+ }
365
+ }
366
+
367
+ /**
368
+ * The request-level render plan. Reads top to bottom as the request executes:
369
+ * serve a stored PPR shell if one commits, otherwise match and build the
370
+ * payload, render it through the stage driver, then hand off background
371
+ * captures. Effects run through the routine runner (yield-before-execute,
372
+ * exact result/error identity — see routine-plan.ts).
373
+ */
374
+ function* requestRenderPlan<TEnv>(
375
+ input: RequestRenderInput<TEnv>,
376
+ ): RoutinePlan<Response> {
377
+ const { isPartial, reqCtx } = input;
378
+
379
+ // --- Axis 2: integrated PPR shell serve (docs/design/ppr-shell-resume.md) ---
380
+ //
381
+ // COMMIT POINT: this render pass runs strictly AFTER the whole middleware
382
+ // chain (executeRender wraps it), so no shell byte can precede a guard
383
+ // decision — that ordering is what makes a shared shell safe. Routes
384
+ // without the `ppr` option stay pure axis 1 at zero cost.
385
+ const shell = yield* scope("shell-serve", shellServePlan(input));
386
+ if (shell.kind === "serve") return shell.response;
34
387
 
35
- let payload: RscPayload;
36
- let hasInterceptSlots = false;
388
+ // Match + payload. A control response (redirect, prerender collection)
389
+ // ends the plan before any rendering.
390
+ const prepared = yield* scope(
391
+ isPartial ? "prepare:partial" : "prepare:full",
392
+ preparePayloadPlan(input),
393
+ );
394
+ if (prepared.kind === "control") return prepared.response;
395
+
396
+ // For partial requests, include any server-set location state in the payload.
397
+ // SSR (full page) requests ignore location state since there's no history.state
398
+ // to write to on a fresh page load.
399
+ if (isPartial && prepared.payload.metadata) {
400
+ attachLocationStateIfPresent(prepared.payload);
401
+ }
402
+
403
+ const response = yield* step("render", () =>
404
+ renderPreparedRscResponse(input, prepared),
405
+ );
406
+
407
+ // --- Axis 2: PPR shell CAPTURE on MISS (background task; see design doc) ---
408
+ // Capture only a 200 HTML document (a 404/error render is not a cacheable
409
+ // shell). Capture does not flow through the HTTP pipeline — middleware never
410
+ // re-runs (it already ran for this request; guarding is serve-time).
411
+ // reqCtx._dynamic is re-read here on purpose: a loader may have marked the
412
+ // request dynamic while rendering.
413
+ if (shell.kind === "miss" && !reqCtx._dynamic) {
414
+ if (
415
+ response.status === 200 &&
416
+ (response.headers.get("content-type") ?? "").includes("text/html")
417
+ ) {
418
+ const { descriptor, ssrModule } = shell;
419
+ yield* handoff("shell-capture", () =>
420
+ scheduleShellCapture(
421
+ input.ctx,
422
+ input.request,
423
+ input.env,
424
+ input.url,
425
+ reqCtx,
426
+ ssrModule,
427
+ descriptor,
428
+ ),
429
+ );
430
+ }
431
+ response.headers.set(SHELL_STATUS_HEADER, "MISS");
432
+ }
433
+
434
+ if (
435
+ isPartial &&
436
+ prepared.partialCaptureNeeded &&
437
+ !reqCtx._dynamic &&
438
+ response.status === 200
439
+ ) {
440
+ const captureKey = prepared.partialCaptureKey;
441
+ yield* handoff("navigation-shell-capture", () =>
442
+ scheduleNavigationShellCapture(input, captureKey),
443
+ );
444
+ }
445
+
446
+ return response;
447
+ }
448
+
449
+ /**
450
+ * Axis 2 shell serve. Sync gates stay plan code; store and SSR effects run as
451
+ * named steps. Outcomes: serve a composed shell response, report a MISS (the
452
+ * top-level plan schedules the capture after the response commits), or pass
453
+ * (route not eligible — pure axis 1).
454
+ */
455
+ function* shellServePlan<TEnv>(
456
+ input: RequestRenderInput<TEnv>,
457
+ ): RoutinePlan<ShellServeOutcome> {
458
+ const { ctx, request, env, url, isPartial, handleStore, nonce, reqCtx } =
459
+ input;
460
+
461
+ if (
462
+ isPartial ||
463
+ request.method !== "GET" ||
464
+ url.searchParams.has("__prerender_collect") ||
465
+ isRscRequest(request, url, false) ||
466
+ reqCtx._dynamic
467
+ ) {
468
+ return { kind: "pass" };
469
+ }
470
+ const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry);
471
+ if (!pprConfig) return { kind: "pass" };
472
+
473
+ // A per-request CSP nonce pins the route to axis 1: a shared shell would
474
+ // freeze the capture request's nonce and CSP would reject it for every
475
+ // other visitor. BOTH nonce sources must gate — the createRouter({ nonce })
476
+ // provider (`nonce` param) and a middleware ctx.set(nonce, …) token write;
477
+ // the provider-only check missed the latter (issue #656).
478
+ const activeNonce = nonce ?? contextGet(reqCtx._variables, nonceToken);
479
+ const store = reqCtx._cacheStore;
480
+ const key = buildShellKey(url, reqCtx._searchParamsFilter);
481
+ mirrorPprServerTimingsForDev(key, reqCtx);
482
+ if (activeNonce !== undefined) {
483
+ // Declared intent that cannot be honored deserves a diagnostic (unlike an
484
+ // undeclared route, which is silent): a ppr route gated off by an active
485
+ // per-request nonce warns once per key. Axis 1 after the warning.
486
+ warnPprNonceActiveOnce(key);
487
+ return { kind: "pass" };
488
+ }
489
+ if (!hasShellFamily(store)) {
490
+ // Declared intent that cannot be honored deserves a diagnostic (unlike an
491
+ // undeclared route, which is silent). Axis 1 after the warning.
492
+ warnShellStoreMissingOnce(key);
493
+ return { kind: "pass" };
494
+ }
495
+
496
+ // SSR setup starts before route handling, so read the shell before joining it
497
+ // to overlap the remaining setup work with cache I/O.
498
+ const cached = yield* step("shell-read", () =>
499
+ readShellEntry(store, key, reqCtx),
500
+ );
501
+
502
+ // allReady (ssr.resolveStreaming) bypasses PPR entirely: buffering defeats
503
+ // streaming, so bots/SEO crawlers get one complete axis-1 document. These
504
+ // routes pay one unnecessary shell read to keep the PPR hot path concurrent.
505
+ const [ssrModule, streamMode] = yield* step("ssr-setup", () =>
506
+ getSSRSetup(ctx, request, env, url, reqCtx._metricsStore),
507
+ );
508
+ if (
509
+ streamMode === "allReady" ||
510
+ !ssrModule.resumeShellHTML ||
511
+ !ssrModule.captureShellHTML
512
+ ) {
513
+ return { kind: "pass" };
514
+ }
515
+ const descriptor = createShellCaptureDescriptor(ctx, key, pprConfig, store);
516
+
517
+ if (
518
+ cached &&
519
+ !cached.entry.navigationOnly &&
520
+ isValidShellHit(cached.entry, ctx.version)
521
+ ) {
522
+ if (!hasIntactShellPayload(cached.entry)) {
523
+ // Corrupt stored payload (undecodable prelude / unparseable
524
+ // postponed): a store-layer fault worth a diagnostic, unlike the
525
+ // silent version-mismatch lifecycle misses above. Degrade to MISS
526
+ // — the top-level plan schedules the recapture that overwrites it.
527
+ reportCacheError(
528
+ new Error(
529
+ `corrupt shell entry for "${key}": prelude/postponed failed ` +
530
+ "the integrity check; serving axis 1 and recapturing",
531
+ ),
532
+ "cache-read",
533
+ "[ShellServe] getShell",
534
+ );
535
+ } else {
536
+ // Stale (SWR) hit: serve the stale shell now, recapture in the
537
+ // background (stampede-guarded + backoff inside scheduleShellCapture).
538
+ if (cached.shouldRevalidate) {
539
+ yield* handoff("shell-recapture", () =>
540
+ scheduleShellCapture(
541
+ ctx,
542
+ request,
543
+ env,
544
+ url,
545
+ reqCtx,
546
+ ssrModule,
547
+ descriptor,
548
+ ),
549
+ );
550
+ }
551
+ const entry = cached.entry;
552
+ const response = yield* step("shell-hit", () =>
553
+ serveShellHit(
554
+ ctx,
555
+ request,
556
+ env,
557
+ url,
558
+ reqCtx,
559
+ handleStore,
560
+ ssrModule,
561
+ entry,
562
+ descriptor,
563
+ ),
564
+ );
565
+ return { kind: "serve", response };
566
+ }
567
+ }
568
+
569
+ // Build-time shell read-through (producer B, #699): on a runtime
570
+ // store MISS a Prerender+ppr route serves its `vite build`-baked
571
+ // shell through the SAME serve path. lookupBuildShell owns every
572
+ // gate and fails to null (ordinary MISS path takes over); past
573
+ // ppr.ttl the baked entry still serves while SWR recaptures — the
574
+ // upgrade path from build entry to runtime entry.
575
+ const buildHit = yield* step("build-shell-lookup", () =>
576
+ lookupBuildShell(
577
+ url,
578
+ ctx.version,
579
+ store,
580
+ // Dev: no build manifest exists; producer B runs on demand via
581
+ // the dev server's /__rsc_shell endpoint for PRERENDERED routes
582
+ // only (production's exact candidate set). Folded away in
583
+ // production builds (NODE_ENV is a compile-time constant).
584
+ resolveDevShellLookup(reqCtx, pprConfig),
585
+ reqCtx._searchParamsFilter,
586
+ ),
587
+ );
588
+ if (buildHit) {
589
+ // Past ppr.ttl: still serve the baked entry, recapture upgrades it.
590
+ if (buildHit.stale) {
591
+ yield* handoff("shell-recapture", () =>
592
+ scheduleShellCapture(
593
+ ctx,
594
+ request,
595
+ env,
596
+ url,
597
+ reqCtx,
598
+ ssrModule,
599
+ descriptor,
600
+ ),
601
+ );
602
+ }
603
+ const response = yield* step("shell-hit", () =>
604
+ serveShellHit(
605
+ ctx,
606
+ request,
607
+ env,
608
+ url,
609
+ reqCtx,
610
+ handleStore,
611
+ ssrModule,
612
+ buildHit.entry,
613
+ descriptor,
614
+ ),
615
+ );
616
+ return { kind: "serve", response };
617
+ }
618
+
619
+ // MISS (no entry, invalid reactVersion, or store read failure): axis 1
620
+ // + a background capture scheduled once the response is known servable.
621
+ return { kind: "miss", descriptor, ssrModule };
622
+ }
623
+
624
+ /**
625
+ * Match the request and assemble the RSC payload, or produce a control
626
+ * response (redirect, prerender collection) that ends the request plan.
627
+ */
628
+ function* preparePayloadPlan<TEnv>(
629
+ input: RequestRenderInput<TEnv>,
630
+ ): RoutinePlan<PreparedRender> {
631
+ const { ctx, request, env, url, isPartial, handleStore, nonce, reqCtx } =
632
+ input;
37
633
 
38
634
  if (isPartial) {
39
635
  // Partial render (navigation)
40
- const result = await ctx.router.matchPartial(request, { env });
636
+ const replay = yield* step("match:ppr-replay", () =>
637
+ matchPartialAndRecordParams(ctx, request, env, url, reqCtx, nonce),
638
+ );
639
+ const result = replay.result;
640
+ const pprReplayStatus = replay.status;
641
+ const partialCaptureNeeded =
642
+ "captureNeeded" in replay && replay.captureNeeded === true;
643
+ const partialCaptureKey =
644
+ "captureKey" in replay ? replay.captureKey : undefined;
41
645
 
42
646
  if (!result) {
43
647
  // Fall back to full render
44
- const match = await ctx.router.match(request, { env });
45
- setRequestContextParams(match.params, match.routeName);
648
+ const match = yield* step("match:fallback", () =>
649
+ matchAndRecordParams(ctx, request, env),
650
+ );
46
651
 
47
652
  if (match.redirect) {
48
653
  // Partial request: use X-RSC-Redirect header so the client can
49
654
  // perform SPA navigation. A raw 308 would be auto-followed by
50
- // fetch, hitting the target without _rsc_partial.
51
- return createSimpleRedirectResponse(match.redirect);
655
+ // fetch, hitting the target without _rsc_partial. Resolve the
656
+ // target server-side (same open-redirect policy as 3xx).
657
+ const redirectResponse = createSimpleRedirectResponse(match.redirect, {
658
+ requestOrigin: url.origin,
659
+ basename: ctx.router.basename,
660
+ });
661
+ if (pprReplayStatus) {
662
+ redirectResponse.headers.set(
663
+ PPR_REPLAY_STATUS_HEADER,
664
+ serializePprReplayStatus(pprReplayStatus),
665
+ );
666
+ }
667
+ return { kind: "control", response: redirectResponse };
52
668
  }
53
669
 
54
- payload = {
55
- metadata: {
56
- pathname: url.pathname,
57
- routerId: ctx.router.id,
58
- basename: ctx.router.basename,
59
- segments: match.segments,
60
- matched: match.matched,
61
- diff: match.diff,
62
- params: match.params,
63
- isPartial: false,
64
- rootLayout: ctx.router.rootLayout,
65
- handles: handleStore.stream(),
66
- version: ctx.version,
67
- prefetchCacheTTL: ctx.router.prefetchCacheTTL,
68
- themeConfig: ctx.router.themeConfig,
69
- initialTheme: reqCtx.theme,
70
- },
670
+ return {
671
+ kind: "payload",
672
+ payload: buildFullPayload(match, ctx, url, reqCtx, handleStore),
673
+ hasInterceptSlots: false,
674
+ pprReplayStatus,
675
+ partialCaptureNeeded,
676
+ partialCaptureKey,
71
677
  };
72
- } else {
73
- setRequestContextParams(result.params, result.routeName);
74
-
75
- hasInterceptSlots = !!result.slots;
678
+ }
76
679
 
77
- payload = {
680
+ return {
681
+ kind: "payload",
682
+ payload: {
78
683
  metadata: {
79
684
  pathname: url.pathname,
685
+ // routerId is serialized on every payload (including within-session
686
+ // ones) so the frontend can read the current app/router identity. It
687
+ // always equals the current app's id: a cross-app navigation is
688
+ // intercepted server-side (X-RSC-Reload) and never delivers a
689
+ // different-router payload to the client.
80
690
  routerId: ctx.router.id,
81
- segments: result.segments,
691
+ segments: gateTransitions(
692
+ result.segments,
693
+ reqCtx,
694
+ ctx.router.onError,
695
+ ),
82
696
  matched: result.matched,
83
697
  diff: result.diff,
698
+ resolvedIds: result.resolvedIds,
84
699
  params: result.params,
85
700
  isPartial: true,
86
701
  slots: result.slots,
702
+ interceptTargets: result.interceptTargets,
87
703
  handles: handleStore.stream(),
88
704
  version: ctx.version,
89
705
  prefetchCacheTTL: ctx.router.prefetchCacheTTL,
706
+ prefetchCacheSize: ctx.router.prefetchCacheSize,
707
+ prefetchConcurrency: ctx.router.prefetchConcurrency,
708
+ defaultPrefetch: ctx.router.defaultPrefetch,
709
+ stateCookieName: ctx.router.resolvedStateCookieName,
90
710
  },
91
- };
92
- }
93
- } else {
94
- // Full render (initial page load)
95
- const match = await ctx.router.match(request, { env });
96
- setRequestContextParams(match.params, match.routeName);
711
+ },
712
+ hasInterceptSlots: !!result.slots,
713
+ pprReplayStatus,
714
+ partialCaptureNeeded,
715
+ partialCaptureKey,
716
+ };
717
+ }
718
+
719
+ // Full render (initial page load)
720
+ const match = yield* step("match", () =>
721
+ matchAndRecordParams(ctx, request, env),
722
+ );
97
723
 
98
- if (match.redirect) {
99
- return createResponseWithMergedHeaders(null, {
724
+ if (match.redirect) {
725
+ return {
726
+ kind: "control",
727
+ response: createResponseWithMergedHeaders(null, {
100
728
  status: 308,
101
729
  headers: { Location: match.redirect },
102
- });
103
- }
730
+ }),
731
+ };
732
+ }
733
+
734
+ // Caching is now handled in router.match() via cache provider in request context
735
+ // match.segments already contains cached or fresh segments as appropriate
736
+
737
+ if (url.searchParams.has("__prerender_collect")) {
738
+ const response = yield* step("prerender-collect", () =>
739
+ collectPrerenderArtifacts(match, handleStore),
740
+ );
741
+ return { kind: "control", response };
742
+ }
743
+
744
+ return {
745
+ kind: "payload",
746
+ payload: buildFullPayload(match, ctx, url, reqCtx, handleStore),
747
+ hasInterceptSlots: false,
748
+ partialCaptureNeeded: false,
749
+ };
750
+ }
751
+
752
+ /**
753
+ * PPR replay match that stamps params/routeName when a replay result exists.
754
+ * A null result records nothing — the fallback match records its own.
755
+ */
756
+ async function matchPartialAndRecordParams<TEnv>(
757
+ ctx: HandlerContext<TEnv>,
758
+ request: Request,
759
+ env: TEnv,
760
+ url: URL,
761
+ reqCtx: RequestContext<any>,
762
+ nonce: string | undefined,
763
+ ): Promise<Awaited<ReturnType<typeof matchPartialWithPprReplay<TEnv>>>> {
764
+ const replay = await matchPartialWithPprReplay(
765
+ ctx,
766
+ request,
767
+ env,
768
+ url,
769
+ reqCtx,
770
+ nonce,
771
+ );
772
+ if (replay.result) {
773
+ setRequestContextParams(replay.result.params, replay.result.routeName);
774
+ }
775
+ return replay;
776
+ }
104
777
 
105
- // Caching is now handled in router.match() via cache provider in request context
106
- // match.segments already contains cached or fresh segments as appropriate
778
+ /**
779
+ * Shell store read that degrades to null on failure (axis 1 MISS, never a 500)
780
+ * and records the raw `ppr:shell-read` outcome (pre-validity-gates, so a
781
+ * version-mismatch lifecycle miss stays distinguishable from a store miss).
782
+ */
783
+ async function readShellEntry<
784
+ TStore extends { getShell(key: string): Promise<unknown> },
785
+ >(
786
+ store: TStore,
787
+ key: string,
788
+ reqCtx: ReturnType<typeof getRequestContext>,
789
+ ): Promise<Awaited<ReturnType<TStore["getShell"]>> | null> {
790
+ let cached: Awaited<ReturnType<TStore["getShell"]>> | null = null;
791
+ const shellReadStart = reqCtx._metricsStore ? performance.now() : 0;
792
+ try {
793
+ // The constraint types the call as Promise<unknown>; the instantiated
794
+ // TStore carries the real entry type, so the assertion restores it.
795
+ cached = (await store.getShell(key)) as Awaited<
796
+ ReturnType<TStore["getShell"]>
797
+ >;
798
+ } catch (error) {
799
+ reportCacheError(error, "cache-read", "[ShellServe] getShell");
800
+ }
801
+ if (reqCtx._metricsStore) {
802
+ appendMetric(
803
+ reqCtx._metricsStore,
804
+ "ppr:shell-read",
805
+ shellReadStart,
806
+ performance.now() - shellReadStart,
807
+ undefined,
808
+ cached ? "hit" : "miss",
809
+ );
810
+ }
811
+ return cached;
812
+ }
107
813
 
108
- if (url.searchParams.has("__prerender_collect")) {
109
- // Build-time prerender collection: serialize segments and handle data
110
- // to JSON for storage as build artifacts. At runtime the worker
111
- // deserializes these and feeds them through the normal segment pipeline.
112
- const nonLoaderSegments = match.segments.filter(
113
- (s) => s.type !== "loader",
814
+ /**
815
+ * Dev Server-Timing mirror (issue #651): a capture completes AFTER its
816
+ * triggering response committed, so its outcome can only ride a LATER
817
+ * response's header. Read-and-clear keeps one capture = one report;
818
+ * dev-only (see takeCaptureDebugEventForTiming).
819
+ */
820
+ function mirrorPprServerTimingsForDev(
821
+ key: string,
822
+ reqCtx: ReturnType<typeof getRequestContext>,
823
+ ): void {
824
+ if (process.env.NODE_ENV !== "production" && reqCtx._metricsStore) {
825
+ const lastCapture = takeCaptureDebugEventForTiming(key);
826
+ if (lastCapture) {
827
+ appendMetric(
828
+ reqCtx._metricsStore,
829
+ "ppr:capture",
830
+ performance.now(),
831
+ lastCapture.attemptMs ?? 0,
832
+ undefined,
833
+ // attemptMs already rides as this entry's dur — drop it from desc.
834
+ describeShellCaptureEvent({ ...lastCapture, attemptMs: undefined }),
114
835
  );
115
- handleStore.seal();
116
- await handleStore.settled;
117
- const { serializeSegments } = await import("../cache/segment-codec.js");
118
- const serializedSegments = await serializeSegments(nonLoaderSegments);
119
- const handles: Record<string, Record<string, unknown[]>> = {};
120
- for (const seg of nonLoaderSegments) {
121
- const segHandles = handleStore.getDataForSegment(seg.id);
122
- if (Object.keys(segHandles).length > 0) {
123
- handles[seg.id] = segHandles;
124
- }
125
- }
126
- return new Response(
127
- JSON.stringify({
128
- segments: serializedSegments,
129
- handles,
130
- routeName: match.routeName,
131
- params: match.params,
132
- }),
133
- { headers: { "Content-Type": "application/json" } },
836
+ }
837
+ // Same mirror for the previous HIT's tail: its per-stage numbers
838
+ // (seed/match/handover/first-html/complete) finished after that
839
+ // response's headers were committed, so they ride THIS request's
840
+ // Server-Timing as `ppr:tail;dur=<complete ms>`.
841
+ const lastTail = takeShellTailTimingForServerTiming(key);
842
+ if (lastTail) {
843
+ appendMetric(
844
+ reqCtx._metricsStore,
845
+ "ppr:tail",
846
+ performance.now(),
847
+ lastTail.completeMs ?? 0,
848
+ undefined,
849
+ // completeMs already rides as this entry's dur — drop it from desc.
850
+ describeShellTailTiming({ ...lastTail, completeMs: undefined }),
134
851
  );
135
- } else {
136
- payload = {
137
- // Initial SSR can reconstruct the tree from segments + rootLayout,
138
- // so we omit root to avoid sending the same structure twice.
139
-
140
- metadata: {
141
- pathname: url.pathname,
142
- routerId: ctx.router.id,
143
- basename: ctx.router.basename,
144
- segments: match.segments,
145
- matched: match.matched,
146
- diff: match.diff,
147
- params: match.params,
148
- isPartial: false,
149
- rootLayout: ctx.router.rootLayout,
150
- handles: handleStore.stream(),
151
- version: ctx.version,
152
- prefetchCacheTTL: ctx.router.prefetchCacheTTL,
153
- themeConfig: ctx.router.themeConfig,
154
- initialTheme: reqCtx.theme,
155
- },
156
- };
157
852
  }
158
853
  }
854
+ }
159
855
 
160
- // For partial requests, include any server-set location state in the payload.
161
- // SSR (full page) requests ignore location state since there's no history.state
162
- // to write to on a fresh page load.
163
- if (isPartial && payload.metadata) {
164
- const locationState = getLocationState();
165
- if (locationState) {
166
- payload.metadata.locationState =
167
- resolveLocationStateEntries(locationState);
856
+ /**
857
+ * Build-time prerender collection: serialize segments and handle data
858
+ * to JSON for storage as build artifacts. At runtime the worker
859
+ * deserializes these and feeds them through the normal segment pipeline.
860
+ */
861
+ async function collectPrerenderArtifacts<TEnv>(
862
+ match: Awaited<ReturnType<HandlerContext<TEnv>["router"]["match"]>>,
863
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
864
+ ): Promise<Response> {
865
+ const nonLoaderSegments = match.segments.filter((s) => s.type !== "loader");
866
+ handleStore.seal();
867
+ await handleStore.settled;
868
+ const { serializeSegments } = await import("../cache/segment-codec.js");
869
+ const serializedSegments = await serializeSegments(nonLoaderSegments);
870
+ const handles: Record<string, Record<string, unknown[]>> = {};
871
+ for (const seg of nonLoaderSegments) {
872
+ const segHandles = handleStore.getDataForSegment(seg.id);
873
+ if (Object.keys(segHandles).length > 0) {
874
+ handles[seg.id] = segHandles;
168
875
  }
169
876
  }
877
+ return new Response(
878
+ JSON.stringify({
879
+ segments: serializedSegments,
880
+ handles,
881
+ routeName: match.routeName,
882
+ params: match.params,
883
+ }),
884
+ { headers: { "Content-Type": "application/json" } },
885
+ );
886
+ }
170
887
 
888
+ /** Assemble headers + tracking and run the foreground stage-driver render. */
889
+ function renderPreparedRscResponse<TEnv>(
890
+ input: RequestRenderInput<TEnv>,
891
+ prepared: Extract<PreparedRender, { kind: "payload" }>,
892
+ ): Promise<Response> {
893
+ const { ctx, request, env, url, isPartial, nonce, reqCtx, renderSpan } =
894
+ input;
895
+ const { payload, pprReplayStatus, hasInterceptSlots } = prepared;
171
896
  const metricsStore = reqCtx._metricsStore;
172
- const renderStart = performance.now();
173
-
174
- // Serialize to RSC stream
175
- const rscSerializeStart = performance.now();
176
- const rscStream = ctx.renderToReadableStream<RscPayload>(payload, {
177
- onError: (error: unknown) => {
178
- ctx.callOnError(error, "rendering", { request, url, env });
179
- },
180
- });
181
- const rscSerializeDur = performance.now() - rscSerializeStart;
182
- // This measures synchronous stream creation, not end-to-end stream consumption.
183
- appendMetric(
184
- metricsStore,
185
- "rsc-serialize",
186
- rscSerializeStart,
187
- rscSerializeDur,
188
- );
189
897
 
190
- // Determine if this is an RSC request or HTML request.
191
- // Partial requests (_rsc_partial) are always RSC -- they come from client-side
192
- // navigation or prefetch fetch(). We cannot rely on Accept alone since some
193
- // browsers may send Accept: text/html for non-HTML requests.
194
- const isRscRequest =
195
- isPartial ||
196
- (!request.headers.get("accept")?.includes("text/html") &&
197
- !url.searchParams.has("__html")) ||
198
- url.searchParams.has("__rsc");
199
-
200
- if (isRscRequest) {
201
- const renderDur = performance.now() - renderStart;
202
- appendMetric(metricsStore, "render:total", renderStart, renderDur);
203
- const rscHeaders: Record<string, string> = {
204
- "content-type": "text/x-component;charset=utf-8",
205
- vary: "accept, X-Rango-State, X-RSC-Router-Client-Path",
206
- };
207
- // Tell the client's prefetch cache to scope this response to its source
208
- // URL (instead of the default source-agnostic wildcard). Intercept
209
- // responses depend on the source page matching an intercept rule, so
210
- // they must not be reused for navigations from other sources.
211
- if (hasInterceptSlots) {
212
- rscHeaders["x-rsc-prefetch-scope"] = "source";
213
- }
214
- // Enable browser HTTP caching for prefetch responses only.
215
- // Requires X-Rango-Prefetch header (sent by Link prefetch fetch),
216
- // non-intercept context (intercept responses depend on source page),
217
- // and a configured cache-control value (false disables caching).
218
- const isPrefetch = request.headers.has("X-Rango-Prefetch");
219
- if (isPrefetch && isPartial && !hasInterceptSlots) {
220
- const cc = ctx.router.prefetchCacheControl;
221
- if (cc) {
222
- rscHeaders["cache-control"] = cc;
223
- }
898
+ const rscHeaders: Record<string, string> = {
899
+ "content-type": "text/x-component;charset=utf-8",
900
+ vary: `accept, X-Rango-State, X-RSC-Router-Client-Path, ${SEGMENT_FRAGMENT_CAPABILITY_HEADER}, ${SEGMENT_FRAGMENT_RECOVERY_HEADER}`,
901
+ // Router identity, so the client can verify pre-decode (before importing
902
+ // chunks) that this content payload belongs to its app and refuse a
903
+ // foreign one (cache/proxy/bug). Control-only reload/redirect responses
904
+ // are deliberately NOT stamped. See browser/response-adapter.ts.
905
+ "X-RSC-Router-Id": ctx.router.id,
906
+ };
907
+ if (pprReplayStatus) {
908
+ rscHeaders[PPR_REPLAY_STATUS_HEADER] =
909
+ serializePprReplayStatus(pprReplayStatus);
910
+ }
911
+ // Tell the client's prefetch cache to scope this response to its source
912
+ // URL (instead of the default source-agnostic wildcard). Intercept
913
+ // responses depend on the source page matching an intercept rule, so
914
+ // they must not be reused for navigations from other sources.
915
+ if (hasInterceptSlots) {
916
+ rscHeaders["x-rsc-prefetch-scope"] = "source";
917
+ }
918
+ // Enable browser HTTP caching for prefetch responses only.
919
+ // Requires X-Rango-Prefetch header (sent by Link prefetch fetch),
920
+ // non-intercept context (intercept responses depend on source page),
921
+ // and a configured cache-control value (false disables caching).
922
+ const isPrefetch = request.headers.has("X-Rango-Prefetch");
923
+ if (isPrefetch && isPartial && !hasInterceptSlots) {
924
+ const cc = ctx.router.prefetchCacheControl;
925
+ if (cc) {
926
+ rscHeaders["cache-control"] = cc;
224
927
  }
225
- return createResponseWithMergedHeaders(rscStream, {
226
- headers: rscHeaders,
227
- });
228
928
  }
229
929
 
230
- // Delegate to SSR for HTML response (reuse early setup if available)
231
- const [ssrModule, streamMode] = await getSSRSetup(
930
+ const isFlightResponse = isRscRequest(request, url, isPartial);
931
+ const stageTracking = {
932
+ mode: isPartial ? ("partial" as const) : ("full" as const),
933
+ routeKey: reqCtx._routeName,
934
+ span: renderSpan,
935
+ onEvent:
936
+ reqCtx._activeRoutine &&
937
+ createRenderStageTraceBridge(reqCtx._activeRoutine),
938
+ };
939
+ return renderRscResponse(
940
+ {
941
+ ctx,
942
+ request,
943
+ env,
944
+ url,
945
+ payload,
946
+ init: { headers: rscHeaders },
947
+ tracking: stageTracking,
948
+ },
949
+ isFlightResponse
950
+ ? undefined
951
+ : {
952
+ html: createSsrHtmlStage({
953
+ ctx,
954
+ request,
955
+ env,
956
+ url,
957
+ metricsStore,
958
+ render: { nonce },
959
+ init: { headers: { "content-type": "text/html;charset=utf-8" } },
960
+ }),
961
+ },
962
+ );
963
+ }
964
+
965
+ /**
966
+ * Background capture for a navigation-only shell (partial replay reported
967
+ * captureNeeded). SSR setup is resolved lazily inside the capture because the
968
+ * partial request itself never touched HTML rendering.
969
+ */
970
+ function scheduleNavigationShellCapture<TEnv>(
971
+ input: RequestRenderInput<TEnv>,
972
+ partialCaptureKey: string | undefined,
973
+ ): void {
974
+ const { ctx, request, env, url, reqCtx } = input;
975
+ const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry)!;
976
+ const store = reqCtx._cacheStore!;
977
+ scheduleShellCapture(
232
978
  ctx,
233
979
  request,
234
980
  env,
235
981
  url,
236
- metricsStore,
982
+ reqCtx,
983
+ async (captureRequest, captureUrl) => {
984
+ const [ssrModule, streamMode] = await getSSRSetup(
985
+ ctx,
986
+ captureRequest,
987
+ env,
988
+ captureUrl,
989
+ undefined,
990
+ );
991
+ return streamMode === "allReady" ? null : ssrModule;
992
+ },
993
+ createShellCaptureDescriptor(
994
+ ctx,
995
+ partialCaptureKey ??
996
+ buildNavigationShellKey(url, reqCtx._searchParamsFilter),
997
+ pprConfig,
998
+ store,
999
+ true,
1000
+ ),
237
1001
  );
1002
+ }
238
1003
 
239
- const ssrRenderStart = performance.now();
240
- const htmlStream = await ssrModule.renderHTML(rscStream, {
241
- nonce,
242
- streamMode,
1004
+ /**
1005
+ * Reuse a PPR capture's canonical segment record for a partial navigation.
1006
+ * The ordinary matchPartial pipeline remains authoritative: it projects the
1007
+ * cached target tree against the client's segment ids, evaluates revalidation,
1008
+ * and resolves every loader fresh. Only segment-family records are seeded;
1009
+ * captured item/response/loader values belong to document parity and must not
1010
+ * pin navigation data.
1011
+ */
1012
+ async function matchPartialWithPprReplay<TEnv>(
1013
+ ctx: HandlerContext<TEnv>,
1014
+ request: Request,
1015
+ env: TEnv,
1016
+ url: URL,
1017
+ reqCtx: RequestContext<any>,
1018
+ nonce: string | undefined,
1019
+ ) {
1020
+ const replayStart = reqCtx._metricsStore ? performance.now() : 0;
1021
+ const recordReplayStatus = (status: PprReplayStatus): void => {
1022
+ if (!reqCtx._metricsStore) return;
1023
+ appendMetric(
1024
+ reqCtx._metricsStore,
1025
+ "ppr:navigation-replay",
1026
+ replayStart,
1027
+ performance.now() - replayStart,
1028
+ undefined,
1029
+ describePprReplayStatus(status),
1030
+ );
1031
+ };
1032
+ const finalizeReplayStatus = (status: PprReplayStatus): PprReplayStatus => {
1033
+ const finalStatus = reclassifyReplayStatus(reqCtx, status);
1034
+ recordReplayStatus(finalStatus);
1035
+ return finalStatus;
1036
+ };
1037
+ let armFragments = false;
1038
+ /**
1039
+ * Every matchPartial in this function runs through this helper so the
1040
+ * fragment flag (#700 passthrough, armed below the navigation-context gate)
1041
+ * can never outlive a match or miss a lane — a thrown-Response redirect
1042
+ * exit included. Mutate-restore on the SHARED reqCtx, never a derived
1043
+ * context: the pipeline writes ambient state during the match that must
1044
+ * land on reqCtx (_pprReplayPostMatchReason, location state,
1045
+ * _treeHasStreaming read by the render-barrier closure). Assign-back
1046
+ * restore leaves an own `undefined` after the first arm, matching the
1047
+ * _shellImplicitCache idiom.
1048
+ */
1049
+ const matchPartialForReplay = async () => {
1050
+ if (!armFragments) return ctx.router.matchPartial(request, { env });
1051
+ const prevFragmentPayload = reqCtx._shellFragmentPayload;
1052
+ reqCtx._shellFragmentPayload = true;
1053
+ try {
1054
+ return await ctx.router.matchPartial(request, { env });
1055
+ } finally {
1056
+ reqCtx._shellFragmentPayload = prevFragmentPayload;
1057
+ }
1058
+ };
1059
+ const runMatch = async (status?: PprReplayStatus) => {
1060
+ const result = await matchPartialForReplay();
1061
+ // The match may have settled a fact the pre-match gate could only guess
1062
+ // at (prerender serve, intercept resolution) — report the truth.
1063
+ const finalStatus = status ? finalizeReplayStatus(status) : undefined;
1064
+ return { result, status: finalStatus };
1065
+ };
1066
+ const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry);
1067
+ const activeNonce = nonce ?? contextGet(reqCtx._variables, nonceToken);
1068
+ const store = reqCtx._cacheStore;
1069
+
1070
+ if (!pprConfig) return runMatch();
1071
+ if (request.method !== "GET") {
1072
+ return runMatch({ outcome: "BYPASS", reason: "method" });
1073
+ }
1074
+ if (reqCtx._dynamic) {
1075
+ return runMatch({ outcome: "BYPASS", reason: "dynamic" });
1076
+ }
1077
+ if (activeNonce !== undefined) {
1078
+ return runMatch({ outcome: "BYPASS", reason: "nonce" });
1079
+ }
1080
+ if (!hasShellFamily(store)) {
1081
+ return runMatch({ outcome: "BYPASS", reason: "store-unavailable" });
1082
+ }
1083
+ if (store.supportsPassiveShellReads !== true) {
1084
+ return runMatch({
1085
+ outcome: "BYPASS",
1086
+ reason: "passive-read-unsupported",
1087
+ });
1088
+ }
1089
+ // A partial without navigation context (curl probes, synthetic monitors)
1090
+ // can never produce a partial match — createMatchContextForPartial returns
1091
+ // null and the seeded record could not have been consulted, which used to
1092
+ // read as a misleading `snapshot-miss` AFTER two wasted getShell reads.
1093
+ // Same predicate as resolveNavigation, decided before any store I/O.
1094
+ if (!getNavigationContextHeader(request)) {
1095
+ return runMatch({ outcome: "BYPASS", reason: "no-navigation-context" });
1096
+ }
1097
+ // Fragment passthrough (#700), extended to partial replay. Navigation
1098
+ // context proves the request can be matched; the separate capability header
1099
+ // proves its payload consumer can expand envelopes. Older clients and the
1100
+ // one-shot corruption recovery request still replay the same segment record,
1101
+ // but through the server decode path.
1102
+ armFragments =
1103
+ request.headers.get(SEGMENT_FRAGMENT_RECOVERY_HEADER) !== "1" &&
1104
+ request.headers.get(SEGMENT_FRAGMENT_CAPABILITY_HEADER) === "1";
1105
+ // The prerender probe and the cache-opt-out gate below both need the
1106
+ // classified snapshot; resolve (and persist) it once.
1107
+ const routeSnapshot = classifiedRouteSnapshot(reqCtx);
1108
+ // Prerender routes short-circuit in withCacheLookup and serve the partial
1109
+ // from build-time segments — a better-than-HIT outcome. Their captures
1110
+ // record no doc segment record (withCacheStore skips on the prerender hit),
1111
+ // so seeding could never succeed; skip the reads and report the store that
1112
+ // actually serves instead of blaming a "broken" capture. Bypass ONLY when
1113
+ // the baked artifact actually exists — the trie's pr flag alone is not a
1114
+ // serve guarantee: a Passthrough(Prerender()) route with an unbaked or
1115
+ // ctx.passthrough()-skipped param misses the store and renders live, and
1116
+ // replay (including its heal capture) must stay available for it. The
1117
+ // probe goes through the same memoized store the middleware serves from.
1118
+ // Shared predicate with the middleware (it declines on dev HMR — such
1119
+ // partials fall through to the ordinary replay decision here too).
1120
+ //
1121
+ // The probe is a PRE-match fast path, not the truth: it reads only the
1122
+ // non-intercept artifact, and whether the navigation IS an intercept (and
1123
+ // therefore whether tryPrerenderLookup reads `paramHash` or
1124
+ // `paramHash + "/i"`) is resolved during the match by match-api's
1125
+ // findInterceptForRoute — an intercept-source header proves nothing in
1126
+ // either direction. runMatch reclassifies every BYPASS from the stamped
1127
+ // post-match facts (reclassifyReplayStatus), so a wrong guess here can
1128
+ // skip the two getShell reads but never mis-report or mis-heal.
1129
+ if (
1130
+ prerenderStoreShortCircuits(routeSnapshot?.matched?.pr, request) &&
1131
+ (await prerenderEntryExists(
1132
+ routeSnapshot?.matched?.routeKey,
1133
+ routeSnapshot?.params ?? {},
1134
+ url.pathname,
1135
+ routeSnapshot?.entries ?? [],
1136
+ ))
1137
+ ) {
1138
+ return runMatch({ outcome: "BYPASS", reason: "prerender-store" });
1139
+ }
1140
+ // Consumer cache opt-outs are absolute: a STATICALLY disabled scope
1141
+ // (cache(false)) bypasses before any shell read — no heal capture (its
1142
+ // snapshot would be equally unusable). A `condition()` predicate is
1143
+ // request-time state and must NOT be pre-decided here: evaluating it at the
1144
+ // gate and again at the lookup lets a false-then-true flap report
1145
+ // cache-disabled while the explicit tier serves. The lookup's own
1146
+ // evaluation governs (withCacheLookup fires the marker's onExplicitBypass,
1147
+ // reported as cache-disabled post-match).
1148
+ const routeCacheScope = routeSnapshot?.cacheScope ?? null;
1149
+ if (routeCacheScope && !routeCacheScope.enabled) {
1150
+ return runMatch({ outcome: "BYPASS", reason: "cache-disabled" });
1151
+ }
1152
+
1153
+ const key = buildShellKey(url, reqCtx._searchParamsFilter);
1154
+ const navigationKey = `${key}:navigation`;
1155
+ let cached: Awaited<ReturnType<typeof store.getShell>> = null;
1156
+ try {
1157
+ cached = await store.getShell(key, { claimRevalidation: false });
1158
+ } catch (error) {
1159
+ reportCacheError(error, "cache-read", "[NavigationPPR] getShell");
1160
+ return runMatch({ outcome: "BYPASS", reason: "read-error" });
1161
+ }
1162
+
1163
+ let bypassReason: PprReplayBypassReason | undefined;
1164
+ let snapshot: ShellSnapshotRecord[] | undefined;
1165
+ let snapshotStoreKey: string | undefined;
1166
+ let freshness: "fresh" | "stale" = "fresh";
1167
+ if (cached) {
1168
+ const decision = replayableShellSnapshot(cached.entry, ctx.version);
1169
+ if ("snapshot" in decision) {
1170
+ snapshot = decision.snapshot;
1171
+ snapshotStoreKey = key;
1172
+ freshness = cached.shouldRevalidate ? "stale" : "fresh";
1173
+ } else {
1174
+ bypassReason = decision.reason;
1175
+ }
1176
+ }
1177
+
1178
+ if (
1179
+ !snapshot &&
1180
+ bypassReason !== "handler-live-holes" &&
1181
+ bypassReason !== "transition-when"
1182
+ ) {
1183
+ let navigationCached: Awaited<ReturnType<typeof store.getShell>> = null;
1184
+ try {
1185
+ navigationCached = await store.getShell(navigationKey, {
1186
+ claimRevalidation: false,
1187
+ });
1188
+ } catch (error) {
1189
+ reportCacheError(error, "cache-read", "[NavigationPPR] getShell");
1190
+ return runMatch({ outcome: "BYPASS", reason: "read-error" });
1191
+ }
1192
+ if (navigationCached) {
1193
+ const decision = replayableShellSnapshot(
1194
+ navigationCached.entry,
1195
+ ctx.version,
1196
+ );
1197
+ if ("snapshot" in decision) {
1198
+ snapshot = decision.snapshot;
1199
+ snapshotStoreKey = navigationKey;
1200
+ freshness = navigationCached.shouldRevalidate ? "stale" : "fresh";
1201
+ } else {
1202
+ bypassReason = decision.reason;
1203
+ }
1204
+ }
1205
+ }
1206
+
1207
+ if (!snapshot) {
1208
+ // Production build manifests are local module data. In dev, resolving a
1209
+ // missing build shell would foreground-fetch /__rsc_shell and block an
1210
+ // otherwise ordinary navigation on capture, so replay remains runtime-only.
1211
+ const buildHit = await lookupBuildShell(
1212
+ url,
1213
+ ctx.version,
1214
+ store,
1215
+ undefined,
1216
+ reqCtx._searchParamsFilter,
1217
+ );
1218
+ if (buildHit?.stale) {
1219
+ bypassReason ??= "stale-build-entry";
1220
+ } else if (buildHit) {
1221
+ const buildDecision = replayableShellSnapshot(
1222
+ buildHit.entry,
1223
+ ctx.version,
1224
+ );
1225
+ if ("snapshot" in buildDecision) {
1226
+ snapshot = buildDecision.snapshot;
1227
+ } else {
1228
+ bypassReason ??= buildDecision.reason;
1229
+ }
1230
+ }
1231
+ }
1232
+
1233
+ if (!snapshot) {
1234
+ // Report-only marker for routes with an ENABLED route-derived scope: the
1235
+ // lookup's own outcome must stay reportable even without a replayable
1236
+ // snapshot. An always-false condition() route never produces a doc
1237
+ // record (the consumer's write refusal is absolute — see
1238
+ // recordShellCaptureDocRecord), so without this its lookup-time refusal
1239
+ // would be misreported as the eligibility reason and heal captures would
1240
+ // be scheduled for snapshots that can never become consumable. The
1241
+ // marker carries NO store: the seeded fallback in withCacheLookup
1242
+ // requires one, so nothing can be served through it — it only reports.
1243
+ // Bare routes never see it (an installed marker would otherwise mint an
1244
+ // implicit scope over the REAL doc: partition in
1245
+ // resolveShellImplicitCacheScope).
1246
+ if (routeCacheScope?.enabled) {
1247
+ let explicitCacheHit = false;
1248
+ let explicitCacheBypass = false;
1249
+ const previousImplicitCache = reqCtx._shellImplicitCache;
1250
+ reqCtx._shellImplicitCache = {
1251
+ onExplicitHit: () => {
1252
+ explicitCacheHit = true;
1253
+ },
1254
+ onExplicitBypass: () => {
1255
+ explicitCacheBypass = true;
1256
+ },
1257
+ };
1258
+ try {
1259
+ const result = await matchPartialForReplay();
1260
+ const provisionalStatus: PprReplayStatus = explicitCacheBypass
1261
+ ? { outcome: "BYPASS", reason: "cache-disabled" }
1262
+ : explicitCacheHit
1263
+ ? { outcome: "BYPASS", reason: "explicit-cache-hit" }
1264
+ : { outcome: "BYPASS", reason: bypassReason ?? "no-entry" };
1265
+ const status = finalizeReplayStatus(provisionalStatus);
1266
+ return {
1267
+ result,
1268
+ status,
1269
+ // A lookup-time opt-out makes every heal snapshot unusable
1270
+ // (recordShellCaptureDocRecord refuses under the same predicate),
1271
+ // and a prerender-served or intercept match never consults a heal
1272
+ // snapshot at all. Otherwise heal the shouldHealReplayMiss set PLUS
1273
+ // `no-segment-snapshot`: an entry captured while condition() was
1274
+ // false legitimately lacks a snapshot, and a later request whose
1275
+ // lookup did NOT refuse (condition true now) can heal it — the
1276
+ // capture derives from THIS request's context, so its doc record
1277
+ // records. Excluding it left replay dead until the document
1278
+ // recaptured. The always-false route stays protected: its every
1279
+ // lookup refuses, so explicitCacheBypass suppresses the heal.
1280
+ captureNeeded:
1281
+ !explicitCacheBypass &&
1282
+ reqCtx._pprReplayPostMatchReason === undefined &&
1283
+ (shouldHealReplayMiss(bypassReason) ||
1284
+ bypassReason === "no-segment-snapshot"),
1285
+ };
1286
+ } finally {
1287
+ reqCtx._shellImplicitCache = previousImplicitCache;
1288
+ }
1289
+ }
1290
+ const match = await runMatch({
1291
+ outcome: "BYPASS",
1292
+ reason: bypassReason ?? "no-entry",
1293
+ });
1294
+ return {
1295
+ ...match,
1296
+ captureNeeded:
1297
+ reqCtx._pprReplayPostMatchReason === undefined &&
1298
+ shouldHealReplayMiss(bypassReason),
1299
+ };
1300
+ }
1301
+
1302
+ const previousImplicitCache = reqCtx._shellImplicitCache;
1303
+ let segmentReplayHit = false;
1304
+ let segmentReplayCorrupt = false;
1305
+ let explicitCacheHit = false;
1306
+ let explicitCacheBypass = false;
1307
+ reqCtx._shellImplicitCache = {
1308
+ ttl: pprConfig.ttl,
1309
+ swr: pprConfig.swr,
1310
+ store: new SeededShellStore(store, snapshot, {
1311
+ segmentsOnly: true,
1312
+ }),
1313
+ keyPrefix: "doc",
1314
+ onHit: () => {
1315
+ segmentReplayHit = true;
1316
+ },
1317
+ onCorrupt: () => {
1318
+ segmentReplayCorrupt = true;
1319
+ },
1320
+ // Arms the explicit-scope composition in withCacheLookup: a route-derived
1321
+ // cache() scope stays authoritative, the seeded doc record supplies the
1322
+ // match only on its miss. An explicit-tier hit must NOT report a replay
1323
+ // HIT — it served under the consumer's own semantics.
1324
+ onExplicitHit: () => {
1325
+ explicitCacheHit = true;
1326
+ },
1327
+ // Lookup-time condition() refusal (or a scope with no store): the gate
1328
+ // deliberately does not pre-decide predicates, so the truthful
1329
+ // cache-disabled report comes from the lookup that actually refused.
1330
+ onExplicitBypass: () => {
1331
+ explicitCacheBypass = true;
1332
+ },
1333
+ };
1334
+
1335
+ try {
1336
+ const result = await matchPartialForReplay();
1337
+ const provisionalStatus: PprReplayStatus = segmentReplayHit
1338
+ ? { outcome: "HIT", freshness }
1339
+ : explicitCacheHit
1340
+ ? { outcome: "BYPASS", reason: "explicit-cache-hit" }
1341
+ : explicitCacheBypass
1342
+ ? { outcome: "BYPASS", reason: "cache-disabled" }
1343
+ : { outcome: "BYPASS", reason: "snapshot-miss" };
1344
+ // A prerender serve or intercept resolution leaves the seeded record
1345
+ // unconsulted (prerender short-circuits before the scope; intercepts
1346
+ // keep snapshot.cacheScope) — the "snapshot-miss" guess would blame the
1347
+ // capture for a lane that was never in play.
1348
+ const status = finalizeReplayStatus(provisionalStatus);
1349
+ return {
1350
+ result,
1351
+ status,
1352
+ captureNeeded:
1353
+ segmentReplayCorrupt && reqCtx._pprReplayPostMatchReason === undefined,
1354
+ // A corrupt document snapshot must be overwritten at the document key;
1355
+ // writing only the secondary navigation key would leave the preferred
1356
+ // document entry shadowing the repair forever. The capture remains marked
1357
+ // navigationOnly, so a document request ignores it and recaptures a
1358
+ // document-safe shell under the same key.
1359
+ captureKey: segmentReplayCorrupt ? snapshotStoreKey : undefined,
1360
+ };
1361
+ } finally {
1362
+ reqCtx._shellImplicitCache = previousImplicitCache;
1363
+ }
1364
+ }
1365
+
1366
+ /**
1367
+ * The full route snapshot for the classified route, or null when
1368
+ * classification is unavailable (the gates then fall open to the ordinary
1369
+ * replay decision). Persists the enriched snapshot back onto
1370
+ * `_classifiedRoute` so the manifest-chain walk runs once per request:
1371
+ * matchPartial's createMatchContextForPartial re-reads `_classifiedRoute` and
1372
+ * calls ensureFullRouteSnapshot again, and the write-back lets that call hit
1373
+ * the entries-already-built fast path and reuse this same scope chain instead
1374
+ * of rebuilding it.
1375
+ */
1376
+ function classifiedRouteSnapshot(
1377
+ reqCtx: RequestContext<any>,
1378
+ ): RouteSnapshot<any> | null {
1379
+ const classified = reqCtx._classifiedRoute;
1380
+ if (!classified?.manifestEntry) return null;
1381
+ const full = ensureFullRouteSnapshot({
1382
+ ...classified,
1383
+ entries: classified.entries ?? [],
243
1384
  });
244
- const ssrRenderDur = performance.now() - ssrRenderStart;
245
- appendMetric(metricsStore, "ssr-render-html", ssrRenderStart, ssrRenderDur);
1385
+ reqCtx._classifiedRoute = full;
1386
+ return full;
1387
+ }
246
1388
 
247
- const renderDur = performance.now() - renderStart;
248
- appendMetric(metricsStore, "render:total", renderStart, renderDur);
1389
+ /**
1390
+ * Neutralize the shell-HIT degradation redirect target. The inline
1391
+ * `location.replace` in a committed 200 body bypasses the 3xx chokepoint
1392
+ * (guardOutgoingRedirect only sees 3xx + Location), so this reuses the same
1393
+ * same-origin resolver directly: unsafe targets neutralize to the
1394
+ * redirect-guard.ts landing instead of navigating the user off-host.
1395
+ */
1396
+ export function resolveShellHitRedirectTarget(
1397
+ rawTarget: string,
1398
+ requestOrigin: string,
1399
+ basename: string | undefined,
1400
+ ): string {
1401
+ return (
1402
+ resolveSameOriginRedirect(rawTarget, requestOrigin) ??
1403
+ safeSameOriginLanding(basename)
1404
+ );
1405
+ }
1406
+
1407
+ /**
1408
+ * Serve a validated shell HIT: commit the stored prelude bytes NOW and run the
1409
+ * live tail behind them inside the response stream. Plain byte concatenation is
1410
+ * correct — React foster-parents content streamed after the prelude's closing
1411
+ * `</body></html>`. After the flush a failing hole cannot become a 500/redirect
1412
+ * (error UI renders inline — the documented PPR constraint). The tail promise
1413
+ * is kicked off SYNCHRONOUSLY so it runs inside the current ALS request-context
1414
+ * frame; the adapter may pull the stream outside it.
1415
+ */
1416
+ function serveShellHit(
1417
+ ctx: HandlerContext<any>,
1418
+ request: Request,
1419
+ env: any,
1420
+ url: URL,
1421
+ reqCtx: RequestContext<any>,
1422
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
1423
+ ssrModule: SSRModule,
1424
+ entry: DocumentShellCacheEntry,
1425
+ descriptor: ShellCaptureDescriptor,
1426
+ ): Response {
1427
+ const preludeBytes = base64ToBytes(entry.prelude);
1428
+ // Per-stage tail timing for the dev `ppr:tail` Server-Timing mirror. Dev
1429
+ // only (NODE_ENV folds the branch away in production builds); offsets are
1430
+ // relative to this commit point.
1431
+ const tailTiming: ShellTailTiming | null =
1432
+ process.env.NODE_ENV !== "production"
1433
+ ? {
1434
+ key: descriptor.key,
1435
+ outcome: "complete",
1436
+ preludeBytes: preludeBytes.length,
1437
+ }
1438
+ : null;
1439
+ const tailT0 = tailTiming ? performance.now() : 0;
1440
+
1441
+ const createTailContext = (): RequestContext<any> => {
1442
+ const tailCtx: RequestContext<any> = Object.create(reqCtx);
1443
+ // Matching writes render state onto the derived context. Its barrier must
1444
+ // close over that same context or a streaming tail inherits the base
1445
+ // context's premature non-streaming handle snapshot.
1446
+ wireRenderBarrier(tailCtx, handleStore);
1447
+ return tailCtx;
1448
+ };
1449
+
1450
+ const renderTail = async (
1451
+ activeCtx: RequestContext<any>,
1452
+ ): Promise<ReadableStream<Uint8Array> | { redirect: string }> => {
1453
+ const matchStart = INTERNAL_RANGO_DEBUG ? performance.now() : 0;
1454
+ const match = await ctx.router.match(request, { env });
1455
+ if (tailTiming) {
1456
+ tailTiming.matchMs = Math.round(performance.now() - tailT0);
1457
+ }
1458
+ if (INTERNAL_RANGO_DEBUG) {
1459
+ console.log(
1460
+ `[Server][ppr] shell HIT: tail match done +${Math.round(performance.now() - matchStart)}ms (abs ${Math.round(performance.now())}, started ${Math.round(matchStart)})`,
1461
+ );
1462
+ }
1463
+ if (match.redirect) return { redirect: match.redirect };
1464
+ setRequestContextParams(match.params, match.routeName);
1465
+ const payload = buildFullPayload(match, ctx, url, activeCtx, handleStore);
1466
+ // Theme fidelity for resume: replay the CAPTURE's initialTheme into the
1467
+ // payload so the resume/hydration trees match the frozen prelude by
1468
+ // construction. The visitor still sees THEIR theme — the prelude's FOUC
1469
+ // script applies the cookie pre-paint and ThemeProvider re-syncs post-mount.
1470
+ if (payload.metadata) {
1471
+ payload.metadata.initialTheme = entry.initialTheme as
1472
+ | import("../theme/types.js").Theme
1473
+ | undefined;
1474
+ }
1475
+ // Full Flight render per request: hydration needs the whole payload (there
1476
+ // is no Flight-side resume — a React limitation, not ours).
1477
+ const flightStage = renderRscFlightStage({
1478
+ ctx,
1479
+ request,
1480
+ env,
1481
+ url,
1482
+ payload,
1483
+ tracking: {
1484
+ mode: "full",
1485
+ routeKey: activeCtx._routeName,
1486
+ },
1487
+ });
1488
+ let rscStream = flightStage.stream;
1489
+ // Timing tap: when does the Flight render produce its FIRST byte? Compared
1490
+ // with the eager-inject/first-tail logs this proves whether hydration-start
1491
+ // latency is genuine server work (loaders) or stream plumbing holding
1492
+ // ready bytes back.
1493
+ if (INTERNAL_RANGO_DEBUG) {
1494
+ const tapStart = performance.now();
1495
+ let first = false;
1496
+ rscStream = rscStream.pipeThrough(
1497
+ new TransformStream({
1498
+ transform(chunk, controller) {
1499
+ if (!first) {
1500
+ first = true;
1501
+ console.log(
1502
+ `[Server][ppr] flight render: first chunk +${Math.round(performance.now() - tapStart)}ms (abs ${Math.round(performance.now())})`,
1503
+ );
1504
+ }
1505
+ controller.enqueue(chunk);
1506
+ },
1507
+ }),
1508
+ );
1509
+ }
1510
+ return observePhase(PHASES.ssr, () =>
1511
+ ssrModule.resumeShellHTML!(rscStream, {
1512
+ postponed: entry.postponed,
1513
+ nonce: undefined,
1514
+ }),
1515
+ );
1516
+ };
1517
+
1518
+ const tailPromise: Promise<
1519
+ ReadableStream<Uint8Array> | { redirect: string }
1520
+ > = (async () => {
1521
+ // Snapshot seeding (docs/design/ppr-shell-resume.md): the tail render must
1522
+ // match the frozen prelude, so pinned cache reads replay their capture-time
1523
+ // values via a SeededShellStore overlay while unpinned reads (the holes)
1524
+ // stay live. The overlay lives on a DERIVED context so the shared reqCtx is
1525
+ // untouched.
1526
+ if (entry.snapshot && entry.snapshot.length > 0) {
1527
+ const seededCtx = createTailContext();
1528
+ if (reqCtx._cacheStore) {
1529
+ seededCtx._cacheStore = new SeededShellStore(
1530
+ reqCtx._cacheStore,
1531
+ entry.snapshot,
1532
+ );
1533
+ }
1534
+ // Loader-family records (bake-lane containers, loader-container-bake):
1535
+ // decode into a seed Map for the resolveLoaderData overlay, so the
1536
+ // payload's baked container bytes match the frozen prelude while the
1537
+ // hole-marker paths keep the fresh run's live nested promises.
1538
+ const seedStart = INTERNAL_RANGO_DEBUG ? performance.now() : 0;
1539
+ const loaderSeed = await buildShellLoaderSeed(entry.snapshot);
1540
+ if (tailTiming) {
1541
+ tailTiming.seedMs = Math.round(performance.now() - tailT0);
1542
+ }
1543
+ if (INTERNAL_RANGO_DEBUG) {
1544
+ console.log(
1545
+ `[Server][ppr] shell HIT: loader seed built +${Math.round(performance.now() - seedStart)}ms (abs ${Math.round(performance.now())})`,
1546
+ );
1547
+ }
1548
+ if (loaderSeed) seededCtx._shellLoaderSeed = loaderSeed;
1549
+ // Shell fast path (serve side): if the capture recorded the implicit doc
1550
+ // segment record and the handler layer declared no liveness, the tail's
1551
+ // cache lookup HITs the seeded doc entry — the handler layer is REPLAYED,
1552
+ // not re-executed (loaders still run fresh). Anything else degrades to
1553
+ // the full tail automatically.
1554
+ if (!entry.handlerLiveHoles && !entry.transitionWhen) {
1555
+ seededCtx._shellImplicitCache = {
1556
+ ttl: descriptor.ttl,
1557
+ swr: descriptor.swr,
1558
+ keyPrefix: "doc",
1559
+ };
1560
+ if (INTERNAL_RANGO_DEBUG) {
1561
+ console.log(
1562
+ `[Server][ppr] shell HIT: fast path armed (implicit doc cache) (abs ${Math.round(performance.now())})`,
1563
+ );
1564
+ }
1565
+ } else if (INTERNAL_RANGO_DEBUG) {
1566
+ console.log(
1567
+ `[Server][ppr] shell HIT: fast path declined — request-dependent handler/transition state; tail re-runs handlers (abs ${Math.round(performance.now())})`,
1568
+ );
1569
+ }
1570
+ // Fragment splice (issue #700): store hits in THIS tail emit their stored
1571
+ // segment fragments verbatim (expanded by segment-fragments.ts). The flag
1572
+ // lives on the derived context so it can never leak into a capture render,
1573
+ // which serializes segments and must see real elements.
1574
+ seededCtx._shellFragmentPayload = true;
1575
+ return runWithRequestContext(seededCtx, () => renderTail(seededCtx));
1576
+ }
1577
+ // No snapshot (e.g. a producer B entry): still a shell-HIT tail, so arm the
1578
+ // fragment splice on a derived context — never the shared reqCtx, from which
1579
+ // scheduleShellCapture derives the capture context (the flag must not be
1580
+ // inherited there).
1581
+ const fragmentCtx = createTailContext();
1582
+ fragmentCtx._shellFragmentPayload = true;
1583
+ return runWithRequestContext(fragmentCtx, () => renderTail(fragmentCtx));
1584
+ })();
1585
+ // The stream below is the only consumer; pre-attach a no-op catch so a tail
1586
+ // failure before the stream is pulled never surfaces as an unhandled rejection.
1587
+ tailPromise.catch(() => {});
249
1588
 
250
- return createResponseWithMergedHeaders(htmlStream, {
251
- headers: { "content-type": "text/html;charset=utf-8" },
1589
+ const serveStart = INTERNAL_RANGO_DEBUG ? performance.now() : 0;
1590
+ const body = new ReadableStream<Uint8Array>({
1591
+ async start(controller) {
1592
+ controller.enqueue(preludeBytes);
1593
+ if (INTERNAL_RANGO_DEBUG) {
1594
+ console.log(
1595
+ `[Server][ppr] shell HIT: prelude enqueued (${preludeBytes.length}b) +${Math.round(performance.now() - serveStart)}ms`,
1596
+ );
1597
+ }
1598
+ try {
1599
+ const tail = await tailPromise;
1600
+ if (tailTiming) {
1601
+ tailTiming.handoverMs = Math.round(performance.now() - tailT0);
1602
+ }
1603
+ if (INTERNAL_RANGO_DEBUG) {
1604
+ console.log(
1605
+ `[Server][ppr] shell HIT: tail stream handed over +${Math.round(performance.now() - serveStart)}ms (abs ${Math.round(performance.now())})`,
1606
+ );
1607
+ }
1608
+ if (tail instanceof ReadableStream) {
1609
+ const reader = tail.getReader();
1610
+ let firstTailChunk = true;
1611
+ let tailBytes = 0;
1612
+ try {
1613
+ for (;;) {
1614
+ const { done, value } = await reader.read();
1615
+ if (done) break;
1616
+ if (firstTailChunk) {
1617
+ firstTailChunk = false;
1618
+ if (tailTiming) {
1619
+ tailTiming.firstHtmlMs = Math.round(
1620
+ performance.now() - tailT0,
1621
+ );
1622
+ }
1623
+ if (INTERNAL_RANGO_DEBUG) {
1624
+ console.log(
1625
+ `[Server][ppr] shell HIT: first tail chunk on the wire +${Math.round(performance.now() - serveStart)}ms (abs ${Math.round(performance.now())})`,
1626
+ );
1627
+ }
1628
+ }
1629
+ if (tailTiming || INTERNAL_RANGO_DEBUG) {
1630
+ tailBytes += value.length;
1631
+ }
1632
+ controller.enqueue(value);
1633
+ }
1634
+ } finally {
1635
+ reader.releaseLock();
1636
+ }
1637
+ if (tailTiming) {
1638
+ tailTiming.completeMs = Math.round(performance.now() - tailT0);
1639
+ tailTiming.tailBytes = tailBytes;
1640
+ }
1641
+ // Bounds the post-header work Server-Timing structurally cannot see:
1642
+ // the HIT commits headers at the flush, so ALL live-tail time (match,
1643
+ // loaders, Flight, resume) happens inside the response body. This
1644
+ // line plus the [Server][segments] build logs narrate that window.
1645
+ if (INTERNAL_RANGO_DEBUG) {
1646
+ console.log(
1647
+ `[Server][ppr] shell HIT: tail complete +${Math.round(performance.now() - serveStart)}ms (${tailBytes}b)`,
1648
+ );
1649
+ }
1650
+ } else {
1651
+ // Defensive, near-unreachable: a redirecting match cannot have captured
1652
+ // a shell (capture bails on redirects), so a HIT on a redirecting URL
1653
+ // requires the route to have BECOME redirecting within the shell TTL.
1654
+ // The 200 + prelude are already committed; degrade to a client-side
1655
+ // replace so the user still lands on the target. The target is
1656
+ // neutralized first (see resolveShellHitRedirectTarget).
1657
+ const safeTarget = resolveShellHitRedirectTarget(
1658
+ tail.redirect,
1659
+ url.origin,
1660
+ ctx.router.basename,
1661
+ );
1662
+ controller.enqueue(
1663
+ new TextEncoder().encode(
1664
+ `<script>location.replace(${JSON.stringify(safeTarget)})</script>`,
1665
+ ),
1666
+ );
1667
+ if (tailTiming) {
1668
+ tailTiming.outcome = "redirect";
1669
+ tailTiming.completeMs = Math.round(performance.now() - tailT0);
1670
+ }
1671
+ }
1672
+ if (tailTiming) publishShellTailTiming(tailTiming);
1673
+ controller.close();
1674
+ } catch (error) {
1675
+ // Self-heal on a failed tail: errors the pre-commit gates cannot catch
1676
+ // (mismatched postponed blob, hard render error above the holes) throw
1677
+ // here AFTER the 200 + prelude flushed and would re-fail on every
1678
+ // request until the entry ages out — recapture overwrites the entry.
1679
+ // Client disconnects land here too; the recapture is idempotent and
1680
+ // bounded by scheduleShellCapture's stampede guard + backoff.
1681
+ scheduleShellCapture(
1682
+ ctx,
1683
+ request,
1684
+ env,
1685
+ url,
1686
+ reqCtx,
1687
+ ssrModule,
1688
+ descriptor,
1689
+ );
1690
+ if (tailTiming) {
1691
+ tailTiming.outcome = "error";
1692
+ tailTiming.completeMs = Math.round(performance.now() - tailT0);
1693
+ publishShellTailTiming(tailTiming);
1694
+ }
1695
+ controller.error(error);
1696
+ }
1697
+ },
1698
+ });
1699
+
1700
+ return createResponseWithMergedHeaders(body, {
1701
+ headers: {
1702
+ "content-type": "text/html;charset=utf-8",
1703
+ [SHELL_STATUS_HEADER]: "HIT",
1704
+ },
252
1705
  });
253
1706
  }