@rangojs/router 0.5.1 → 0.6.0

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 (609) hide show
  1. package/README.md +5 -1
  2. package/dist/bin/rango.js +343 -125
  3. package/dist/types/browser/event-controller.d.ts +6 -0
  4. package/dist/types/browser/react/use-router.d.ts +10 -3
  5. package/dist/types/browser/react/use-search-params.d.ts +57 -10
  6. package/dist/types/browser/types.d.ts +22 -0
  7. package/dist/types/build/merge-full-manifests.d.ts +3 -0
  8. package/dist/types/build/route-trie.d.ts +4 -73
  9. package/dist/types/build/route-types/per-module-writer.d.ts +6 -4
  10. package/dist/types/build/route-types/router-processing.d.ts +2 -3
  11. package/dist/types/cache/cache-exec-scope.d.ts +31 -0
  12. package/dist/types/cache/cf/cf-cache-constants.d.ts +8 -1
  13. package/dist/types/cache/cf/cf-cache-store.d.ts +15 -1
  14. package/dist/types/cache/cf/cf-cache-types.d.ts +1 -1
  15. package/dist/types/cache/cf/cf-kv-utils.d.ts +21 -0
  16. package/dist/types/cache/taint.d.ts +12 -6
  17. package/dist/types/client-urls/client-root.d.ts +38 -0
  18. package/dist/types/client-urls/client-urls.d.ts +5 -0
  19. package/dist/types/client-urls/navigation.d.ts +38 -0
  20. package/dist/types/client-urls/revalidation-protocol.d.ts +25 -0
  21. package/dist/types/client-urls/server-projection.d.ts +62 -0
  22. package/dist/types/client-urls/types.d.ts +144 -0
  23. package/dist/types/client.d.ts +12 -4
  24. package/dist/types/client.rsc.d.ts +4 -1
  25. package/dist/types/decode-loader-results.d.ts +37 -0
  26. package/dist/types/errors.d.ts +1 -0
  27. package/dist/types/handles/is-thenable.d.ts +2 -4
  28. package/dist/types/index.d.ts +1 -1
  29. package/dist/types/loader-redirect.d.ts +27 -0
  30. package/dist/types/outlet-context.d.ts +12 -0
  31. package/dist/types/outlet-provider.d.ts +3 -1
  32. package/dist/types/redirect-origin.d.ts +4 -0
  33. package/dist/types/route-content-wrapper.d.ts +42 -1
  34. package/dist/types/route-definition/helpers-types.d.ts +13 -2
  35. package/dist/types/router/error-handling.d.ts +35 -1
  36. package/dist/types/router/intercept-resolution.d.ts +12 -0
  37. package/dist/types/router/loader-resolution.d.ts +24 -2
  38. package/dist/types/router/revalidation.d.ts +7 -0
  39. package/dist/{types.backup/build/route-trie.d.ts → types/router/route-trie-builder.d.ts} +4 -16
  40. package/dist/types/router/router-interfaces.d.ts +20 -0
  41. package/dist/types/router/segment-resolution/helpers.d.ts +1 -1
  42. package/dist/types/router/trie-matching.d.ts +1 -1
  43. package/dist/types/rsc/helpers.d.ts +3 -0
  44. package/dist/types/rsc/manifest-init.d.ts +5 -5
  45. package/dist/types/rsc/render-pipeline.d.ts +9 -0
  46. package/dist/types/rsc/routine-plan.d.ts +124 -0
  47. package/dist/types/rsc/shell-capture-constants.d.ts +17 -0
  48. package/dist/types/rsc/shell-capture.d.ts +9 -0
  49. package/dist/types/rsc/shell-serve.d.ts +11 -0
  50. package/dist/types/rsc/types.d.ts +30 -0
  51. package/dist/types/segment-system.d.ts +2 -0
  52. package/dist/types/server/context.d.ts +10 -0
  53. package/dist/types/server/handle-store.d.ts +34 -3
  54. package/dist/types/server/request-context.d.ts +14 -1
  55. package/dist/types/server.d.ts +1 -0
  56. package/dist/types/ssr/index.d.ts +22 -0
  57. package/dist/types/ssr/ssr-root.d.ts +10 -0
  58. package/dist/types/testing/dom.entry.d.ts +1 -1
  59. package/dist/types/testing/render-route.d.ts +16 -6
  60. package/dist/types/testing/run-loader.d.ts +9 -0
  61. package/dist/types/types/boundaries.d.ts +22 -0
  62. package/dist/types/types/index.d.ts +1 -1
  63. package/dist/types/types/loader-types.d.ts +57 -5
  64. package/dist/types/types/segments.d.ts +7 -0
  65. package/dist/types/urls/path-helper-types.d.ts +10 -4
  66. package/dist/types/vite/discovery/client-urls-projection.d.ts +53 -0
  67. package/dist/types/vite/discovery/discover-routers.d.ts +1 -1
  68. package/dist/types/vite/discovery/state.d.ts +8 -1
  69. package/dist/types/vite/encryption-key.d.ts +2 -0
  70. package/dist/types/vite/plugins/expose-internal-ids.d.ts +10 -0
  71. package/dist/types/vite/plugins/server-ref-hashing.d.ts +24 -0
  72. package/dist/types/vite/plugins/server-reference-pattern.d.ts +1 -0
  73. package/dist/types/vite/utils/shared-utils.d.ts +12 -0
  74. package/dist/vite/index.js +5101 -2056
  75. package/package.json +3 -3
  76. package/skills/breadcrumbs/SKILL.md +39 -9
  77. package/skills/caching/SKILL.md +1 -1
  78. package/skills/catalog.json +7 -1
  79. package/skills/client-urls/SKILL.md +338 -0
  80. package/skills/comparison/references/framework-comparison.md +23 -9
  81. package/skills/hooks/SKILL.md +2 -2
  82. package/skills/hooks/data.md +11 -2
  83. package/skills/hooks/handle-and-actions.md +7 -0
  84. package/skills/hooks/outlets.md +26 -5
  85. package/skills/hooks/urls.md +40 -3
  86. package/skills/loader/SKILL.md +132 -20
  87. package/skills/migrate-nextjs/SKILL.md +70 -10
  88. package/skills/migrate-react-router/SKILL.md +49 -13
  89. package/skills/migrate-react-router/component-migration.md +18 -13
  90. package/skills/migrate-react-router/data-and-actions.md +14 -3
  91. package/skills/migrate-react-router/route-mapping.md +15 -2
  92. package/skills/mime-routes/SKILL.md +3 -1
  93. package/skills/parallel/SKILL.md +32 -1
  94. package/skills/ppr/SKILL.md +16 -6
  95. package/skills/prerender/SKILL.md +8 -4
  96. package/skills/rango/SKILL.md +21 -17
  97. package/skills/react-compiler/SKILL.md +3 -3
  98. package/skills/response-routes/SKILL.md +4 -2
  99. package/skills/route/SKILL.md +5 -2
  100. package/skills/router-setup/SKILL.md +16 -2
  101. package/skills/scripts/SKILL.md +16 -6
  102. package/skills/shell-manifest/SKILL.md +16 -7
  103. package/skills/testing/SKILL.md +2 -2
  104. package/skills/testing/client-components.md +6 -0
  105. package/skills/testing/handles.md +30 -8
  106. package/skills/testing/loader.md +51 -49
  107. package/skills/testing/middleware.md +1 -1
  108. package/skills/theme/SKILL.md +8 -5
  109. package/skills/typesafety/generated-files-and-cli.md +16 -9
  110. package/skills/typesafety/route-types.md +5 -1
  111. package/skills/use-cache/SKILL.md +47 -0
  112. package/src/bin/rango.ts +7 -3
  113. package/src/browser/event-controller.ts +40 -15
  114. package/src/browser/navigation-bridge.ts +6 -0
  115. package/src/browser/navigation-client.ts +5 -0
  116. package/src/browser/partial-update.ts +77 -10
  117. package/src/browser/react/NavigationProvider.tsx +7 -0
  118. package/src/browser/react/use-router.ts +40 -11
  119. package/src/browser/react/use-search-params.ts +140 -17
  120. package/src/browser/rsc-router.tsx +59 -0
  121. package/src/browser/server-action-bridge.ts +26 -0
  122. package/src/browser/types.ts +22 -0
  123. package/src/build/merge-full-manifests.ts +161 -0
  124. package/src/build/route-trie.ts +9 -332
  125. package/src/build/route-types/include-resolution.ts +66 -11
  126. package/src/build/route-types/per-module-writer.ts +11 -6
  127. package/src/build/route-types/router-processing.ts +184 -153
  128. package/src/build/runtime-discovery.ts +23 -12
  129. package/src/cache/cache-exec-scope.ts +47 -0
  130. package/src/cache/cache-runtime.ts +113 -40
  131. package/src/cache/cf/cf-cache-constants.ts +8 -1
  132. package/src/cache/cf/cf-cache-store.ts +41 -64
  133. package/src/cache/cf/cf-cache-types.ts +1 -1
  134. package/src/cache/cf/cf-kv-utils.ts +38 -0
  135. package/src/cache/segment-codec.ts +21 -5
  136. package/src/cache/taint.ts +28 -9
  137. package/src/client-urls/client-root.tsx +168 -0
  138. package/src/client-urls/client-urls.ts +698 -0
  139. package/src/client-urls/navigation.ts +237 -0
  140. package/src/client-urls/revalidation-protocol.ts +56 -0
  141. package/src/client-urls/server-projection.ts +579 -0
  142. package/src/client-urls/types.ts +195 -0
  143. package/src/client.rsc.tsx +12 -0
  144. package/src/client.tsx +49 -6
  145. package/src/decode-loader-results.ts +113 -0
  146. package/src/errors.ts +14 -0
  147. package/src/handles/deferred-resolution.ts +14 -7
  148. package/src/handles/is-thenable.ts +2 -4
  149. package/src/index.ts +1 -0
  150. package/src/loader-redirect.tsx +64 -0
  151. package/src/outlet-context.ts +12 -0
  152. package/src/outlet-provider.tsx +15 -1
  153. package/src/redirect-origin.ts +29 -0
  154. package/src/route-content-wrapper.tsx +96 -3
  155. package/src/route-definition/dsl-helpers.ts +28 -3
  156. package/src/route-definition/helpers-types.ts +13 -0
  157. package/src/route-definition/redirect.ts +17 -18
  158. package/src/router/error-handling.ts +65 -11
  159. package/src/router/intercept-resolution.ts +29 -0
  160. package/src/router/loader-resolution.ts +261 -28
  161. package/src/router/match-middleware/cache-lookup.ts +24 -15
  162. package/src/router/match-result.ts +7 -0
  163. package/src/router/revalidation.ts +24 -11
  164. package/src/router/route-trie-builder.ts +334 -0
  165. package/src/router/router-interfaces.ts +38 -0
  166. package/src/router/segment-resolution/fresh.ts +47 -0
  167. package/src/router/segment-resolution/helpers.ts +9 -11
  168. package/src/router/segment-resolution/loader-cache.ts +14 -24
  169. package/src/router/segment-resolution/revalidation.ts +20 -1
  170. package/src/router/trie-matching.ts +3 -3
  171. package/src/router.ts +46 -1
  172. package/src/rsc/full-payload.ts +6 -0
  173. package/src/rsc/handler.ts +36 -12
  174. package/src/rsc/helpers.ts +13 -0
  175. package/src/rsc/loader-fetch.ts +2 -2
  176. package/src/rsc/manifest-init.ts +28 -9
  177. package/src/rsc/progressive-enhancement.ts +247 -70
  178. package/src/rsc/render-pipeline.ts +68 -24
  179. package/src/rsc/routine-plan.ts +359 -0
  180. package/src/rsc/rsc-rendering.ts +569 -302
  181. package/src/rsc/server-action.ts +180 -71
  182. package/src/rsc/shell-capture-constants.ts +18 -0
  183. package/src/rsc/shell-capture.ts +104 -21
  184. package/src/rsc/shell-serve.ts +15 -2
  185. package/src/rsc/ssr-setup.ts +10 -1
  186. package/src/rsc/types.ts +31 -2
  187. package/src/segment-system.tsx +83 -26
  188. package/src/server/context.ts +10 -0
  189. package/src/server/cookie-store.ts +19 -19
  190. package/src/server/handle-store.ts +185 -48
  191. package/src/server/request-context.ts +36 -6
  192. package/src/server.ts +7 -0
  193. package/src/ssr/index.tsx +37 -2
  194. package/src/ssr/ssr-root.tsx +30 -2
  195. package/src/testing/dom.entry.ts +1 -1
  196. package/src/testing/render-route.tsx +22 -8
  197. package/src/testing/run-loader.ts +51 -13
  198. package/src/types/boundaries.ts +19 -0
  199. package/src/types/index.ts +1 -0
  200. package/src/types/loader-types.ts +60 -5
  201. package/src/types/segments.ts +7 -0
  202. package/src/urls/include-helper.ts +22 -4
  203. package/src/urls/path-helper-types.ts +14 -1
  204. package/src/use-loader.tsx +67 -6
  205. package/src/vite/discovery/client-urls-projection.ts +322 -0
  206. package/src/vite/discovery/discover-routers.ts +43 -17
  207. package/src/vite/discovery/state.ts +11 -1
  208. package/src/vite/discovery/virtual-module-codegen.ts +20 -0
  209. package/src/vite/encryption-key.ts +29 -0
  210. package/src/vite/plugins/expose-action-id.ts +2 -2
  211. package/src/vite/plugins/expose-internal-ids.ts +46 -0
  212. package/src/vite/plugins/server-ref-hashing.ts +74 -0
  213. package/src/vite/plugins/server-reference-pattern.ts +10 -0
  214. package/src/vite/plugins/virtual-entries.ts +12 -3
  215. package/src/vite/rango.ts +9 -0
  216. package/src/vite/router-discovery.ts +184 -14
  217. package/src/vite/utils/shared-utils.ts +12 -7
  218. package/dist/types.backup/__internal.d.ts +0 -127
  219. package/dist/types.backup/bin/rango.d.ts +0 -1
  220. package/dist/types.backup/browser/action-coordinator.d.ts +0 -57
  221. package/dist/types.backup/browser/action-fence.d.ts +0 -33
  222. package/dist/types.backup/browser/app-shell.d.ts +0 -34
  223. package/dist/types.backup/browser/app-version.d.ts +0 -6
  224. package/dist/types.backup/browser/connection-warmup.d.ts +0 -31
  225. package/dist/types.backup/browser/cookie-name.d.ts +0 -66
  226. package/dist/types.backup/browser/event-controller.d.ts +0 -221
  227. package/dist/types.backup/browser/history-state.d.ts +0 -26
  228. package/dist/types.backup/browser/index.d.ts +0 -1
  229. package/dist/types.backup/browser/intercept-utils.d.ts +0 -30
  230. package/dist/types.backup/browser/invalidate-client-cache.d.ts +0 -17
  231. package/dist/types.backup/browser/link-interceptor.d.ts +0 -43
  232. package/dist/types.backup/browser/logging.d.ts +0 -33
  233. package/dist/types.backup/browser/merge-segment-loaders.d.ts +0 -38
  234. package/dist/types.backup/browser/navigation-bridge.d.ts +0 -27
  235. package/dist/types.backup/browser/navigation-client.d.ts +0 -17
  236. package/dist/types.backup/browser/navigation-store-handle.d.ts +0 -25
  237. package/dist/types.backup/browser/navigation-store.d.ts +0 -95
  238. package/dist/types.backup/browser/navigation-transaction.d.ts +0 -75
  239. package/dist/types.backup/browser/network-error-handler.d.ts +0 -35
  240. package/dist/types.backup/browser/partial-update.d.ts +0 -61
  241. package/dist/types.backup/browser/prefetch/cache.d.ts +0 -183
  242. package/dist/types.backup/browser/prefetch/fetch.d.ts +0 -52
  243. package/dist/types.backup/browser/prefetch/observer.d.ts +0 -27
  244. package/dist/types.backup/browser/prefetch/policy.d.ts +0 -13
  245. package/dist/types.backup/browser/prefetch/queue.d.ts +0 -48
  246. package/dist/types.backup/browser/prefetch/resource-ready.d.ts +0 -28
  247. package/dist/types.backup/browser/rango-state.d.ts +0 -52
  248. package/dist/types.backup/browser/react/Link.d.ts +0 -140
  249. package/dist/types.backup/browser/react/NavigationProvider.d.ts +0 -88
  250. package/dist/types.backup/browser/react/ScrollRestoration.d.ts +0 -78
  251. package/dist/types.backup/browser/react/context.d.ts +0 -54
  252. package/dist/types.backup/browser/react/filter-segment-order.d.ts +0 -35
  253. package/dist/types.backup/browser/react/index.d.ts +0 -1
  254. package/dist/types.backup/browser/react/location-state-shared.d.ts +0 -162
  255. package/dist/types.backup/browser/react/location-state.d.ts +0 -29
  256. package/dist/types.backup/browser/react/mount-context.d.ts +0 -23
  257. package/dist/types.backup/browser/react/nonce-context.d.ts +0 -14
  258. package/dist/types.backup/browser/react/shallow-equal.d.ts +0 -5
  259. package/dist/types.backup/browser/react/use-action.d.ts +0 -61
  260. package/dist/types.backup/browser/react/use-handle.d.ts +0 -21
  261. package/dist/types.backup/browser/react/use-href.d.ts +0 -32
  262. package/dist/types.backup/browser/react/use-link-status.d.ts +0 -36
  263. package/dist/types.backup/browser/react/use-mount.d.ts +0 -24
  264. package/dist/types.backup/browser/react/use-navigation.d.ts +0 -15
  265. package/dist/types.backup/browser/react/use-params.d.ts +0 -21
  266. package/dist/types.backup/browser/react/use-pathname.d.ts +0 -13
  267. package/dist/types.backup/browser/react/use-reverse.d.ts +0 -40
  268. package/dist/types.backup/browser/react/use-router.d.ts +0 -23
  269. package/dist/types.backup/browser/react/use-search-params.d.ts +0 -19
  270. package/dist/types.backup/browser/react/use-segments.d.ts +0 -29
  271. package/dist/types.backup/browser/response-adapter.d.ts +0 -58
  272. package/dist/types.backup/browser/rsc-router.d.ts +0 -141
  273. package/dist/types.backup/browser/scroll-restoration.d.ts +0 -103
  274. package/dist/types.backup/browser/segment-reconciler.d.ts +0 -74
  275. package/dist/types.backup/browser/segment-structure-assert.d.ts +0 -16
  276. package/dist/types.backup/browser/server-action-bridge.d.ts +0 -29
  277. package/dist/types.backup/browser/types.d.ts +0 -530
  278. package/dist/types.backup/browser/validate-redirect-origin.d.ts +0 -28
  279. package/dist/types.backup/build/collect-fallback-refs.d.ts +0 -5
  280. package/dist/types.backup/build/generate-manifest.d.ts +0 -100
  281. package/dist/types.backup/build/generate-route-types.d.ts +0 -8
  282. package/dist/types.backup/build/index.d.ts +0 -21
  283. package/dist/types.backup/build/prefix-tree-utils.d.ts +0 -56
  284. package/dist/types.backup/build/route-types/ast-helpers.d.ts +0 -3
  285. package/dist/types.backup/build/route-types/ast-route-extraction.d.ts +0 -13
  286. package/dist/types.backup/build/route-types/codegen.d.ts +0 -16
  287. package/dist/types.backup/build/route-types/include-resolution.d.ts +0 -74
  288. package/dist/types.backup/build/route-types/param-extraction.d.ts +0 -13
  289. package/dist/types.backup/build/route-types/per-module-writer.d.ts +0 -18
  290. package/dist/types.backup/build/route-types/router-processing.d.ts +0 -82
  291. package/dist/types.backup/build/route-types/scan-filter.d.ts +0 -17
  292. package/dist/types.backup/build/route-types/source-scan.d.ts +0 -13
  293. package/dist/types.backup/build/runtime-discovery.d.ts +0 -24
  294. package/dist/types.backup/cache/background-task.d.ts +0 -21
  295. package/dist/types.backup/cache/cache-error.d.ts +0 -71
  296. package/dist/types.backup/cache/cache-key-utils.d.ts +0 -35
  297. package/dist/types.backup/cache/cache-policy.d.ts +0 -59
  298. package/dist/types.backup/cache/cache-runtime.d.ts +0 -51
  299. package/dist/types.backup/cache/cache-scope.d.ts +0 -134
  300. package/dist/types.backup/cache/cache-tag.d.ts +0 -79
  301. package/dist/types.backup/cache/cf/cf-base64.d.ts +0 -4
  302. package/dist/types.backup/cache/cf/cf-cache-constants.d.ts +0 -105
  303. package/dist/types.backup/cache/cf/cf-cache-store.d.ts +0 -481
  304. package/dist/types.backup/cache/cf/cf-cache-types.d.ts +0 -300
  305. package/dist/types.backup/cache/cf/cf-kv-utils.d.ts +0 -22
  306. package/dist/types.backup/cache/cf/cf-tag-marker-memo.d.ts +0 -15
  307. package/dist/types.backup/cache/cf/index.d.ts +0 -3
  308. package/dist/types.backup/cache/document-cache.d.ts +0 -69
  309. package/dist/types.backup/cache/handle-capture.d.ts +0 -23
  310. package/dist/types.backup/cache/handle-snapshot.d.ts +0 -39
  311. package/dist/types.backup/cache/index.d.ts +0 -7
  312. package/dist/types.backup/cache/memory-segment-store.d.ts +0 -163
  313. package/dist/types.backup/cache/profile-registry.d.ts +0 -40
  314. package/dist/types.backup/cache/read-through-swr.d.ts +0 -60
  315. package/dist/types.backup/cache/segment-codec.d.ts +0 -78
  316. package/dist/types.backup/cache/shell-snapshot.d.ts +0 -162
  317. package/dist/types.backup/cache/tag-invalidation.d.ts +0 -74
  318. package/dist/types.backup/cache/taint.d.ts +0 -71
  319. package/dist/types.backup/cache/types.d.ts +0 -407
  320. package/dist/types.backup/cache/vercel/index.d.ts +0 -1
  321. package/dist/types.backup/cache/vercel/vercel-cache-store.d.ts +0 -267
  322. package/dist/types.backup/client.d.ts +0 -184
  323. package/dist/types.backup/client.rsc.d.ts +0 -39
  324. package/dist/types.backup/cloudflare/index.d.ts +0 -7
  325. package/dist/types.backup/cloudflare/tracing.d.ts +0 -53
  326. package/dist/types.backup/component-utils.d.ts +0 -46
  327. package/dist/types.backup/components/DefaultDocument.d.ts +0 -13
  328. package/dist/types.backup/context-var.d.ts +0 -84
  329. package/dist/types.backup/debug.d.ts +0 -57
  330. package/dist/types.backup/decode-loader-results.d.ts +0 -5
  331. package/dist/types.backup/default-error-boundary.d.ts +0 -10
  332. package/dist/types.backup/defer.d.ts +0 -89
  333. package/dist/types.backup/deps/browser.d.ts +0 -1
  334. package/dist/types.backup/deps/html-stream-client.d.ts +0 -1
  335. package/dist/types.backup/deps/html-stream-server.d.ts +0 -1
  336. package/dist/types.backup/deps/rsc.d.ts +0 -1
  337. package/dist/types.backup/deps/ssr.d.ts +0 -1
  338. package/dist/types.backup/encode-kv.d.ts +0 -35
  339. package/dist/types.backup/errors.d.ts +0 -226
  340. package/dist/types.backup/escape-script.d.ts +0 -44
  341. package/dist/types.backup/handle.d.ts +0 -93
  342. package/dist/types.backup/handles/MetaTags.d.ts +0 -17
  343. package/dist/types.backup/handles/Scripts.d.ts +0 -38
  344. package/dist/types.backup/handles/breadcrumbs.d.ts +0 -43
  345. package/dist/types.backup/handles/deferred-resolution.d.ts +0 -53
  346. package/dist/types.backup/handles/is-thenable.d.ts +0 -12
  347. package/dist/types.backup/handles/meta.d.ts +0 -43
  348. package/dist/types.backup/handles/script.d.ts +0 -139
  349. package/dist/types.backup/host/cookie-handler.d.ts +0 -8
  350. package/dist/types.backup/host/errors.d.ts +0 -40
  351. package/dist/types.backup/host/index.d.ts +0 -33
  352. package/dist/types.backup/host/pattern-matcher.d.ts +0 -30
  353. package/dist/types.backup/host/router.d.ts +0 -12
  354. package/dist/types.backup/host/testing.d.ts +0 -41
  355. package/dist/types.backup/host/types.d.ts +0 -148
  356. package/dist/types.backup/host/utils.d.ts +0 -20
  357. package/dist/types.backup/href-client.d.ts +0 -214
  358. package/dist/types.backup/index.d.ts +0 -112
  359. package/dist/types.backup/index.rsc.d.ts +0 -51
  360. package/dist/types.backup/internal-debug.d.ts +0 -1
  361. package/dist/types.backup/loader-store.d.ts +0 -193
  362. package/dist/types.backup/loader.d.ts +0 -18
  363. package/dist/types.backup/loader.rsc.d.ts +0 -18
  364. package/dist/types.backup/missing-id-error.d.ts +0 -1
  365. package/dist/types.backup/outlet-context.d.ts +0 -12
  366. package/dist/types.backup/outlet-provider.d.ts +0 -12
  367. package/dist/types.backup/prerender/build-shell-capture.d.ts +0 -104
  368. package/dist/types.backup/prerender/param-hash.d.ts +0 -6
  369. package/dist/types.backup/prerender/shell-manifest-key.d.ts +0 -18
  370. package/dist/types.backup/prerender/store.d.ts +0 -62
  371. package/dist/types.backup/prerender.d.ts +0 -292
  372. package/dist/types.backup/redirect-origin.d.ts +0 -55
  373. package/dist/types.backup/regex-escape.d.ts +0 -6
  374. package/dist/types.backup/render-error-thrower.d.ts +0 -13
  375. package/dist/types.backup/response-utils.d.ts +0 -35
  376. package/dist/types.backup/reverse.d.ts +0 -206
  377. package/dist/types.backup/root-error-boundary.d.ts +0 -32
  378. package/dist/types.backup/route-content-wrapper.d.ts +0 -40
  379. package/dist/types.backup/route-definition/dsl-helpers.d.ts +0 -130
  380. package/dist/types.backup/route-definition/helper-factories.d.ts +0 -22
  381. package/dist/types.backup/route-definition/helpers-types.d.ts +0 -392
  382. package/dist/types.backup/route-definition/index.d.ts +0 -7
  383. package/dist/types.backup/route-definition/redirect.d.ts +0 -48
  384. package/dist/types.backup/route-definition/resolve-handler-use.d.ts +0 -19
  385. package/dist/types.backup/route-definition/use-item-types.d.ts +0 -1
  386. package/dist/types.backup/route-definition.d.ts +0 -1
  387. package/dist/types.backup/route-map-builder.d.ts +0 -127
  388. package/dist/types.backup/route-name.d.ts +0 -27
  389. package/dist/types.backup/route-types.d.ts +0 -172
  390. package/dist/types.backup/router/basename.d.ts +0 -10
  391. package/dist/types.backup/router/content-negotiation.d.ts +0 -91
  392. package/dist/types.backup/router/debug-manifest.d.ts +0 -7
  393. package/dist/types.backup/router/error-handling.d.ts +0 -76
  394. package/dist/types.backup/router/find-match.d.ts +0 -19
  395. package/dist/types.backup/router/handler-context.d.ts +0 -41
  396. package/dist/types.backup/router/instrument.d.ts +0 -161
  397. package/dist/types.backup/router/intercept-resolution.d.ts +0 -79
  398. package/dist/types.backup/router/lazy-includes.d.ts +0 -26
  399. package/dist/types.backup/router/loader-resolution.d.ts +0 -63
  400. package/dist/types.backup/router/logging.d.ts +0 -41
  401. package/dist/types.backup/router/manifest.d.ts +0 -8
  402. package/dist/types.backup/router/match-api.d.ts +0 -19
  403. package/dist/types.backup/router/match-context.d.ts +0 -184
  404. package/dist/types.backup/router/match-handlers.d.ts +0 -49
  405. package/dist/types.backup/router/match-middleware/background-revalidation.d.ts +0 -113
  406. package/dist/types.backup/router/match-middleware/cache-lookup.d.ts +0 -113
  407. package/dist/types.backup/router/match-middleware/cache-store.d.ts +0 -112
  408. package/dist/types.backup/router/match-middleware/index.d.ts +0 -80
  409. package/dist/types.backup/router/match-middleware/intercept-resolution.d.ts +0 -116
  410. package/dist/types.backup/router/match-middleware/segment-resolution.d.ts +0 -94
  411. package/dist/types.backup/router/match-pipelines.d.ts +0 -103
  412. package/dist/types.backup/router/match-result.d.ts +0 -114
  413. package/dist/types.backup/router/metrics.d.ts +0 -6
  414. package/dist/types.backup/router/middleware-types.d.ts +0 -74
  415. package/dist/types.backup/router/middleware.d.ts +0 -116
  416. package/dist/types.backup/router/navigation-snapshot.d.ts +0 -22
  417. package/dist/types.backup/router/params-util.d.ts +0 -8
  418. package/dist/types.backup/router/parse-pattern.d.ts +0 -38
  419. package/dist/types.backup/router/pattern-matching.d.ts +0 -169
  420. package/dist/types.backup/router/prefetch-cache-ttl.d.ts +0 -27
  421. package/dist/types.backup/router/prefetch-limits.d.ts +0 -20
  422. package/dist/types.backup/router/prerender-match.d.ts +0 -50
  423. package/dist/types.backup/router/preview-match.d.ts +0 -22
  424. package/dist/types.backup/router/request-classification.d.ts +0 -104
  425. package/dist/types.backup/router/revalidation.d.ts +0 -57
  426. package/dist/types.backup/router/route-snapshot.d.ts +0 -112
  427. package/dist/types.backup/router/router-context.d.ts +0 -137
  428. package/dist/types.backup/router/router-interfaces.d.ts +0 -432
  429. package/dist/types.backup/router/router-options.d.ts +0 -738
  430. package/dist/types.backup/router/router-registry.d.ts +0 -15
  431. package/dist/types.backup/router/segment-resolution/fresh.d.ts +0 -55
  432. package/dist/types.backup/router/segment-resolution/helpers.d.ts +0 -93
  433. package/dist/types.backup/router/segment-resolution/loader-cache.d.ts +0 -33
  434. package/dist/types.backup/router/segment-resolution/loader-mask.d.ts +0 -44
  435. package/dist/types.backup/router/segment-resolution/loader-snapshot.d.ts +0 -90
  436. package/dist/types.backup/router/segment-resolution/mask-nested.d.ts +0 -53
  437. package/dist/types.backup/router/segment-resolution/revalidation.d.ts +0 -85
  438. package/dist/types.backup/router/segment-resolution/static-store.d.ts +0 -17
  439. package/dist/types.backup/router/segment-resolution/streamed-handler-telemetry.d.ts +0 -16
  440. package/dist/types.backup/router/segment-resolution/view-transition-default.d.ts +0 -28
  441. package/dist/types.backup/router/segment-resolution.d.ts +0 -3
  442. package/dist/types.backup/router/segment-wrappers.d.ts +0 -53
  443. package/dist/types.backup/router/state-cookie-name.d.ts +0 -1
  444. package/dist/types.backup/router/substitute-pattern-params.d.ts +0 -23
  445. package/dist/types.backup/router/telemetry-otel.d.ts +0 -113
  446. package/dist/types.backup/router/telemetry.d.ts +0 -215
  447. package/dist/types.backup/router/timeout.d.ts +0 -68
  448. package/dist/types.backup/router/tracing.d.ts +0 -125
  449. package/dist/types.backup/router/trie-matching.d.ts +0 -32
  450. package/dist/types.backup/router/types.d.ts +0 -98
  451. package/dist/types.backup/router/url-params.d.ts +0 -26
  452. package/dist/types.backup/router.d.ts +0 -7
  453. package/dist/types.backup/rsc/capture-queue.d.ts +0 -6
  454. package/dist/types.backup/rsc/full-payload.d.ts +0 -22
  455. package/dist/types.backup/rsc/handler-context.d.ts +0 -31
  456. package/dist/types.backup/rsc/handler.d.ts +0 -9
  457. package/dist/types.backup/rsc/helpers.d.ts +0 -213
  458. package/dist/types.backup/rsc/index.d.ts +0 -17
  459. package/dist/types.backup/rsc/json-route-result.d.ts +0 -20
  460. package/dist/types.backup/rsc/loader-fetch.d.ts +0 -14
  461. package/dist/types.backup/rsc/manifest-init.d.ts +0 -18
  462. package/dist/types.backup/rsc/nonce.d.ts +0 -28
  463. package/dist/types.backup/rsc/origin-guard.d.ts +0 -50
  464. package/dist/types.backup/rsc/progressive-enhancement.d.ts +0 -19
  465. package/dist/types.backup/rsc/redirect-guard.d.ts +0 -35
  466. package/dist/types.backup/rsc/response-cache-serve.d.ts +0 -46
  467. package/dist/types.backup/rsc/response-error.d.ts +0 -19
  468. package/dist/types.backup/rsc/response-route-handler.d.ts +0 -29
  469. package/dist/types.backup/rsc/rsc-rendering.d.ts +0 -23
  470. package/dist/types.backup/rsc/runtime-warnings.d.ts +0 -22
  471. package/dist/types.backup/rsc/server-action.d.ts +0 -68
  472. package/dist/types.backup/rsc/shell-build-manifest.d.ts +0 -84
  473. package/dist/types.backup/rsc/shell-capture-constants.d.ts +0 -27
  474. package/dist/types.backup/rsc/shell-capture.d.ts +0 -374
  475. package/dist/types.backup/rsc/shell-serve.d.ts +0 -136
  476. package/dist/types.backup/rsc/ssr-setup.d.ts +0 -48
  477. package/dist/types.backup/rsc/transition-gate.d.ts +0 -27
  478. package/dist/types.backup/rsc/types.d.ts +0 -290
  479. package/dist/types.backup/runtime-env.d.ts +0 -1
  480. package/dist/types.backup/search-params.d.ts +0 -125
  481. package/dist/types.backup/segment-content-promise.d.ts +0 -13
  482. package/dist/types.backup/segment-fragments.d.ts +0 -56
  483. package/dist/types.backup/segment-loader-promise.d.ts +0 -22
  484. package/dist/types.backup/segment-system.d.ts +0 -84
  485. package/dist/types.backup/serialize.d.ts +0 -164
  486. package/dist/types.backup/server/context.d.ts +0 -494
  487. package/dist/types.backup/server/cookie-parse.d.ts +0 -10
  488. package/dist/types.backup/server/cookie-store.d.ts +0 -107
  489. package/dist/types.backup/server/fetchable-loader-store.d.ts +0 -20
  490. package/dist/types.backup/server/handle-store.d.ts +0 -100
  491. package/dist/types.backup/server/loader-registry.d.ts +0 -32
  492. package/dist/types.backup/server/request-context.d.ts +0 -596
  493. package/dist/types.backup/server/root-layout.d.ts +0 -3
  494. package/dist/types.backup/server.d.ts +0 -15
  495. package/dist/types.backup/ssr/index.d.ts +0 -233
  496. package/dist/types.backup/ssr/inject-rsc-eager.d.ts +0 -3
  497. package/dist/types.backup/ssr/preinit-client-references.d.ts +0 -71
  498. package/dist/types.backup/ssr/ssr-root.d.ts +0 -69
  499. package/dist/types.backup/static-handler.d.ts +0 -57
  500. package/dist/types.backup/testing/cache-status.d.ts +0 -63
  501. package/dist/types.backup/testing/collect-handle.d.ts +0 -20
  502. package/dist/types.backup/testing/dispatch.d.ts +0 -123
  503. package/dist/types.backup/testing/dom.entry.d.ts +0 -15
  504. package/dist/types.backup/testing/e2e/fixture.d.ts +0 -37
  505. package/dist/types.backup/testing/e2e/index.d.ts +0 -30
  506. package/dist/types.backup/testing/e2e/matchers.d.ts +0 -17
  507. package/dist/types.backup/testing/e2e/page-helpers.d.ts +0 -62
  508. package/dist/types.backup/testing/e2e/parity.d.ts +0 -111
  509. package/dist/types.backup/testing/e2e/server.d.ts +0 -35
  510. package/dist/types.backup/testing/flight-matchers.d.ts +0 -55
  511. package/dist/types.backup/testing/flight-normalize.d.ts +0 -1
  512. package/dist/types.backup/testing/flight-tree.d.ts +0 -192
  513. package/dist/types.backup/testing/flight.d.ts +0 -115
  514. package/dist/types.backup/testing/flight.entry.d.ts +0 -27
  515. package/dist/types.backup/testing/generated-routes.d.ts +0 -66
  516. package/dist/types.backup/testing/index.d.ts +0 -52
  517. package/dist/types.backup/testing/internal/context.d.ts +0 -225
  518. package/dist/types.backup/testing/internal/flight-client-globals.d.ts +0 -1
  519. package/dist/types.backup/testing/internal/seed-vars.d.ts +0 -30
  520. package/dist/types.backup/testing/render-handler.d.ts +0 -160
  521. package/dist/types.backup/testing/render-route.d.ts +0 -246
  522. package/dist/types.backup/testing/run-loader.d.ts +0 -186
  523. package/dist/types.backup/testing/run-middleware.d.ts +0 -132
  524. package/dist/types.backup/testing/run-transition-when.d.ts +0 -77
  525. package/dist/types.backup/testing/vitest-stubs/cloudflare-email.d.ts +0 -6
  526. package/dist/types.backup/testing/vitest-stubs/cloudflare-workers.d.ts +0 -13
  527. package/dist/types.backup/testing/vitest-stubs/plugin-rsc.d.ts +0 -7
  528. package/dist/types.backup/testing/vitest-stubs/version.d.ts +0 -1
  529. package/dist/types.backup/testing/vitest.d.ts +0 -205
  530. package/dist/types.backup/theme/ThemeProvider.d.ts +0 -13
  531. package/dist/types.backup/theme/ThemeScript.d.ts +0 -45
  532. package/dist/types.backup/theme/constants.d.ts +0 -39
  533. package/dist/types.backup/theme/index.d.ts +0 -29
  534. package/dist/types.backup/theme/theme-context.d.ts +0 -21
  535. package/dist/types.backup/theme/theme-script.d.ts +0 -26
  536. package/dist/types.backup/theme/types.d.ts +0 -162
  537. package/dist/types.backup/theme/use-theme.d.ts +0 -8
  538. package/dist/types.backup/types/boundaries.d.ts +0 -93
  539. package/dist/types.backup/types/cache-types.d.ts +0 -191
  540. package/dist/types.backup/types/error-types.d.ts +0 -114
  541. package/dist/types.backup/types/global-namespace.d.ts +0 -90
  542. package/dist/types.backup/types/handler-context.d.ts +0 -658
  543. package/dist/types.backup/types/index.d.ts +0 -11
  544. package/dist/types.backup/types/loader-types.d.ts +0 -182
  545. package/dist/types.backup/types/request-scope.d.ts +0 -93
  546. package/dist/types.backup/types/route-config.d.ts +0 -105
  547. package/dist/types.backup/types/route-entry.d.ts +0 -95
  548. package/dist/types.backup/types/segments.d.ts +0 -234
  549. package/dist/types.backup/types.d.ts +0 -1
  550. package/dist/types.backup/urls/include-helper.d.ts +0 -17
  551. package/dist/types.backup/urls/include-provider.d.ts +0 -27
  552. package/dist/types.backup/urls/index.d.ts +0 -6
  553. package/dist/types.backup/urls/path-helper-types.d.ts +0 -197
  554. package/dist/types.backup/urls/path-helper.d.ts +0 -12
  555. package/dist/types.backup/urls/pattern-types.d.ts +0 -166
  556. package/dist/types.backup/urls/response-types.d.ts +0 -67
  557. package/dist/types.backup/urls/type-extraction.d.ts +0 -157
  558. package/dist/types.backup/urls/urls-function.d.ts +0 -24
  559. package/dist/types.backup/urls.d.ts +0 -1
  560. package/dist/types.backup/use-loader.d.ts +0 -150
  561. package/dist/types.backup/vercel/index.d.ts +0 -10
  562. package/dist/types.backup/vercel/tracing.d.ts +0 -70
  563. package/dist/types.backup/vite/debug.d.ts +0 -80
  564. package/dist/types.backup/vite/discovery/bundle-postprocess.d.ts +0 -12
  565. package/dist/types.backup/vite/discovery/dev-prerender-cache.d.ts +0 -65
  566. package/dist/types.backup/vite/discovery/discover-routers.d.ts +0 -17
  567. package/dist/types.backup/vite/discovery/discovery-errors.d.ts +0 -113
  568. package/dist/types.backup/vite/discovery/gate-state.d.ts +0 -79
  569. package/dist/types.backup/vite/discovery/prerender-collection.d.ts +0 -24
  570. package/dist/types.backup/vite/discovery/route-types-writer.d.ts +0 -32
  571. package/dist/types.backup/vite/discovery/self-gen-tracking.d.ts +0 -22
  572. package/dist/types.backup/vite/discovery/shell-prerender-phase.d.ts +0 -40
  573. package/dist/types.backup/vite/discovery/state.d.ts +0 -162
  574. package/dist/types.backup/vite/discovery/virtual-module-codegen.d.ts +0 -15
  575. package/dist/types.backup/vite/index.d.ts +0 -11
  576. package/dist/types.backup/vite/inject-client-debug.d.ts +0 -56
  577. package/dist/types.backup/vite/plugin-types.d.ts +0 -298
  578. package/dist/types.backup/vite/plugins/cjs-to-esm.d.ts +0 -6
  579. package/dist/types.backup/vite/plugins/client-ref-dedup.d.ts +0 -40
  580. package/dist/types.backup/vite/plugins/client-ref-hashing.d.ts +0 -35
  581. package/dist/types.backup/vite/plugins/cloudflare-protocol-stub.d.ts +0 -64
  582. package/dist/types.backup/vite/plugins/expose-action-id.d.ts +0 -18
  583. package/dist/types.backup/vite/plugins/expose-id-utils.d.ts +0 -37
  584. package/dist/types.backup/vite/plugins/expose-ids/export-analysis.d.ts +0 -19
  585. package/dist/types.backup/vite/plugins/expose-ids/handler-transform.d.ts +0 -10
  586. package/dist/types.backup/vite/plugins/expose-ids/loader-transform.d.ts +0 -8
  587. package/dist/types.backup/vite/plugins/expose-ids/router-transform.d.ts +0 -13
  588. package/dist/types.backup/vite/plugins/expose-ids/types.d.ts +0 -29
  589. package/dist/types.backup/vite/plugins/expose-internal-ids.d.ts +0 -6
  590. package/dist/types.backup/vite/plugins/performance-tracks.d.ts +0 -25
  591. package/dist/types.backup/vite/plugins/refresh-cmd.d.ts +0 -20
  592. package/dist/types.backup/vite/plugins/use-cache-transform.d.ts +0 -20
  593. package/dist/types.backup/vite/plugins/vercel-output.d.ts +0 -85
  594. package/dist/types.backup/vite/plugins/version-injector.d.ts +0 -21
  595. package/dist/types.backup/vite/plugins/version-plugin.d.ts +0 -19
  596. package/dist/types.backup/vite/plugins/virtual-entries.d.ts +0 -36
  597. package/dist/types.backup/vite/plugins/virtual-stub-plugin.d.ts +0 -7
  598. package/dist/types.backup/vite/rango.d.ts +0 -29
  599. package/dist/types.backup/vite/router-discovery.d.ts +0 -23
  600. package/dist/types.backup/vite/utils/ast-handler-extract.d.ts +0 -64
  601. package/dist/types.backup/vite/utils/banner.d.ts +0 -2
  602. package/dist/types.backup/vite/utils/bundle-analysis.d.ts +0 -28
  603. package/dist/types.backup/vite/utils/client-chunks.d.ts +0 -55
  604. package/dist/types.backup/vite/utils/directive-prologue.d.ts +0 -16
  605. package/dist/types.backup/vite/utils/forward-user-plugins.d.ts +0 -37
  606. package/dist/types.backup/vite/utils/manifest-utils.d.ts +0 -7
  607. package/dist/types.backup/vite/utils/package-resolution.d.ts +0 -6
  608. package/dist/types.backup/vite/utils/prerender-utils.d.ts +0 -32
  609. package/dist/types.backup/vite/utils/shared-utils.d.ts +0 -55
@@ -27,8 +27,21 @@ import {
27
27
  createResponseWithMergedHeaders,
28
28
  createSimpleRedirectResponse,
29
29
  attachLocationStateIfPresent,
30
+ matchAndRecordParams,
30
31
  } from "./helpers.js";
31
- import { renderRscFlightStage, renderRscResponse } from "./render-pipeline.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";
32
45
  import type { HandlerContext } from "./handler-context.js";
33
46
  import { gateTransitions } from "./transition-gate.js";
34
47
  import { buildFullPayload } from "./full-payload.js";
@@ -44,6 +57,7 @@ import {
44
57
  SHELL_STATUS_HEADER,
45
58
  resolvePprConfig,
46
59
  buildShellKey,
60
+ shellSearchSeed,
47
61
  isValidShellHit,
48
62
  hasIntactShellPayload,
49
63
  base64ToBytes,
@@ -140,12 +154,14 @@ function buildNavigationShellKey(
140
154
  function createShellCaptureDescriptor(
141
155
  ctx: HandlerContext<any>,
142
156
  key: string,
157
+ searchSeed: string,
143
158
  pprConfig: ResolvedPprConfig,
144
159
  store: SegmentCacheStore<any>,
145
160
  navigationOnly?: true,
146
161
  ): ShellCaptureDescriptor {
147
162
  return {
148
163
  key,
164
+ searchSeed,
149
165
  buildVersion: ctx.version,
150
166
  ttl: pprConfig.ttl,
151
167
  swr: pprConfig.swr,
@@ -281,6 +297,34 @@ export function handleRscRendering<TEnv>(
281
297
  );
282
298
  }
283
299
 
300
+ interface RequestRenderInput<TEnv> {
301
+ ctx: HandlerContext<TEnv>;
302
+ request: Request;
303
+ env: TEnv;
304
+ url: URL;
305
+ isPartial: boolean;
306
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"];
307
+ nonce: string | undefined;
308
+ renderSpan: TraceSpan;
309
+ reqCtx: ReturnType<typeof getRequestContext>;
310
+ }
311
+
312
+ type ShellServeOutcome =
313
+ | { kind: "serve"; response: Response }
314
+ | { kind: "miss"; descriptor: ShellCaptureDescriptor; ssrModule: SSRModule }
315
+ | { kind: "pass" };
316
+
317
+ type PreparedRender =
318
+ | { kind: "control"; response: Response }
319
+ | {
320
+ kind: "payload";
321
+ payload: RscPayload;
322
+ hasInterceptSlots: boolean;
323
+ pprReplayStatus?: PprReplayStatus;
324
+ partialCaptureNeeded: boolean;
325
+ partialCaptureKey?: string;
326
+ };
327
+
284
328
  async function handleRscRenderingInner<TEnv>(
285
329
  ctx: HandlerContext<TEnv>,
286
330
  request: Request,
@@ -291,13 +335,49 @@ async function handleRscRenderingInner<TEnv>(
291
335
  nonce: string | undefined,
292
336
  renderSpan: TraceSpan,
293
337
  ): Promise<Response> {
338
+ // Flow trace rides the internal debug surface (INTERNAL_RANGO_DEBUG=1): the
339
+ // Vite pipeline bakes the flag at build/dev-server start (inject-client-debug),
340
+ // so trace allocation and output fold out of ordinary production builds while
341
+ // an explicit debug build keeps them. The routine itself remains the executor.
342
+ const mode = isPartial ? "partial" : "document";
343
+ const trace = INTERNAL_RANGO_DEBUG ? createRoutineTrace(mode) : undefined;
294
344
  const reqCtx = getRequestContext();
345
+ const input: RequestRenderInput<TEnv> = {
346
+ ctx,
347
+ request,
348
+ env,
349
+ url,
350
+ isPartial,
351
+ handleStore,
352
+ nonce,
353
+ renderSpan,
354
+ reqCtx,
355
+ };
356
+ try {
357
+ return await runRoutine(requestRenderPlan(input), {
358
+ trace,
359
+ owner: reqCtx,
360
+ });
361
+ } finally {
362
+ if (trace) {
363
+ console.log(
364
+ `[routine] ${request.method} ${url.pathname} (${trace.name})\n${trace.format()}`,
365
+ );
366
+ }
367
+ }
368
+ }
295
369
 
296
- let payload: RscPayload;
297
- let hasInterceptSlots = false;
298
- let pprReplayStatus: PprReplayStatus | undefined;
299
- let partialCaptureNeeded = false;
300
- let partialCaptureKey: string | undefined;
370
+ /**
371
+ * The request-level render plan. Reads top to bottom as the request executes:
372
+ * serve a stored PPR shell if one commits, otherwise match and build the
373
+ * payload, render it through the stage driver, then hand off background
374
+ * captures. Effects run through the routine runner (yield-before-execute,
375
+ * exact result/error identity — see routine-plan.ts).
376
+ */
377
+ function* requestRenderPlan<TEnv>(
378
+ input: RequestRenderInput<TEnv>,
379
+ ): RoutinePlan<Response> {
380
+ const { isPartial, reqCtx } = input;
301
381
 
302
382
  // --- Axis 2: integrated PPR shell serve (docs/design/ppr-shell-resume.md) ---
303
383
  //
@@ -305,214 +385,278 @@ async function handleRscRenderingInner<TEnv>(
305
385
  // chain (executeRender wraps it), so no shell byte can precede a guard
306
386
  // decision — that ordering is what makes a shared shell safe. Routes
307
387
  // without the `ppr` option stay pure axis 1 at zero cost.
308
- let pprMiss: {
309
- descriptor: ShellCaptureDescriptor;
310
- ssrModule: SSRModule;
311
- } | null = null;
388
+ const shell = yield* scope("shell-serve", shellServePlan(input));
389
+ if (shell.kind === "serve") return shell.response;
390
+
391
+ // Match + payload. A control response (redirect, prerender collection)
392
+ // ends the plan before any rendering.
393
+ const prepared = yield* scope(
394
+ isPartial ? "prepare:partial" : "prepare:full",
395
+ preparePayloadPlan(input),
396
+ );
397
+ if (prepared.kind === "control") return prepared.response;
398
+
399
+ // For partial requests, include any server-set location state in the payload.
400
+ // SSR (full page) requests ignore location state since there's no history.state
401
+ // to write to on a fresh page load.
402
+ if (isPartial && prepared.payload.metadata) {
403
+ attachLocationStateIfPresent(prepared.payload);
404
+ }
405
+
406
+ const response = yield* step("render", () =>
407
+ renderPreparedRscResponse(input, prepared),
408
+ );
409
+
410
+ // --- Axis 2: PPR shell CAPTURE on MISS (background task; see design doc) ---
411
+ // Capture only a 200 HTML document (a 404/error render is not a cacheable
412
+ // shell). Capture does not flow through the HTTP pipeline — middleware never
413
+ // re-runs (it already ran for this request; guarding is serve-time).
414
+ // reqCtx._dynamic is re-read here on purpose: a loader may have marked the
415
+ // request dynamic while rendering.
416
+ if (shell.kind === "miss" && !reqCtx._dynamic) {
417
+ if (
418
+ response.status === 200 &&
419
+ (response.headers.get("content-type") ?? "").includes("text/html")
420
+ ) {
421
+ const { descriptor, ssrModule } = shell;
422
+ yield* handoff("shell-capture", () =>
423
+ scheduleShellCapture(
424
+ input.ctx,
425
+ input.request,
426
+ input.env,
427
+ input.url,
428
+ reqCtx,
429
+ ssrModule,
430
+ descriptor,
431
+ ),
432
+ );
433
+ }
434
+ response.headers.set(SHELL_STATUS_HEADER, "MISS");
435
+ }
436
+
312
437
  if (
313
- !isPartial &&
314
- request.method === "GET" &&
315
- !url.searchParams.has("__prerender_collect") &&
316
- !isRscRequest(request, url, false) &&
317
- !reqCtx._dynamic
438
+ isPartial &&
439
+ prepared.partialCaptureNeeded &&
440
+ !reqCtx._dynamic &&
441
+ response.status === 200
318
442
  ) {
319
- const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry);
320
- if (pprConfig) {
321
- // A per-request CSP nonce pins the route to axis 1: a shared shell would
322
- // freeze the capture request's nonce and CSP would reject it for every
323
- // other visitor. BOTH nonce sources must gate — the createRouter({ nonce })
324
- // provider (`nonce` param) and a middleware ctx.set(nonce, …) token write;
325
- // the provider-only check missed the latter (issue #656).
326
- const activeNonce = nonce ?? contextGet(reqCtx._variables, nonceToken);
327
- const store = reqCtx._cacheStore;
328
- const key = buildShellKey(url, reqCtx._searchParamsFilter);
329
- // Dev Server-Timing mirror (issue #651): a capture completes AFTER its
330
- // triggering response committed, so its outcome can only ride a LATER
331
- // response's header. Read-and-clear keeps one capture = one report;
332
- // dev-only (see takeCaptureDebugEventForTiming).
333
- if (process.env.NODE_ENV !== "production" && reqCtx._metricsStore) {
334
- const lastCapture = takeCaptureDebugEventForTiming(key);
335
- if (lastCapture) {
336
- appendMetric(
337
- reqCtx._metricsStore,
338
- "ppr:capture",
339
- performance.now(),
340
- lastCapture.attemptMs ?? 0,
341
- undefined,
342
- // attemptMs already rides as this entry's dur — drop it from desc.
343
- describeShellCaptureEvent({ ...lastCapture, attemptMs: undefined }),
344
- );
345
- }
346
- // Same mirror for the previous HIT's tail: its per-stage numbers
347
- // (seed/match/handover/first-html/complete) finished after that
348
- // response's headers were committed, so they ride THIS request's
349
- // Server-Timing as `ppr:tail;dur=<complete ms>`.
350
- const lastTail = takeShellTailTimingForServerTiming(key);
351
- if (lastTail) {
352
- appendMetric(
353
- reqCtx._metricsStore,
354
- "ppr:tail",
355
- performance.now(),
356
- lastTail.completeMs ?? 0,
357
- undefined,
358
- // completeMs already rides as this entry's dur — drop it from desc.
359
- describeShellTailTiming({ ...lastTail, completeMs: undefined }),
360
- );
361
- }
443
+ const captureKey = prepared.partialCaptureKey;
444
+ yield* handoff("navigation-shell-capture", () =>
445
+ scheduleNavigationShellCapture(input, captureKey),
446
+ );
447
+ }
448
+
449
+ return response;
450
+ }
451
+
452
+ /**
453
+ * Axis 2 shell serve. Sync gates stay plan code; store and SSR effects run as
454
+ * named steps. Outcomes: serve a composed shell response, report a MISS (the
455
+ * top-level plan schedules the capture after the response commits), or pass
456
+ * (route not eligible — pure axis 1).
457
+ */
458
+ function* shellServePlan<TEnv>(
459
+ input: RequestRenderInput<TEnv>,
460
+ ): RoutinePlan<ShellServeOutcome> {
461
+ const { ctx, request, env, url, isPartial, handleStore, nonce, reqCtx } =
462
+ input;
463
+
464
+ if (
465
+ isPartial ||
466
+ request.method !== "GET" ||
467
+ url.searchParams.has("__prerender_collect") ||
468
+ isRscRequest(request, url, false) ||
469
+ reqCtx._dynamic
470
+ ) {
471
+ return { kind: "pass" };
472
+ }
473
+ const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry);
474
+ if (!pprConfig) return { kind: "pass" };
475
+
476
+ // A per-request CSP nonce pins the route to axis 1: a shared shell would
477
+ // freeze the capture request's nonce and CSP would reject it for every
478
+ // other visitor. BOTH nonce sources must gate — the createRouter({ nonce })
479
+ // provider (`nonce` param) and a middleware ctx.set(nonce, …) token write;
480
+ // the provider-only check missed the latter (issue #656).
481
+ const activeNonce = nonce ?? contextGet(reqCtx._variables, nonceToken);
482
+ const store = reqCtx._cacheStore;
483
+ const key = buildShellKey(url, reqCtx._searchParamsFilter);
484
+ mirrorPprServerTimingsForDev(key, reqCtx);
485
+ if (activeNonce !== undefined) {
486
+ // Declared intent that cannot be honored deserves a diagnostic (unlike an
487
+ // undeclared route, which is silent): a ppr route gated off by an active
488
+ // per-request nonce warns once per key. Axis 1 after the warning.
489
+ warnPprNonceActiveOnce(key);
490
+ return { kind: "pass" };
491
+ }
492
+ if (!hasShellFamily(store)) {
493
+ // Declared intent that cannot be honored deserves a diagnostic (unlike an
494
+ // undeclared route, which is silent). Axis 1 after the warning.
495
+ warnShellStoreMissingOnce(key);
496
+ return { kind: "pass" };
497
+ }
498
+
499
+ // SSR setup starts before route handling, so read the shell before joining it
500
+ // to overlap the remaining setup work with cache I/O.
501
+ const cached = yield* step("shell-read", () =>
502
+ readShellEntry(store, key, reqCtx),
503
+ );
504
+
505
+ // allReady (ssr.resolveStreaming) bypasses PPR entirely: buffering defeats
506
+ // streaming, so bots/SEO crawlers get one complete axis-1 document. These
507
+ // routes pay one unnecessary shell read to keep the PPR hot path concurrent.
508
+ const [ssrModule, streamMode] = yield* step("ssr-setup", () =>
509
+ getSSRSetup(ctx, request, env, url, reqCtx._metricsStore),
510
+ );
511
+ if (
512
+ streamMode === "allReady" ||
513
+ !ssrModule.resumeShellHTML ||
514
+ !ssrModule.captureShellHTML
515
+ ) {
516
+ return { kind: "pass" };
517
+ }
518
+ const descriptor = createShellCaptureDescriptor(
519
+ ctx,
520
+ key,
521
+ shellSearchSeed(url, reqCtx._searchParamsFilter),
522
+ pprConfig,
523
+ store,
524
+ );
525
+
526
+ if (
527
+ cached &&
528
+ !cached.entry.navigationOnly &&
529
+ isValidShellHit(cached.entry, ctx.version)
530
+ ) {
531
+ if (!hasIntactShellPayload(cached.entry)) {
532
+ // Corrupt stored payload (undecodable prelude / unparseable
533
+ // postponed): a store-layer fault worth a diagnostic, unlike the
534
+ // silent version-mismatch lifecycle misses above. Degrade to MISS
535
+ // — the top-level plan schedules the recapture that overwrites it.
536
+ reportCacheError(
537
+ new Error(
538
+ `corrupt shell entry for "${key}": prelude/postponed failed ` +
539
+ "the integrity check; serving axis 1 and recapturing",
540
+ ),
541
+ "cache-read",
542
+ "[ShellServe] getShell",
543
+ );
544
+ } else {
545
+ // Stale (SWR) hit: serve the stale shell now, recapture in the
546
+ // background (stampede-guarded + backoff inside scheduleShellCapture).
547
+ if (cached.shouldRevalidate) {
548
+ yield* handoff("shell-recapture", () =>
549
+ scheduleShellCapture(
550
+ ctx,
551
+ request,
552
+ env,
553
+ url,
554
+ reqCtx,
555
+ ssrModule,
556
+ descriptor,
557
+ ),
558
+ );
362
559
  }
363
- if (activeNonce !== undefined) {
364
- // Declared intent that cannot be honored deserves a diagnostic (unlike an
365
- // undeclared route, which is silent): a ppr route gated off by an active
366
- // per-request nonce warns once per key. Axis 1 after the warning.
367
- warnPprNonceActiveOnce(key);
368
- } else if (!hasShellFamily(store)) {
369
- // Declared intent that cannot be honored deserves a diagnostic (unlike an
370
- // undeclared route, which is silent). Axis 1 after the warning.
371
- warnShellStoreMissingOnce(key);
372
- } else {
373
- // allReady (ssr.resolveStreaming) bypasses PPR entirely: buffering defeats
374
- // streaming, so bots/SEO crawlers get one complete axis-1 document.
375
- const [ssrModule, streamMode] = await getSSRSetup(
560
+ const entry = cached.entry;
561
+ const response = yield* step("shell-hit", () =>
562
+ serveShellHit(
376
563
  ctx,
377
564
  request,
378
565
  env,
379
566
  url,
380
- reqCtx._metricsStore,
381
- );
382
- if (
383
- streamMode !== "allReady" &&
384
- ssrModule.resumeShellHTML &&
385
- ssrModule.captureShellHTML
386
- ) {
387
- const descriptor = createShellCaptureDescriptor(
388
- ctx,
389
- key,
390
- pprConfig,
391
- store,
392
- );
393
- // One serve funnel for BOTH entry sources (runtime store hit below,
394
- // build-manifest hit further down): schedule the background
395
- // recapture when asked, then commit the composed response.
396
- const serveHit = (
397
- entry: DocumentShellCacheEntry,
398
- revalidate: boolean | undefined,
399
- ): Response => {
400
- if (revalidate) {
401
- scheduleShellCapture(
402
- ctx,
403
- request,
404
- env,
405
- url,
406
- reqCtx,
407
- ssrModule,
408
- descriptor,
409
- );
410
- }
411
- return serveShellHit(
412
- ctx,
413
- request,
414
- env,
415
- url,
416
- reqCtx,
417
- handleStore,
418
- ssrModule,
419
- entry,
420
- descriptor,
421
- );
422
- };
423
- let cached: Awaited<ReturnType<typeof store.getShell>> = null;
424
- const shellReadStart = reqCtx._metricsStore ? performance.now() : 0;
425
- try {
426
- cached = await store.getShell(key);
427
- } catch (error) {
428
- // A failing store read degrades to axis 1 (MISS), never a 500.
429
- reportCacheError(error, "cache-read", "[ShellServe] getShell");
430
- }
431
- if (reqCtx._metricsStore) {
432
- // Raw store outcome (pre-validity-gates), so a version-mismatch
433
- // lifecycle miss is still distinguishable from a store miss.
434
- appendMetric(
435
- reqCtx._metricsStore,
436
- "ppr:shell-read",
437
- shellReadStart,
438
- performance.now() - shellReadStart,
439
- undefined,
440
- cached ? "hit" : "miss",
441
- );
442
- }
443
- if (
444
- cached &&
445
- !cached.entry.navigationOnly &&
446
- isValidShellHit(cached.entry, ctx.version)
447
- ) {
448
- if (!hasIntactShellPayload(cached.entry)) {
449
- // Corrupt stored payload (undecodable prelude / unparseable
450
- // postponed): a store-layer fault worth a diagnostic, unlike the
451
- // silent version-mismatch lifecycle misses above. Degrade to MISS
452
- // — pprMiss below schedules the recapture that overwrites it.
453
- reportCacheError(
454
- new Error(
455
- `corrupt shell entry for "${key}": prelude/postponed failed ` +
456
- "the integrity check; serving axis 1 and recapturing",
457
- ),
458
- "cache-read",
459
- "[ShellServe] getShell",
460
- );
461
- } else {
462
- // Stale (SWR) hit: serve the stale shell now, recapture in the
463
- // background (stampede-guarded + backoff inside scheduleShellCapture).
464
- return serveHit(cached.entry, cached.shouldRevalidate);
465
- }
466
- }
467
- // Build-time shell read-through (producer B, #699): on a runtime
468
- // store MISS a Prerender+ppr route serves its `vite build`-baked
469
- // shell through the SAME serveShellHit. lookupBuildShell owns every
470
- // gate and fails to null (ordinary MISS path takes over); past
471
- // ppr.ttl the baked entry still serves while SWR recaptures — the
472
- // upgrade path from build entry to runtime entry.
473
- const buildHit = await lookupBuildShell(
474
- url,
475
- ctx.version,
476
- store,
477
- // Dev: no build manifest exists; producer B runs on demand via
478
- // the dev server's /__rsc_shell endpoint for PRERENDERED routes
479
- // only (production's exact candidate set). Folded away in
480
- // production builds (NODE_ENV is a compile-time constant).
481
- resolveDevShellLookup(reqCtx, pprConfig),
482
- reqCtx._searchParamsFilter,
483
- );
484
- if (buildHit) {
485
- // Past ppr.ttl: still serve the baked entry, recapture upgrades it.
486
- return serveHit(buildHit.entry, buildHit.stale);
487
- }
488
- // MISS (no entry, invalid reactVersion, or store read failure): axis 1
489
- // + a background capture scheduled once the response is known servable.
490
- pprMiss = { descriptor, ssrModule };
491
- }
492
- }
567
+ reqCtx,
568
+ handleStore,
569
+ ssrModule,
570
+ entry,
571
+ descriptor,
572
+ ),
573
+ );
574
+ return { kind: "serve", response };
575
+ }
576
+ }
577
+
578
+ // Build-time shell read-through (producer B, #699): on a runtime
579
+ // store MISS a Prerender+ppr route serves its `vite build`-baked
580
+ // shell through the SAME serve path. lookupBuildShell owns every
581
+ // gate and fails to null (ordinary MISS path takes over); past
582
+ // ppr.ttl the baked entry still serves while SWR recaptures — the
583
+ // upgrade path from build entry to runtime entry.
584
+ const buildHit = yield* step("build-shell-lookup", () =>
585
+ lookupBuildShell(
586
+ url,
587
+ ctx.version,
588
+ store,
589
+ // Dev: no build manifest exists; producer B runs on demand via
590
+ // the dev server's /__rsc_shell endpoint for PRERENDERED routes
591
+ // only (production's exact candidate set). Folded away in
592
+ // production builds (NODE_ENV is a compile-time constant).
593
+ resolveDevShellLookup(reqCtx, pprConfig),
594
+ reqCtx._searchParamsFilter,
595
+ ),
596
+ );
597
+ if (buildHit) {
598
+ // Past ppr.ttl: still serve the baked entry, recapture upgrades it.
599
+ if (buildHit.stale) {
600
+ yield* handoff("shell-recapture", () =>
601
+ scheduleShellCapture(
602
+ ctx,
603
+ request,
604
+ env,
605
+ url,
606
+ reqCtx,
607
+ ssrModule,
608
+ descriptor,
609
+ ),
610
+ );
493
611
  }
612
+ const response = yield* step("shell-hit", () =>
613
+ serveShellHit(
614
+ ctx,
615
+ request,
616
+ env,
617
+ url,
618
+ reqCtx,
619
+ handleStore,
620
+ ssrModule,
621
+ buildHit.entry,
622
+ descriptor,
623
+ ),
624
+ );
625
+ return { kind: "serve", response };
494
626
  }
495
627
 
628
+ // MISS (no entry, invalid reactVersion, or store read failure): axis 1
629
+ // + a background capture scheduled once the response is known servable.
630
+ return { kind: "miss", descriptor, ssrModule };
631
+ }
632
+
633
+ /**
634
+ * Match the request and assemble the RSC payload, or produce a control
635
+ * response (redirect, prerender collection) that ends the request plan.
636
+ */
637
+ function* preparePayloadPlan<TEnv>(
638
+ input: RequestRenderInput<TEnv>,
639
+ ): RoutinePlan<PreparedRender> {
640
+ const { ctx, request, env, url, isPartial, handleStore, nonce, reqCtx } =
641
+ input;
642
+
496
643
  if (isPartial) {
497
644
  // Partial render (navigation)
498
- const replay = await matchPartialWithPprReplay(
499
- ctx,
500
- request,
501
- env,
502
- url,
503
- reqCtx,
504
- nonce,
645
+ const replay = yield* step("match:ppr-replay", () =>
646
+ matchPartialAndRecordParams(ctx, request, env, url, reqCtx, nonce),
505
647
  );
506
648
  const result = replay.result;
507
- pprReplayStatus = replay.status;
508
- partialCaptureNeeded =
649
+ const pprReplayStatus = replay.status;
650
+ const partialCaptureNeeded =
509
651
  "captureNeeded" in replay && replay.captureNeeded === true;
510
- partialCaptureKey = "captureKey" in replay ? replay.captureKey : undefined;
652
+ const partialCaptureKey =
653
+ "captureKey" in replay ? replay.captureKey : undefined;
511
654
 
512
655
  if (!result) {
513
656
  // Fall back to full render
514
- const match = await ctx.router.match(request, { env });
515
- setRequestContextParams(match.params, match.routeName);
657
+ const match = yield* step("match:fallback", () =>
658
+ matchAndRecordParams(ctx, request, env),
659
+ );
516
660
 
517
661
  if (match.redirect) {
518
662
  // Partial request: use X-RSC-Redirect header so the client can
@@ -529,16 +673,22 @@ async function handleRscRenderingInner<TEnv>(
529
673
  serializePprReplayStatus(pprReplayStatus),
530
674
  );
531
675
  }
532
- return redirectResponse;
676
+ return { kind: "control", response: redirectResponse };
533
677
  }
534
678
 
535
- payload = buildFullPayload(match, ctx, url, reqCtx, handleStore);
536
- } else {
537
- setRequestContextParams(result.params, result.routeName);
538
-
539
- hasInterceptSlots = !!result.slots;
679
+ return {
680
+ kind: "payload",
681
+ payload: buildFullPayload(match, ctx, url, reqCtx, handleStore),
682
+ hasInterceptSlots: false,
683
+ pprReplayStatus,
684
+ partialCaptureNeeded,
685
+ partialCaptureKey,
686
+ };
687
+ }
540
688
 
541
- payload = {
689
+ return {
690
+ kind: "payload",
691
+ payload: {
542
692
  metadata: {
543
693
  pathname: url.pathname,
544
694
  // routerId is serialized on every payload (including within-session
@@ -558,6 +708,7 @@ async function handleRscRenderingInner<TEnv>(
558
708
  params: result.params,
559
709
  isPartial: true,
560
710
  slots: result.slots,
711
+ interceptTargets: result.interceptTargets,
561
712
  handles: handleStore.stream(),
562
713
  version: ctx.version,
563
714
  prefetchCacheTTL: ctx.router.prefetchCacheTTL,
@@ -566,62 +717,191 @@ async function handleRscRenderingInner<TEnv>(
566
717
  defaultPrefetch: ctx.router.defaultPrefetch,
567
718
  stateCookieName: ctx.router.resolvedStateCookieName,
568
719
  },
569
- };
570
- }
571
- } else {
572
- // Full render (initial page load)
573
- const match = await ctx.router.match(request, { env });
574
- setRequestContextParams(match.params, match.routeName);
720
+ },
721
+ hasInterceptSlots: !!result.slots,
722
+ pprReplayStatus,
723
+ partialCaptureNeeded,
724
+ partialCaptureKey,
725
+ };
726
+ }
575
727
 
576
- if (match.redirect) {
577
- return createResponseWithMergedHeaders(null, {
728
+ // Full render (initial page load)
729
+ const match = yield* step("match", () =>
730
+ matchAndRecordParams(ctx, request, env),
731
+ );
732
+
733
+ if (match.redirect) {
734
+ return {
735
+ kind: "control",
736
+ response: createResponseWithMergedHeaders(null, {
578
737
  status: 308,
579
738
  headers: { Location: match.redirect },
580
- });
581
- }
739
+ }),
740
+ };
741
+ }
582
742
 
583
- // Caching is now handled in router.match() via cache provider in request context
584
- // match.segments already contains cached or fresh segments as appropriate
743
+ // Caching is now handled in router.match() via cache provider in request context
744
+ // match.segments already contains cached or fresh segments as appropriate
745
+
746
+ if (url.searchParams.has("__prerender_collect")) {
747
+ const response = yield* step("prerender-collect", () =>
748
+ collectPrerenderArtifacts(match, handleStore),
749
+ );
750
+ return { kind: "control", response };
751
+ }
752
+
753
+ return {
754
+ kind: "payload",
755
+ payload: buildFullPayload(match, ctx, url, reqCtx, handleStore),
756
+ hasInterceptSlots: false,
757
+ partialCaptureNeeded: false,
758
+ };
759
+ }
760
+
761
+ /**
762
+ * PPR replay match that stamps params/routeName when a replay result exists.
763
+ * A null result records nothing — the fallback match records its own.
764
+ */
765
+ async function matchPartialAndRecordParams<TEnv>(
766
+ ctx: HandlerContext<TEnv>,
767
+ request: Request,
768
+ env: TEnv,
769
+ url: URL,
770
+ reqCtx: RequestContext<any>,
771
+ nonce: string | undefined,
772
+ ): Promise<Awaited<ReturnType<typeof matchPartialWithPprReplay<TEnv>>>> {
773
+ const replay = await matchPartialWithPprReplay(
774
+ ctx,
775
+ request,
776
+ env,
777
+ url,
778
+ reqCtx,
779
+ nonce,
780
+ );
781
+ if (replay.result) {
782
+ setRequestContextParams(replay.result.params, replay.result.routeName);
783
+ }
784
+ return replay;
785
+ }
786
+
787
+ /**
788
+ * Shell store read that degrades to null on failure (axis 1 MISS, never a 500)
789
+ * and records the raw `ppr:shell-read` outcome (pre-validity-gates, so a
790
+ * version-mismatch lifecycle miss stays distinguishable from a store miss).
791
+ */
792
+ async function readShellEntry<
793
+ TStore extends { getShell(key: string): Promise<unknown> },
794
+ >(
795
+ store: TStore,
796
+ key: string,
797
+ reqCtx: ReturnType<typeof getRequestContext>,
798
+ ): Promise<Awaited<ReturnType<TStore["getShell"]>> | null> {
799
+ let cached: Awaited<ReturnType<TStore["getShell"]>> | null = null;
800
+ const shellReadStart = reqCtx._metricsStore ? performance.now() : 0;
801
+ try {
802
+ // The constraint types the call as Promise<unknown>; the instantiated
803
+ // TStore carries the real entry type, so the assertion restores it.
804
+ cached = (await store.getShell(key)) as Awaited<
805
+ ReturnType<TStore["getShell"]>
806
+ >;
807
+ } catch (error) {
808
+ reportCacheError(error, "cache-read", "[ShellServe] getShell");
809
+ }
810
+ if (reqCtx._metricsStore) {
811
+ appendMetric(
812
+ reqCtx._metricsStore,
813
+ "ppr:shell-read",
814
+ shellReadStart,
815
+ performance.now() - shellReadStart,
816
+ undefined,
817
+ cached ? "hit" : "miss",
818
+ );
819
+ }
820
+ return cached;
821
+ }
585
822
 
586
- if (url.searchParams.has("__prerender_collect")) {
587
- // Build-time prerender collection: serialize segments and handle data
588
- // to JSON for storage as build artifacts. At runtime the worker
589
- // deserializes these and feeds them through the normal segment pipeline.
590
- const nonLoaderSegments = match.segments.filter(
591
- (s) => s.type !== "loader",
823
+ /**
824
+ * Dev Server-Timing mirror (issue #651): a capture completes AFTER its
825
+ * triggering response committed, so its outcome can only ride a LATER
826
+ * response's header. Read-and-clear keeps one capture = one report;
827
+ * dev-only (see takeCaptureDebugEventForTiming).
828
+ */
829
+ function mirrorPprServerTimingsForDev(
830
+ key: string,
831
+ reqCtx: ReturnType<typeof getRequestContext>,
832
+ ): void {
833
+ if (process.env.NODE_ENV !== "production" && reqCtx._metricsStore) {
834
+ const lastCapture = takeCaptureDebugEventForTiming(key);
835
+ if (lastCapture) {
836
+ appendMetric(
837
+ reqCtx._metricsStore,
838
+ "ppr:capture",
839
+ performance.now(),
840
+ lastCapture.attemptMs ?? 0,
841
+ undefined,
842
+ // attemptMs already rides as this entry's dur — drop it from desc.
843
+ describeShellCaptureEvent({ ...lastCapture, attemptMs: undefined }),
592
844
  );
593
- handleStore.seal();
594
- await handleStore.settled;
595
- const { serializeSegments } = await import("../cache/segment-codec.js");
596
- const serializedSegments = await serializeSegments(nonLoaderSegments);
597
- const handles: Record<string, Record<string, unknown[]>> = {};
598
- for (const seg of nonLoaderSegments) {
599
- const segHandles = handleStore.getDataForSegment(seg.id);
600
- if (Object.keys(segHandles).length > 0) {
601
- handles[seg.id] = segHandles;
602
- }
603
- }
604
- return new Response(
605
- JSON.stringify({
606
- segments: serializedSegments,
607
- handles,
608
- routeName: match.routeName,
609
- params: match.params,
610
- }),
611
- { headers: { "Content-Type": "application/json" } },
845
+ }
846
+ // Same mirror for the previous HIT's tail: its per-stage numbers
847
+ // (seed/match/handover/first-html/complete) finished after that
848
+ // response's headers were committed, so they ride THIS request's
849
+ // Server-Timing as `ppr:tail;dur=<complete ms>`.
850
+ const lastTail = takeShellTailTimingForServerTiming(key);
851
+ if (lastTail) {
852
+ appendMetric(
853
+ reqCtx._metricsStore,
854
+ "ppr:tail",
855
+ performance.now(),
856
+ lastTail.completeMs ?? 0,
857
+ undefined,
858
+ // completeMs already rides as this entry's dur — drop it from desc.
859
+ describeShellTailTiming({ ...lastTail, completeMs: undefined }),
612
860
  );
613
- } else {
614
- payload = buildFullPayload(match, ctx, url, reqCtx, handleStore);
615
861
  }
616
862
  }
863
+ }
617
864
 
618
- // For partial requests, include any server-set location state in the payload.
619
- // SSR (full page) requests ignore location state since there's no history.state
620
- // to write to on a fresh page load.
621
- if (isPartial && payload.metadata) {
622
- attachLocationStateIfPresent(payload);
865
+ /**
866
+ * Build-time prerender collection: serialize segments and handle data
867
+ * to JSON for storage as build artifacts. At runtime the worker
868
+ * deserializes these and feeds them through the normal segment pipeline.
869
+ */
870
+ async function collectPrerenderArtifacts<TEnv>(
871
+ match: Awaited<ReturnType<HandlerContext<TEnv>["router"]["match"]>>,
872
+ handleStore: ReturnType<typeof getRequestContext>["_handleStore"],
873
+ ): Promise<Response> {
874
+ const nonLoaderSegments = match.segments.filter((s) => s.type !== "loader");
875
+ handleStore.seal();
876
+ await handleStore.settled;
877
+ const { serializeSegments } = await import("../cache/segment-codec.js");
878
+ const serializedSegments = await serializeSegments(nonLoaderSegments);
879
+ const handles: Record<string, Record<string, unknown[]>> = {};
880
+ for (const seg of nonLoaderSegments) {
881
+ const segHandles = handleStore.getDataForSegment(seg.id);
882
+ if (Object.keys(segHandles).length > 0) {
883
+ handles[seg.id] = segHandles;
884
+ }
623
885
  }
886
+ return new Response(
887
+ JSON.stringify({
888
+ segments: serializedSegments,
889
+ handles,
890
+ routeName: match.routeName,
891
+ params: match.params,
892
+ }),
893
+ { headers: { "Content-Type": "application/json" } },
894
+ );
895
+ }
624
896
 
897
+ /** Assemble headers + tracking and run the foreground stage-driver render. */
898
+ function renderPreparedRscResponse<TEnv>(
899
+ input: RequestRenderInput<TEnv>,
900
+ prepared: Extract<PreparedRender, { kind: "payload" }>,
901
+ ): Promise<Response> {
902
+ const { ctx, request, env, url, isPartial, nonce, reqCtx, renderSpan } =
903
+ input;
904
+ const { payload, pprReplayStatus, hasInterceptSlots } = prepared;
625
905
  const metricsStore = reqCtx._metricsStore;
626
906
 
627
907
  const rscHeaders: Record<string, string> = {
@@ -661,8 +941,11 @@ async function handleRscRenderingInner<TEnv>(
661
941
  mode: isPartial ? ("partial" as const) : ("full" as const),
662
942
  routeKey: reqCtx._routeName,
663
943
  span: renderSpan,
944
+ onEvent:
945
+ reqCtx._activeRoutine &&
946
+ createRenderStageTraceBridge(reqCtx._activeRoutine),
664
947
  };
665
- const response = await renderRscResponse(
948
+ return renderRscResponse(
666
949
  {
667
950
  ctx,
668
951
  request,
@@ -686,65 +969,46 @@ async function handleRscRenderingInner<TEnv>(
686
969
  }),
687
970
  },
688
971
  );
972
+ }
689
973
 
690
- // --- Axis 2: PPR shell CAPTURE on MISS (background task; see design doc) ---
691
- // Capture only a 200 HTML document (a 404/error render is not a cacheable
692
- // shell). Capture does not flow through the HTTP pipeline — middleware never
693
- // re-runs (it already ran for this request; guarding is serve-time).
694
- if (pprMiss && !reqCtx._dynamic) {
695
- if (
696
- response.status === 200 &&
697
- (response.headers.get("content-type") ?? "").includes("text/html")
698
- ) {
699
- scheduleShellCapture(
974
+ /**
975
+ * Background capture for a navigation-only shell (partial replay reported
976
+ * captureNeeded). SSR setup is resolved lazily inside the capture because the
977
+ * partial request itself never touched HTML rendering.
978
+ */
979
+ function scheduleNavigationShellCapture<TEnv>(
980
+ input: RequestRenderInput<TEnv>,
981
+ partialCaptureKey: string | undefined,
982
+ ): void {
983
+ const { ctx, request, env, url, reqCtx } = input;
984
+ const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry)!;
985
+ const store = reqCtx._cacheStore!;
986
+ scheduleShellCapture(
987
+ ctx,
988
+ request,
989
+ env,
990
+ url,
991
+ reqCtx,
992
+ async (captureRequest, captureUrl) => {
993
+ const [ssrModule, streamMode] = await getSSRSetup(
700
994
  ctx,
701
- request,
995
+ captureRequest,
702
996
  env,
703
- url,
704
- reqCtx,
705
- pprMiss.ssrModule,
706
- pprMiss.descriptor,
997
+ captureUrl,
998
+ undefined,
707
999
  );
708
- }
709
- response.headers.set(SHELL_STATUS_HEADER, "MISS");
710
- }
711
-
712
- if (
713
- isPartial &&
714
- partialCaptureNeeded &&
715
- !reqCtx._dynamic &&
716
- response.status === 200
717
- ) {
718
- const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry)!;
719
- const store = reqCtx._cacheStore!;
720
- scheduleShellCapture(
1000
+ return streamMode === "allReady" ? null : ssrModule;
1001
+ },
1002
+ createShellCaptureDescriptor(
721
1003
  ctx,
722
- request,
723
- env,
724
- url,
725
- reqCtx,
726
- async (captureRequest, captureUrl) => {
727
- const [ssrModule, streamMode] = await getSSRSetup(
728
- ctx,
729
- captureRequest,
730
- env,
731
- captureUrl,
732
- undefined,
733
- );
734
- return streamMode === "allReady" ? null : ssrModule;
735
- },
736
- createShellCaptureDescriptor(
737
- ctx,
738
- partialCaptureKey ??
739
- buildNavigationShellKey(url, reqCtx._searchParamsFilter),
740
- pprConfig,
741
- store,
742
- true,
743
- ),
744
- );
745
- }
746
-
747
- return response;
1004
+ partialCaptureKey ??
1005
+ buildNavigationShellKey(url, reqCtx._searchParamsFilter),
1006
+ shellSearchSeed(url, reqCtx._searchParamsFilter),
1007
+ pprConfig,
1008
+ store,
1009
+ true,
1010
+ ),
1011
+ );
748
1012
  }
749
1013
 
750
1014
  /**
@@ -1257,6 +1521,9 @@ function serveShellHit(
1257
1521
  ssrModule.resumeShellHTML!(rscStream, {
1258
1522
  postponed: entry.postponed,
1259
1523
  nonce: undefined,
1524
+ // The shell key's own search — identical to the capture seed for
1525
+ // this key, so the resume tree matches the captured tree.
1526
+ search: shellSearchSeed(url, reqCtx._searchParamsFilter),
1260
1527
  }),
1261
1528
  );
1262
1529
  };