@timber-js/app 0.2.0-alpha.208 → 0.2.0-alpha.209

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 (520) hide show
  1. package/dist/_chunks/{primitives-DLAnvsrk.js → actions-BerlqoXA.js} +640 -410
  2. package/dist/_chunks/actions-BerlqoXA.js.map +1 -0
  3. package/dist/_chunks/{als-registry-C6kcfprT.js → als-registry-DaxkVjt5.js} +6 -2
  4. package/dist/_chunks/als-registry-DaxkVjt5.js.map +1 -0
  5. package/dist/_chunks/{build-manifest-DTmSGLRz.js → build-manifest-DWppEdLB.js} +2 -51
  6. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  7. package/dist/_chunks/{build-output-helper-9dqCv1pZ.js → build-output-helper-RV_BRcF1.js} +50 -53
  8. package/dist/_chunks/build-output-helper-RV_BRcF1.js.map +1 -0
  9. package/dist/_chunks/{cache-api-CUD9Ezaq.js → cache-api-CR23J_NC.js} +64 -32
  10. package/dist/_chunks/cache-api-CR23J_NC.js.map +1 -0
  11. package/dist/_chunks/{chains-B4bgOl2g.js → chains-CpFg56UB.js} +2 -2
  12. package/dist/_chunks/{chains-B4bgOl2g.js.map → chains-CpFg56UB.js.map} +1 -1
  13. package/dist/_chunks/{cli-check-G8o30ldg.js → cli-check-C6Ev6wBO.js} +11 -52
  14. package/dist/_chunks/cli-check-C6Ev6wBO.js.map +1 -0
  15. package/dist/_chunks/cli-context-By7k2xVo.js +70 -0
  16. package/dist/_chunks/cli-context-By7k2xVo.js.map +1 -0
  17. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js → cli-schema-sync-CbT2AUUI.js} +3 -3
  18. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js.map → cli-schema-sync-CbT2AUUI.js.map} +1 -1
  19. package/dist/_chunks/{cloudflare-BFb__LYG.js → cloudflare-Byxl8FWP.js} +96 -53
  20. package/dist/_chunks/{cloudflare-BFb__LYG.js.map → cloudflare-Byxl8FWP.js.map} +1 -1
  21. package/dist/_chunks/{convention-lint-5KzoMg_A.js → convention-lint-jKTwKwPe.js} +21 -6
  22. package/dist/_chunks/convention-lint-jKTwKwPe.js.map +1 -0
  23. package/dist/_chunks/{dev-server-BzBxgYAV.js → dev-server-C4WZdB7L.js} +15 -167
  24. package/dist/_chunks/dev-server-C4WZdB7L.js.map +1 -0
  25. package/dist/_chunks/{error-boundary-BrHmG-2X.js → error-boundary-tA7kVfs4.js} +84 -104
  26. package/dist/_chunks/error-boundary-tA7kVfs4.js.map +1 -0
  27. package/dist/_chunks/{fs-identity-D7vb6GdI.js → fs-identity-BRKuL215.js} +3 -4
  28. package/dist/_chunks/fs-identity-BRKuL215.js.map +1 -0
  29. package/dist/_chunks/{graph-cache-CP4GEmf9.js → graph-cache-CYiUS2aS.js} +4 -5
  30. package/dist/_chunks/graph-cache-CYiUS2aS.js.map +1 -0
  31. package/dist/_chunks/{json-lossy-check-ClNvBM_3.js → json-lossy-check-ip0Qi0MT.js} +6 -3
  32. package/dist/_chunks/json-lossy-check-ip0Qi0MT.js.map +1 -0
  33. package/dist/_chunks/{live-graph-Bm5WTvcr.js → live-graph-Dv-JJCZw.js} +3 -3
  34. package/dist/_chunks/{live-graph-Bm5WTvcr.js.map → live-graph-Dv-JJCZw.js.map} +1 -1
  35. package/dist/_chunks/{logger-k2DQ4EUf.js → logger-DiDt5ppH.js} +192 -51
  36. package/dist/_chunks/logger-DiDt5ppH.js.map +1 -0
  37. package/dist/_chunks/{navigation-root-mHSK9psY.js → navigation-root-BQfo1-kG.js} +2 -2
  38. package/dist/_chunks/{navigation-root-mHSK9psY.js.map → navigation-root-BQfo1-kG.js.map} +1 -1
  39. package/dist/_chunks/{plugin-context-8idfR3UZ.js → plugin-context-BPBPc3lL.js} +28 -4
  40. package/dist/_chunks/plugin-context-BPBPc3lL.js.map +1 -0
  41. package/dist/_chunks/{poison-scan-DG5eI2_z.js → poison-scan-CpeT6_OJ.js} +2 -2
  42. package/dist/_chunks/{poison-scan-DG5eI2_z.js.map → poison-scan-CpeT6_OJ.js.map} +1 -1
  43. package/dist/_chunks/render-timeout-DOf_BBcO.js +46 -0
  44. package/dist/_chunks/render-timeout-DOf_BBcO.js.map +1 -0
  45. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js → rsc-payload-path-dffcs4jp.js} +9 -3
  46. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js.map → rsc-payload-path-dffcs4jp.js.map} +1 -1
  47. package/dist/_chunks/{scanner-BQ5sPIJ7.js → scanner-Bw0oq1HB.js} +2 -2
  48. package/dist/_chunks/{scanner-BQ5sPIJ7.js.map → scanner-Bw0oq1HB.js.map} +1 -1
  49. package/dist/_chunks/{navigation-context-D0TU0Jog.js → segment-context-xtPUGfdq.js} +36 -34
  50. package/dist/_chunks/segment-context-xtPUGfdq.js.map +1 -0
  51. package/dist/_chunks/{singleflight-2lUWfcAk.js → singleflight-BeVMMKi0.js} +4 -3
  52. package/dist/_chunks/{singleflight-2lUWfcAk.js.map → singleflight-BeVMMKi0.js.map} +1 -1
  53. package/dist/_chunks/{sizeof-lXffQ1Vr.js → sizeof-UwzwB1uM.js} +3 -2
  54. package/dist/_chunks/sizeof-UwzwB1uM.js.map +1 -0
  55. package/dist/_chunks/ssr-data-nA3I70_n.js +49 -0
  56. package/dist/_chunks/ssr-data-nA3I70_n.js.map +1 -0
  57. package/dist/_chunks/{state-FippDgxN.js → state-BhNGPsdi.js} +6 -8
  58. package/dist/_chunks/state-BhNGPsdi.js.map +1 -0
  59. package/dist/_chunks/{status-page-marker-CNbpUOPB.js → status-page-marker-gaihi0KZ.js} +53 -20
  60. package/dist/_chunks/status-page-marker-gaihi0KZ.js.map +1 -0
  61. package/dist/_chunks/{walkers-CN2N_bA-.js → walkers-BXExhzzk.js} +2 -2
  62. package/dist/_chunks/{walkers-CN2N_bA-.js.map → walkers-BXExhzzk.js.map} +1 -1
  63. package/dist/_chunks/write-file-atomic-D1qWqHb4.js +32 -0
  64. package/dist/_chunks/write-file-atomic-D1qWqHb4.js.map +1 -0
  65. package/dist/adapters/build-output-helper.d.ts +7 -7
  66. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  67. package/dist/adapters/canonicalize-module.d.ts +8 -0
  68. package/dist/adapters/canonicalize-module.d.ts.map +1 -0
  69. package/dist/adapters/cloudflare-dev.js +1 -1
  70. package/dist/adapters/cloudflare-kv-cache.js +2 -2
  71. package/dist/adapters/cloudflare.d.ts +30 -8
  72. package/dist/adapters/cloudflare.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare.js +2 -2
  74. package/dist/adapters/compress-module.d.ts +8 -0
  75. package/dist/adapters/compress-module.d.ts.map +1 -1
  76. package/dist/adapters/fs-identity.d.ts +2 -3
  77. package/dist/adapters/fs-identity.d.ts.map +1 -1
  78. package/dist/adapters/nitro-presets.d.ts +0 -6
  79. package/dist/adapters/nitro-presets.d.ts.map +1 -1
  80. package/dist/adapters/nitro-preview.d.ts +43 -11
  81. package/dist/adapters/nitro-preview.d.ts.map +1 -1
  82. package/dist/adapters/nitro.d.ts +1 -13
  83. package/dist/adapters/nitro.d.ts.map +1 -1
  84. package/dist/adapters/nitro.js +291 -176
  85. package/dist/adapters/nitro.js.map +1 -1
  86. package/dist/adapters/shared.d.ts +7 -2
  87. package/dist/adapters/shared.d.ts.map +1 -1
  88. package/dist/adapters/types.d.ts +105 -21
  89. package/dist/adapters/types.d.ts.map +1 -1
  90. package/dist/adapters/types.js +0 -0
  91. package/dist/analyze/crawl-entry.js +3 -3
  92. package/dist/analyze/graph-cache.d.ts.map +1 -1
  93. package/dist/analyze/graph-command.js +4 -4
  94. package/dist/cache/index.js +2 -2
  95. package/dist/cache/json-lossy-check.d.ts.map +1 -1
  96. package/dist/cache/singleflight.d.ts.map +1 -1
  97. package/dist/cache/sizeof.d.ts.map +1 -1
  98. package/dist/cache/stores/memory.js +1 -1
  99. package/dist/cache/tag-aware-handler.d.ts.map +1 -1
  100. package/dist/cdn/workers-cache-purge.js +1 -1
  101. package/dist/cli-check.d.ts +7 -37
  102. package/dist/cli-check.d.ts.map +1 -1
  103. package/dist/cli-context.d.ts +54 -0
  104. package/dist/cli-context.d.ts.map +1 -0
  105. package/dist/cli.d.ts +9 -9
  106. package/dist/cli.d.ts.map +1 -1
  107. package/dist/cli.js +20 -24
  108. package/dist/cli.js.map +1 -1
  109. package/dist/client/browser-dev.d.ts +1 -1
  110. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  111. package/dist/client/browser-entry/hydrate.d.ts +19 -29
  112. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  113. package/dist/client/browser-entry/index.d.ts +7 -7
  114. package/dist/client/browser-entry/post-hydration.d.ts +6 -9
  115. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  116. package/dist/client/browser-entry/router-init.d.ts +6 -11
  117. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  118. package/dist/client/error-boundary.d.ts +4 -3
  119. package/dist/client/error-boundary.d.ts.map +1 -1
  120. package/dist/client/error-boundary.js +1 -1
  121. package/dist/client/error-reconstituter.d.ts +3 -9
  122. package/dist/client/error-reconstituter.d.ts.map +1 -1
  123. package/dist/client/history.d.ts +12 -11
  124. package/dist/client/history.d.ts.map +1 -1
  125. package/dist/client/index.d.ts +0 -1
  126. package/dist/client/index.d.ts.map +1 -1
  127. package/dist/client/index.js +5 -6
  128. package/dist/client/index.js.map +1 -1
  129. package/dist/client/internal.d.ts +3 -3
  130. package/dist/client/internal.d.ts.map +1 -1
  131. package/dist/client/internal.js +68 -104
  132. package/dist/client/internal.js.map +1 -1
  133. package/dist/client/navigation-commit.d.ts +16 -7
  134. package/dist/client/navigation-commit.d.ts.map +1 -1
  135. package/dist/client/navigation-context.d.ts +3 -5
  136. package/dist/client/navigation-context.d.ts.map +1 -1
  137. package/dist/client/react-root.d.ts +3 -2
  138. package/dist/client/react-root.d.ts.map +1 -1
  139. package/dist/client/router-pipeline.d.ts +1 -6
  140. package/dist/client/router-pipeline.d.ts.map +1 -1
  141. package/dist/client/router-types.d.ts +45 -39
  142. package/dist/client/router-types.d.ts.map +1 -1
  143. package/dist/client/router-url.d.ts +24 -0
  144. package/dist/client/router-url.d.ts.map +1 -0
  145. package/dist/client/router.d.ts.map +1 -1
  146. package/dist/client/rsc-fetch.d.ts +8 -4
  147. package/dist/client/rsc-fetch.d.ts.map +1 -1
  148. package/dist/client/ssr-data.d.ts +18 -64
  149. package/dist/client/ssr-data.d.ts.map +1 -1
  150. package/dist/client/state.d.ts +2 -5
  151. package/dist/client/state.d.ts.map +1 -1
  152. package/dist/client/use-pathname.d.ts +1 -1
  153. package/dist/config-types.d.ts +2 -1
  154. package/dist/config-types.d.ts.map +1 -1
  155. package/dist/config-validation.d.ts.map +1 -1
  156. package/dist/cookies/index.js +1 -1
  157. package/dist/dev-tools/dev-page-shell.d.ts +17 -0
  158. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
  159. package/dist/dev-tools/index.d.ts +1 -1
  160. package/dist/dev-tools/index.d.ts.map +1 -1
  161. package/dist/dev-tools/instrumentation.d.ts +17 -2
  162. package/dist/dev-tools/instrumentation.d.ts.map +1 -1
  163. package/dist/dev-tools/overlay.d.ts +6 -27
  164. package/dist/dev-tools/overlay.d.ts.map +1 -1
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +531 -373
  167. package/dist/index.js.map +1 -1
  168. package/dist/plugin-context.d.ts +26 -40
  169. package/dist/plugin-context.d.ts.map +1 -1
  170. package/dist/plugins/build-manifest.d.ts.map +1 -1
  171. package/dist/plugins/build-report.d.ts +15 -2
  172. package/dist/plugins/build-report.d.ts.map +1 -1
  173. package/dist/plugins/dev-server.d.ts.map +1 -1
  174. package/dist/plugins/entries.d.ts.map +1 -1
  175. package/dist/plugins/fonts.d.ts +19 -1
  176. package/dist/plugins/fonts.d.ts.map +1 -1
  177. package/dist/plugins/post-build.d.ts +110 -0
  178. package/dist/plugins/post-build.d.ts.map +1 -0
  179. package/dist/plugins/prebuilt-capture.d.ts +11 -4
  180. package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
  181. package/dist/plugins/prebuilt.d.ts +17 -1
  182. package/dist/plugins/prebuilt.d.ts.map +1 -1
  183. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  184. package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
  185. package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
  186. package/dist/plugins/shims.d.ts.map +1 -1
  187. package/dist/plugins/static-build.d.ts +32 -9
  188. package/dist/plugins/static-build.d.ts.map +1 -1
  189. package/dist/routing/codegen-write.d.ts +0 -9
  190. package/dist/routing/codegen-write.d.ts.map +1 -1
  191. package/dist/routing/index.js +2 -2
  192. package/dist/routing/segment-codegen.d.ts.map +1 -1
  193. package/dist/server/access-gate.d.ts.map +1 -1
  194. package/dist/server/action-handler.d.ts +5 -4
  195. package/dist/server/action-handler.d.ts.map +1 -1
  196. package/dist/server/actions.d.ts +46 -7
  197. package/dist/server/actions.d.ts.map +1 -1
  198. package/dist/server/als-registry.d.ts +58 -5
  199. package/dist/server/als-registry.d.ts.map +1 -1
  200. package/dist/server/children-interception.d.ts.map +1 -1
  201. package/dist/server/cookie-context.d.ts +2 -23
  202. package/dist/server/cookie-context.d.ts.map +1 -1
  203. package/dist/server/csp-nonce.d.ts +0 -9
  204. package/dist/server/csp-nonce.d.ts.map +1 -1
  205. package/dist/server/csrf.d.ts +27 -4
  206. package/dist/server/csrf.d.ts.map +1 -1
  207. package/dist/server/debug.d.ts +0 -1
  208. package/dist/server/debug.d.ts.map +1 -1
  209. package/dist/server/default-logger.d.ts +2 -1
  210. package/dist/server/default-logger.d.ts.map +1 -1
  211. package/dist/server/deny-boundary.d.ts +12 -6
  212. package/dist/server/deny-boundary.d.ts.map +1 -1
  213. package/dist/server/deny-renderer.d.ts +2 -2
  214. package/dist/server/deny-renderer.d.ts.map +1 -1
  215. package/dist/server/error-boundary-wrapper.d.ts +7 -3
  216. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  217. package/dist/server/fallback-error.d.ts +9 -2
  218. package/dist/server/fallback-error.d.ts.map +1 -1
  219. package/dist/server/head-response.d.ts +4 -4
  220. package/dist/server/html-injectors.d.ts.map +1 -1
  221. package/dist/server/index.d.ts +0 -1
  222. package/dist/server/index.d.ts.map +1 -1
  223. package/dist/server/index.js +3 -4
  224. package/dist/server/index.js.map +1 -1
  225. package/dist/server/instrumentation.d.ts +10 -3
  226. package/dist/server/instrumentation.d.ts.map +1 -1
  227. package/dist/server/internal.d.ts +1 -4
  228. package/dist/server/internal.d.ts.map +1 -1
  229. package/dist/server/internal.js +961 -581
  230. package/dist/server/internal.js.map +1 -1
  231. package/dist/server/json-status-response.d.ts +34 -0
  232. package/dist/server/json-status-response.d.ts.map +1 -0
  233. package/dist/server/logger.d.ts +26 -0
  234. package/dist/server/logger.d.ts.map +1 -1
  235. package/dist/server/param-coercion.d.ts +11 -6
  236. package/dist/server/param-coercion.d.ts.map +1 -1
  237. package/dist/server/pipeline-helpers.d.ts +95 -7
  238. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  239. package/dist/server/pipeline-interception.d.ts +11 -0
  240. package/dist/server/pipeline-interception.d.ts.map +1 -1
  241. package/dist/server/pipeline-outcome.d.ts +11 -1
  242. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  243. package/dist/server/pipeline-phases.d.ts +2 -2
  244. package/dist/server/pipeline-phases.d.ts.map +1 -1
  245. package/dist/server/pipeline.d.ts +23 -35
  246. package/dist/server/pipeline.d.ts.map +1 -1
  247. package/dist/server/prebuilt/capture-render.d.ts +25 -0
  248. package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
  249. package/dist/server/prebuilt/capture-routes.d.ts +37 -0
  250. package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
  251. package/dist/server/prebuilt/capture-state.d.ts +79 -35
  252. package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
  253. package/dist/server/prebuilt/lifetime.d.ts +38 -0
  254. package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
  255. package/dist/server/prebuilt/slots.d.ts +7 -0
  256. package/dist/server/prebuilt/slots.d.ts.map +1 -1
  257. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
  258. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  259. package/dist/server/prebuilt-runtime.d.ts.map +1 -1
  260. package/dist/server/primitives.d.ts +6 -81
  261. package/dist/server/primitives.d.ts.map +1 -1
  262. package/dist/server/react-cache-bridge.d.ts +59 -0
  263. package/dist/server/react-cache-bridge.d.ts.map +1 -0
  264. package/dist/server/react-cache-scope.d.ts +49 -0
  265. package/dist/server/react-cache-scope.d.ts.map +1 -0
  266. package/dist/server/render-timeout.d.ts +15 -0
  267. package/dist/server/render-timeout.d.ts.map +1 -1
  268. package/dist/server/render-utils.d.ts +9 -0
  269. package/dist/server/render-utils.d.ts.map +1 -1
  270. package/dist/server/request-context.d.ts +26 -5
  271. package/dist/server/request-context.d.ts.map +1 -1
  272. package/dist/server/route-element-builder.d.ts.map +1 -1
  273. package/dist/server/route-handler.d.ts.map +1 -1
  274. package/dist/server/route-matcher.d.ts +7 -0
  275. package/dist/server/route-matcher.d.ts.map +1 -1
  276. package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
  277. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
  278. package/dist/server/rsc-entry/api-handler.d.ts +7 -0
  279. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  280. package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
  281. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  282. package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
  283. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  284. package/dist/server/rsc-entry/helpers.d.ts +0 -1
  285. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  286. package/dist/server/rsc-entry/index.d.ts +5 -15
  287. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  288. package/dist/server/rsc-entry/render-route.d.ts +5 -6
  289. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  290. package/dist/server/rsc-entry/render-signals.d.ts +65 -0
  291. package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
  292. package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
  293. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  294. package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
  295. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  296. package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
  297. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  298. package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
  299. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  300. package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
  301. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  302. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
  303. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
  304. package/dist/server/signal-identity.d.ts +43 -0
  305. package/dist/server/signal-identity.d.ts.map +1 -0
  306. package/dist/server/slot-resolver.d.ts +4 -3
  307. package/dist/server/slot-resolver.d.ts.map +1 -1
  308. package/dist/server/slot-subtree-contain.d.ts.map +1 -1
  309. package/dist/server/ssr-bridge-types.d.ts +91 -53
  310. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  311. package/dist/server/ssr-entry.d.ts +8 -5
  312. package/dist/server/ssr-entry.d.ts.map +1 -1
  313. package/dist/server/ssr-render.d.ts +26 -40
  314. package/dist/server/ssr-render.d.ts.map +1 -1
  315. package/dist/server/ssr-wrappers.d.ts +1 -1
  316. package/dist/server/static-generator.d.ts.map +1 -1
  317. package/dist/server/stream-utils.d.ts +12 -0
  318. package/dist/server/stream-utils.d.ts.map +1 -1
  319. package/dist/server/tracing.d.ts +12 -16
  320. package/dist/server/tracing.d.ts.map +1 -1
  321. package/dist/server/types.d.ts +1 -1
  322. package/dist/server/version-skew.d.ts +3 -3
  323. package/dist/shared/csrf-reject.d.ts +16 -0
  324. package/dist/shared/csrf-reject.d.ts.map +1 -0
  325. package/dist/shared/error-digest.d.ts +28 -0
  326. package/dist/shared/error-digest.d.ts.map +1 -0
  327. package/dist/shared/payload-root.d.ts +11 -10
  328. package/dist/shared/payload-root.d.ts.map +1 -1
  329. package/dist/shared/rsc-payload-path.d.ts +6 -0
  330. package/dist/shared/rsc-payload-path.d.ts.map +1 -1
  331. package/dist/utils/write-file-atomic.d.ts +17 -0
  332. package/dist/utils/write-file-atomic.d.ts.map +1 -0
  333. package/docs/api/30-api-server.mdx +17 -14
  334. package/docs/api/32-api-cache.mdx +51 -23
  335. package/docs/api/34-api-config.mdx +34 -6
  336. package/docs/api/36-cli.mdx +11 -1
  337. package/docs/learn/03-fetching-data.mdx +17 -1
  338. package/docs/learn/04-access-control.mdx +1 -1
  339. package/docs/learn/10-caching.mdx +29 -11
  340. package/docs/learn/11-middleware.mdx +8 -2
  341. package/docs/learn/12-error-handling.mdx +6 -1
  342. package/package.json +5 -1
  343. package/src/adapters/build-output-helper.ts +55 -53
  344. package/src/adapters/canonicalize-module.ts +29 -0
  345. package/src/adapters/cloudflare.ts +105 -63
  346. package/src/adapters/compress-module.ts +16 -5
  347. package/src/adapters/fs-identity.ts +2 -3
  348. package/src/adapters/nitro-presets.ts +0 -15
  349. package/src/adapters/nitro-preview.ts +272 -136
  350. package/src/adapters/nitro.ts +119 -82
  351. package/src/adapters/shared.ts +23 -14
  352. package/src/adapters/types.ts +110 -21
  353. package/src/analyze/graph-cache.ts +3 -4
  354. package/src/cache/json-lossy-check.ts +3 -9
  355. package/src/cache/singleflight.ts +5 -2
  356. package/src/cache/sizeof.ts +3 -1
  357. package/src/cache/tag-aware-handler.ts +43 -26
  358. package/src/cli-check.ts +8 -98
  359. package/src/cli-context.ts +119 -0
  360. package/src/cli.ts +19 -28
  361. package/src/client/browser-dev.ts +1 -1
  362. package/src/client/browser-entry/action-dispatch.ts +26 -4
  363. package/src/client/browser-entry/hydrate.ts +53 -58
  364. package/src/client/browser-entry/index.ts +16 -27
  365. package/src/client/browser-entry/post-hydration.ts +6 -40
  366. package/src/client/browser-entry/router-init.ts +66 -84
  367. package/src/client/error-boundary.tsx +9 -41
  368. package/src/client/error-reconstituter.tsx +10 -5
  369. package/src/client/history.ts +18 -21
  370. package/src/client/index.ts +0 -1
  371. package/src/client/internal.ts +2 -7
  372. package/src/client/navigation-commit.ts +35 -18
  373. package/src/client/navigation-context.ts +3 -39
  374. package/src/client/react-root.ts +3 -2
  375. package/src/client/router-pipeline.ts +65 -128
  376. package/src/client/router-types.ts +46 -44
  377. package/src/client/router-url.ts +32 -0
  378. package/src/client/router.ts +43 -22
  379. package/src/client/rsc-fetch.ts +117 -155
  380. package/src/client/ssr-data.ts +19 -80
  381. package/src/client/state.ts +2 -9
  382. package/src/client/use-pathname.ts +1 -1
  383. package/src/config-types.ts +2 -1
  384. package/src/config-validation.ts +2 -1
  385. package/src/dev-tools/dev-page-shell.ts +18 -0
  386. package/src/dev-tools/index.ts +0 -2
  387. package/src/dev-tools/instrumentation.ts +50 -2
  388. package/src/dev-tools/overlay.ts +8 -238
  389. package/src/index.ts +24 -14
  390. package/src/plugin-context.ts +39 -40
  391. package/src/plugins/build-manifest.ts +4 -11
  392. package/src/plugins/build-report.ts +70 -70
  393. package/src/plugins/dev-server.ts +24 -44
  394. package/src/plugins/entries.ts +2 -1
  395. package/src/plugins/fonts.ts +35 -7
  396. package/src/plugins/post-build.ts +327 -0
  397. package/src/plugins/prebuilt-capture.ts +28 -32
  398. package/src/plugins/prebuilt.ts +54 -39
  399. package/src/plugins/prerender-sugar.ts +0 -4
  400. package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
  401. package/src/plugins/shims.ts +1 -0
  402. package/src/plugins/static-build.ts +42 -74
  403. package/src/routing/codegen-write.ts +25 -3
  404. package/src/routing/segment-codegen.ts +3 -2
  405. package/src/rsc-runtime/vendor-types.d.ts +8 -0
  406. package/src/server/access-gate.tsx +2 -1
  407. package/src/server/action-client.ts +1 -1
  408. package/src/server/action-handler.ts +253 -110
  409. package/src/server/actions.ts +73 -25
  410. package/src/server/als-registry.ts +73 -5
  411. package/src/server/chain-url-parts.ts +1 -1
  412. package/src/server/children-interception.ts +2 -1
  413. package/src/server/cookie-context.ts +18 -48
  414. package/src/server/csp-nonce.ts +0 -12
  415. package/src/server/csrf.ts +140 -8
  416. package/src/server/debug.ts +0 -1
  417. package/src/server/default-logger.ts +2 -1
  418. package/src/server/deny-boundary.ts +25 -13
  419. package/src/server/deny-renderer.ts +30 -97
  420. package/src/server/error-boundary-wrapper.ts +7 -3
  421. package/src/server/fallback-error.ts +26 -11
  422. package/src/server/flight-scripts.ts +1 -1
  423. package/src/server/head-response.ts +4 -4
  424. package/src/server/html-injector-core.ts +2 -2
  425. package/src/server/html-injectors.ts +2 -4
  426. package/src/server/index.ts +0 -4
  427. package/src/server/instrumentation.ts +10 -3
  428. package/src/server/internal.ts +1 -6
  429. package/src/server/json-status-response.ts +105 -0
  430. package/src/server/logger.ts +39 -3
  431. package/src/server/param-coercion.ts +15 -12
  432. package/src/server/pipeline-helpers.ts +257 -12
  433. package/src/server/pipeline-interception.ts +133 -0
  434. package/src/server/pipeline-outcome.ts +103 -31
  435. package/src/server/pipeline-phases.ts +127 -237
  436. package/src/server/pipeline.ts +204 -207
  437. package/src/server/prebuilt/capture-render.ts +118 -0
  438. package/src/server/prebuilt/capture-routes.ts +104 -0
  439. package/src/server/prebuilt/capture-state.ts +155 -48
  440. package/src/server/prebuilt/lifetime.ts +151 -0
  441. package/src/server/prebuilt/slots.ts +14 -2
  442. package/src/server/prebuilt/synthetic-store.ts +3 -0
  443. package/src/server/prebuilt-builder.ts +30 -320
  444. package/src/server/prebuilt-runtime.ts +125 -129
  445. package/src/server/primitives.ts +8 -168
  446. package/src/server/react-cache-bridge.ts +124 -0
  447. package/src/server/react-cache-scope.ts +104 -0
  448. package/src/server/render-timeout.ts +20 -0
  449. package/src/server/render-utils.ts +11 -1
  450. package/src/server/request-context.ts +36 -9
  451. package/src/server/route-element-builder.ts +11 -6
  452. package/src/server/route-handler.ts +36 -23
  453. package/src/server/route-matcher.ts +15 -1
  454. package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
  455. package/src/server/rsc-entry/api-handler.ts +27 -103
  456. package/src/server/rsc-entry/deny-fallback.ts +93 -26
  457. package/src/server/rsc-entry/error-renderer.ts +39 -91
  458. package/src/server/rsc-entry/helpers.ts +2 -4
  459. package/src/server/rsc-entry/index.ts +64 -58
  460. package/src/server/rsc-entry/render-route.ts +15 -80
  461. package/src/server/rsc-entry/render-signals.ts +108 -0
  462. package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
  463. package/src/server/rsc-entry/rsc-payload.ts +28 -61
  464. package/src/server/rsc-entry/rsc-stream.ts +113 -213
  465. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  466. package/src/server/rsc-entry/ssr-renderer.ts +182 -263
  467. package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
  468. package/src/server/signal-identity.ts +112 -0
  469. package/src/server/slot-resolver.ts +18 -18
  470. package/src/server/slot-subtree-contain.ts +2 -1
  471. package/src/server/ssr-bridge-types.ts +92 -56
  472. package/src/server/ssr-entry.ts +87 -111
  473. package/src/server/ssr-render.ts +55 -64
  474. package/src/server/ssr-wrappers.tsx +2 -2
  475. package/src/server/static-generator.ts +7 -42
  476. package/src/server/static-not-found.ts +3 -3
  477. package/src/server/stream-utils.ts +51 -0
  478. package/src/server/tracing.ts +58 -75
  479. package/src/server/types.ts +1 -1
  480. package/src/server/version-skew.ts +5 -5
  481. package/src/shared/csrf-reject.ts +15 -0
  482. package/src/shared/error-digest.ts +46 -0
  483. package/src/shared/payload-root.ts +11 -10
  484. package/src/shared/rsc-payload-path.ts +8 -1
  485. package/src/utils/write-file-atomic.ts +32 -0
  486. package/dist/_chunks/actions-jNrXdzgs.js +0 -346
  487. package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
  488. package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
  489. package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
  490. package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
  491. package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
  492. package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
  493. package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
  494. package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
  495. package/dist/_chunks/error-boundary-BrHmG-2X.js.map +0 -1
  496. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
  497. package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
  498. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
  499. package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
  500. package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
  501. package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
  502. package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
  503. package/dist/_chunks/segment-context-D9_89u34.js +0 -34
  504. package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
  505. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
  506. package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
  507. package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
  508. package/dist/_chunks/state-FippDgxN.js.map +0 -1
  509. package/dist/_chunks/status-page-marker-CNbpUOPB.js.map +0 -1
  510. package/dist/client/types.d.ts +0 -14
  511. package/dist/client/types.d.ts.map +0 -1
  512. package/dist/plugins/adapter-build.d.ts +0 -38
  513. package/dist/plugins/adapter-build.d.ts.map +0 -1
  514. package/dist/server/asset-headers.d.ts +0 -32
  515. package/dist/server/asset-headers.d.ts.map +0 -1
  516. package/dist/server/dev-source-map.d.ts +0 -22
  517. package/dist/server/dev-source-map.d.ts.map +0 -1
  518. package/src/client/types.ts +0 -21
  519. package/src/server/asset-headers.ts +0 -59
  520. package/src/server/dev-source-map.ts +0 -31
@@ -33,15 +33,15 @@ import {
33
33
  nodeReadableToWeb,
34
34
  useNodeStreams,
35
35
  buildSsrResponse,
36
+ type SsrStreamOptions,
36
37
  } from './ssr-render.ts';
37
- import { logRenderError } from './logger.ts';
38
- import { SsrStreamError } from './primitives.ts';
38
+ import { SsrStreamError } from './signal-identity.ts';
39
39
  import { createBufferedTransformStream, injectHead, injectRscPayload } from './html-injectors.ts';
40
40
  import { wrapSsrElement } from './ssr-wrappers.tsx';
41
41
  import { withSpan } from './tracing.ts';
42
42
  import { registerSsrDataProvider, type SsrData } from '../client/ssr-data.ts';
43
43
  import { splitPayloadRoot } from '../shared/payload-root.ts';
44
- import type { NavContext } from './ssr-bridge-types.ts';
44
+ import type { NavContext, SsrRenderResult } from './ssr-bridge-types.ts';
45
45
 
46
46
  // Pre-import Node.js stream modules at module load time — not per-request.
47
47
  // Dynamic imports of node-stream-transforms and node:stream/promises were
@@ -99,34 +99,35 @@ registerSsrDataProvider(() => ssrDataAls.getStore());
99
99
  * 2. Render the decoded tree to HTML via renderToReadableStream (streaming)
100
100
  * 3. Wait for onShellReady before flushing (handled by renderSsrStream)
101
101
  * 4. Inject metadata into <head> and client scripts before </body>
102
- * 5. Return Response with navContext.statusCode and navContext.responseHeaders
102
+ * 5. Return the Response (navContext.statusCode, navContext.responseHeaders)
103
+ * with the SSR sub-phase timings and whether Fizz allReady settled
104
+ * within the hold window
103
105
  *
104
106
  * The RSC stream is piped progressively — not buffered. For deny() outside
105
107
  * Suspense, the RSC stream encodes an error in the shell region, causing
106
108
  * renderToReadableStream to reject. The error propagates back to the RSC
107
- * entry which renders the deny page. For deny() inside Suspense, the shell
109
+ * entry, which rethrows the captured DenySignal for the pipeline to render
110
+ * the deny page. For deny() inside Suspense, the shell
108
111
  * succeeds and the error streams as a React error boundary after flush.
109
112
  *
110
113
  * @param rscStream - The ReadableStream from the RSC environment
111
114
  * @param navContext - Per-request state passed across RSC→SSR boundary
112
- * @returns A Response containing the HTML stream with hydration markers
115
+ * @returns The HTML Response with hydration markers, plus SSR diagnostics
113
116
  */
114
117
  export async function handleSsr(
115
118
  rscStream: ReadableStream<Uint8Array>,
116
119
  navContext: NavContext
117
- ): Promise<Response> {
120
+ ): Promise<SsrRenderResult> {
118
121
  return withSpan('timber.ssr', { 'timber.environment': 'ssr' }, async () => {
119
122
  const _runtimeConfig = config;
120
123
 
121
- // Build per-request SSR data for client hooks (usePathname,
122
- // useSearchParams, useCookie, useParams, etc.).
124
+ // Per-request SSR data for the client code with no React context to
125
+ // read during SSR (useCookie, <Link preserveSearchParams>; useSearchParams
126
+ // uses it only to detect SSR). Route params reach client components through
127
+ // ParamsContext, decoded from the payload root, not through here.
123
128
  const ssrData: SsrData = {
124
- pathname: navContext.pathname,
125
129
  search: navContext.search,
126
130
  cookies: navContext.cookies ?? new Map(),
127
- params: navContext.segmentParams,
128
- slotParams: navContext.slotParams,
129
- _navContext: navContext,
130
131
  };
131
132
 
132
133
  // Run the entire render inside the SSR data ALS scope.
@@ -188,6 +189,36 @@ export async function handleSsr(
188
189
  // Entire pipeline stays in C++ native streams until the Response boundary.
189
190
  // - Workers: renderToReadableStream → Web TransformStream pipeline → Response
190
191
  // Web Streams are V8-native C++ built-ins on Workers.
192
+ //
193
+ // `onFizzAllReadyResolved` fires synchronously before the render
194
+ // promise resolves, so the flag is settled once the render is awaited.
195
+ const renderTimeoutMs = _runtimeConfig.renderTimeoutMs ?? undefined;
196
+ const requestInfo = { method: 'GET', path: navContext.pathname };
197
+ let fizzAllReadyResolved = false;
198
+ const renderOptions: SsrStreamOptions = {
199
+ bootstrapScriptContent: navContext.bootstrapScriptContent || undefined,
200
+ nonce,
201
+ deferSuspenseFor: navContext.deferSuspenseFor,
202
+ signal: navContext.signal,
203
+ renderTimeoutMs,
204
+ requestInfo,
205
+ onFizzAllReadyResolved: (resolved) => {
206
+ fizzAllReadyResolved = resolved;
207
+ },
208
+ };
209
+ // Not logged here. Fizz's onError (ssr-render.ts) has already logged a
210
+ // shell error SSR produced itself, and skips one Flight relayed,
211
+ // which the RSC onError (rsc-stream.ts) logged. Logging the rejection
212
+ // again doubled every shell failure (TIM-1537).
213
+ const renderFailed = (renderError: unknown): never => {
214
+ throw new SsrStreamError(
215
+ 'SSR renderToReadableStream failed due to RSC stream error',
216
+ renderError
217
+ );
218
+ };
219
+
220
+ let outputStream: ReadableStream<Uint8Array>;
221
+ let _renderEnd: number;
191
222
  if (_nodeStreamImports) {
192
223
  // Node.js fast path: full pipeline in native streams
193
224
  const {
@@ -198,30 +229,10 @@ export async function handleSsr(
198
229
  runNodePipelineWithErrorHandling,
199
230
  } = _nodeStreamImports;
200
231
 
201
- const renderTimeoutMs = _runtimeConfig.renderTimeoutMs ?? undefined;
202
- const requestInfo = { method: 'GET', path: navContext.pathname };
203
-
204
- let nodeHtmlStream: import('node:stream').Readable;
205
- try {
206
- nodeHtmlStream = await renderSsrNodeStream(wrappedElement, {
207
- bootstrapScriptContent: navContext.bootstrapScriptContent || undefined,
208
- nonce,
209
- deferSuspenseFor: navContext.deferSuspenseFor,
210
- signal: navContext.signal,
211
- renderTimeoutMs,
212
- requestInfo,
213
- onFizzAllReadyResolved: (resolved) => {
214
- navContext._fizzAllReadyResolved = resolved;
215
- },
216
- });
217
- } catch (renderError) {
218
- logRenderError({ ...requestInfo, error: renderError });
219
- throw new SsrStreamError(
220
- 'SSR renderToReadableStream failed due to RSC stream error',
221
- renderError
222
- );
223
- }
224
- const _renderEnd = performance.now();
232
+ const nodeHtmlStream = await renderSsrNodeStream(wrappedElement, renderOptions).catch(
233
+ renderFailed
234
+ );
235
+ _renderEnd = performance.now();
225
236
 
226
237
  // React 19.3+ emits <!DOCTYPE html> automatically when the root
227
238
  // element is <html>, so no framework-level doctype prepend needed.
@@ -240,92 +251,57 @@ export async function handleSsr(
240
251
  // Resolve the lazy segment script now that the shell is ready
241
252
  // (AccessGates have settled, ALS deny index is authoritative).
242
253
  const resolvedHeadHtml = navContext.headHtml + (navContext.getHeadSegmentScript?.() ?? '');
243
- const bufferedTransform = createNodeBufferedTransform();
244
- const headInjector = createNodeHeadInjector(resolvedHeadHtml);
245
- const flightInjector = createNodeFlightInjector(navContext.rscStream, {
246
- renderTimeoutMs,
247
- errorSignal: navContext._errorSignal,
248
- nonce,
249
- });
250
- const moveSuffix = createNodeMoveSuffixTransform();
251
-
252
254
  const output = runNodePipelineWithErrorHandling(
253
255
  nodeHtmlStream,
254
- [bufferedTransform, headInjector, flightInjector, moveSuffix],
256
+ [
257
+ createNodeBufferedTransform(),
258
+ createNodeHeadInjector(resolvedHeadHtml),
259
+ createNodeFlightInjector(navContext.rscStream, {
260
+ renderTimeoutMs,
261
+ errorSignal: navContext._errorSignal,
262
+ nonce,
263
+ }),
264
+ createNodeMoveSuffixTransform(),
265
+ ],
255
266
  navContext.signal,
256
267
  nonce
257
268
  );
258
- const _pipelineEnd = performance.now();
259
-
260
- // Record SSR sub-timings for Server-Timing header (detailed mode).
261
- navContext._ssrTimings = {
262
- decodeMs: Math.round(_decodeEnd - _ssrStart),
263
- shellMs: Math.round(_renderEnd - _decodeEnd),
264
- pipeMs: 0, // pipe() timing is inside renderSsrNodeStream
265
- pipelineMs: Math.round(_pipelineEnd - _renderEnd),
266
- totalMs: Math.round(_pipelineEnd - _ssrStart),
267
- nodeStreams: true,
268
- };
269
-
270
- const webStream = nodeReadableToWeb(output);
271
- return buildSsrResponse(webStream, navContext.statusCode, navContext.responseHeaders);
272
- }
269
+ outputStream = nodeReadableToWeb(output);
270
+ } else {
271
+ // Web Streams path (CF Workers / fallback)
272
+ const htmlStream = await renderSsrStream(wrappedElement, renderOptions).catch(renderFailed);
273
+ _renderEnd = performance.now();
273
274
 
274
- // Web Streams path (CF Workers / fallback)
275
- const renderTimeoutMs = _runtimeConfig.renderTimeoutMs ?? undefined;
276
- const requestInfo = { method: 'GET', path: navContext.pathname };
277
- let htmlStream: ReadableStream<Uint8Array>;
278
- try {
279
- htmlStream = await renderSsrStream(wrappedElement, {
280
- bootstrapScriptContent: navContext.bootstrapScriptContent || undefined,
281
- nonce,
282
- deferSuspenseFor: navContext.deferSuspenseFor,
283
- signal: navContext.signal,
275
+ // Pipeline: buffer → injectHead → injectRscPayload
276
+ //
277
+ // The buffered transform coalesces Fizz micro-chunks into coherent
278
+ // HTML fragments so downstream transforms never see chunk boundaries
279
+ // mid-tag. This prevents RSC script injection from breaking HTML
280
+ // structure (TIM-527).
281
+ // Resolve the lazy segment script now that the shell is ready
282
+ // (AccessGates have settled, ALS deny index is authoritative).
283
+ const resolvedHeadHtml = navContext.headHtml + (navContext.getHeadSegmentScript?.() ?? '');
284
+ outputStream = htmlStream.pipeThrough(createBufferedTransformStream());
285
+ outputStream = injectHead(outputStream, resolvedHeadHtml);
286
+ outputStream = injectRscPayload(outputStream, navContext.rscStream, {
284
287
  renderTimeoutMs,
285
- requestInfo,
286
- onFizzAllReadyResolved: (resolved) => {
287
- navContext._fizzAllReadyResolved = resolved;
288
- },
288
+ errorSignal: navContext._errorSignal,
289
+ nonce,
289
290
  });
290
- } catch (renderError) {
291
- logRenderError({ ...requestInfo, error: renderError });
292
- throw new SsrStreamError(
293
- 'SSR renderToReadableStream failed due to RSC stream error',
294
- renderError
295
- );
296
291
  }
297
-
298
- const _renderEnd = performance.now();
299
-
300
- // Pipeline: buffer → injectHead → injectRscPayload
301
- //
302
- // The buffered transform coalesces Fizz micro-chunks into coherent
303
- // HTML fragments so downstream transforms never see chunk boundaries
304
- // mid-tag. This prevents RSC script injection from breaking HTML
305
- // structure (TIM-527).
306
- // Resolve the lazy segment script now that the shell is ready
307
- // (AccessGates have settled, ALS deny index is authoritative).
308
- const resolvedHeadHtml = navContext.headHtml + (navContext.getHeadSegmentScript?.() ?? '');
309
- let outputStream = htmlStream.pipeThrough(createBufferedTransformStream());
310
- outputStream = injectHead(outputStream, resolvedHeadHtml);
311
- outputStream = injectRscPayload(outputStream, navContext.rscStream, {
312
- renderTimeoutMs,
313
- errorSignal: navContext._errorSignal,
314
- nonce,
315
- });
316
292
  const _pipelineEnd = performance.now();
317
293
 
318
- navContext._ssrTimings = {
319
- decodeMs: Math.round(_decodeEnd - _ssrStart),
320
- shellMs: Math.round(_renderEnd - _decodeEnd),
321
- pipeMs: 0,
322
- pipelineMs: Math.round(_pipelineEnd - _renderEnd),
323
- totalMs: Math.round(_pipelineEnd - _ssrStart),
324
- nodeStreams: false,
294
+ return {
295
+ response: buildSsrResponse(outputStream, navContext.statusCode, navContext.responseHeaders),
296
+ timings: {
297
+ decodeMs: Math.round(_decodeEnd - _ssrStart),
298
+ shellMs: Math.round(_renderEnd - _decodeEnd),
299
+ pipelineMs: Math.round(_pipelineEnd - _renderEnd),
300
+ totalMs: Math.round(_pipelineEnd - _ssrStart),
301
+ nodeStreams: _nodeStreamImports !== null,
302
+ },
303
+ fizzAllReadyResolved,
325
304
  };
326
-
327
- // Build and return the Response.
328
- return buildSsrResponse(outputStream, navContext.statusCode, navContext.responseHeaders);
329
305
  });
330
306
  });
331
307
  }
@@ -36,12 +36,24 @@ import { isAbortError, noindexScript } from './render-utils.ts';
36
36
  const REACT_PROD_ERROR_PREFIX = 'An error occurred in the Server Components render';
37
37
 
38
38
  /**
39
- * Returns true if the error is React's sanitized production error.
40
- * These are duplicates of errors already logged by the RSC onError handler
41
- * with the full original message — logging them again in SSR adds noise.
39
+ * Returns true if this error was thrown in the RSC render and relayed by
40
+ * Flight, which means the RSC onError handler (rsc-stream.ts) already logged
41
+ * it with the full original message. Logging it again in SSR is a duplicate.
42
+ *
43
+ * In production React replaces a relayed error's message with a fixed
44
+ * sanitized one. In development it keeps the message, stamps the revived
45
+ * Error with the `environmentName` it was thrown in, and copies the digest
46
+ * our onError returned (`resolveErrorDev` and the `E` row in the Flight
47
+ * client). Both are needed: an Error passed as a *value* (a prop, `$Z`) is
48
+ * stamped with `environmentName` too but has no digest, and nothing logged
49
+ * it. When a client component throws one during SSR, it is logged here once,
50
+ * like any other error SSR throws itself (TIM-1537).
42
51
  */
43
- function isReactSanitizedError(error: unknown): boolean {
44
- return error instanceof Error && error.message.startsWith(REACT_PROD_ERROR_PREFIX);
52
+ function isFlightRelayedError(error: unknown): boolean {
53
+ if (!(error instanceof Error)) return false;
54
+ if (error.message.startsWith(REACT_PROD_ERROR_PREFIX)) return true;
55
+ const digest: unknown = Reflect.get(error, 'digest');
56
+ return 'environmentName' in error && typeof digest === 'string' && digest !== '';
45
57
  }
46
58
 
47
59
  /**
@@ -106,6 +118,26 @@ try {
106
118
  // node:stream or renderToPipeableStream not available — use Web Streams path
107
119
  }
108
120
 
121
+ /** Options shared by both SSR render paths (Node streams and Web Streams). */
122
+ export interface SsrStreamOptions {
123
+ bootstrapScriptContent?: string;
124
+ /** Request CSP nonce — stamped by Fizz on the bootstrap and runtime scripts. */
125
+ nonce?: string;
126
+ deferSuspenseFor?: number;
127
+ signal?: AbortSignal;
128
+ renderTimeoutMs?: number;
129
+ /** Request info threaded into render-error logs (method/path). */
130
+ requestInfo?: { method: string; path: string };
131
+ /**
132
+ * Fired synchronously when the render function is about to resolve
133
+ * (i.e. at hold-end / shell-ready). `resolved` reports whether Fizz's
134
+ * allReady had already settled by that moment. The SSR entry returns it
135
+ * as `SsrRenderResult.fizzAllReadyResolved` so the RSC renderer can
136
+ * decide whether signal promotion can be short-circuited.
137
+ */
138
+ onFizzAllReadyResolved?: (resolved: boolean) => void;
139
+ }
140
+
109
141
  /**
110
142
  * Render a React element tree to a ReadableStream of HTML.
111
143
  *
@@ -122,24 +154,7 @@ try {
122
154
  */
123
155
  export async function renderSsrStream(
124
156
  element: ReactNode,
125
- options?: {
126
- bootstrapScriptContent?: string;
127
- /** Request CSP nonce — stamped by Fizz on the bootstrap and runtime scripts. */
128
- nonce?: string;
129
- deferSuspenseFor?: number;
130
- signal?: AbortSignal;
131
- renderTimeoutMs?: number;
132
- /** Request info threaded into render-error logs (method/path). */
133
- requestInfo?: { method: string; path: string };
134
- /**
135
- * Fired synchronously when the render function is about to resolve
136
- * (i.e. at hold-end / shell-ready). `resolved` reports whether Fizz's
137
- * `stream.allReady` had already settled by that moment. Callers use
138
- * this to decide whether signal promotion can be short-circuited.
139
- * See NavContext._fizzAllReadyResolved.
140
- */
141
- onFizzAllReadyResolved?: (resolved: boolean) => void;
142
- }
157
+ options?: SsrStreamOptions
143
158
  ): Promise<ReadableStream<Uint8Array>> {
144
159
  return renderViaReadableStream(element, options);
145
160
  }
@@ -164,23 +179,7 @@ export const useNodeStreams = _useNodeStreams;
164
179
  */
165
180
  export async function renderSsrNodeStream(
166
181
  element: ReactNode,
167
- options?: {
168
- bootstrapScriptContent?: string;
169
- /** Request CSP nonce — stamped by Fizz on the bootstrap and runtime scripts. */
170
- nonce?: string;
171
- deferSuspenseFor?: number;
172
- signal?: AbortSignal;
173
- renderTimeoutMs?: number;
174
- /** Request info threaded into render-error logs (method/path). */
175
- requestInfo?: { method: string; path: string };
176
- /**
177
- * Fired synchronously at the moment `renderSsrNodeStream`'s returned
178
- * Promise is about to resolve. `resolved` reports whether Fizz's
179
- * `onAllReady` had already fired by then. See the twin callback on
180
- * `renderSsrStream`.
181
- */
182
- onFizzAllReadyResolved?: (resolved: boolean) => void;
183
- }
182
+ options?: SsrStreamOptions
184
183
  ): Promise<import('node:stream').Readable> {
185
184
  const signal = options?.signal;
186
185
  const deferMs = options?.deferSuspenseFor;
@@ -235,9 +234,9 @@ export async function renderSsrNodeStream(
235
234
 
236
235
  onError(error: unknown) {
237
236
  if (isAbortError(error) || signal?.aborted) return;
238
- // Skip React's sanitized production errors — the original was
239
- // already logged by the RSC onError with full details.
240
- if (isReactSanitizedError(error)) return;
237
+ // Skip errors Flight relayed — the original was already logged by
238
+ // the RSC onError with full details.
239
+ if (isFlightRelayedError(error)) return;
241
240
  logRenderError({
242
241
  method: requestInfo?.method ?? '',
243
242
  path: requestInfo?.path ?? '',
@@ -301,16 +300,7 @@ export function nodeReadableToWeb(
301
300
 
302
301
  async function renderViaReadableStream(
303
302
  element: ReactNode,
304
- options?: {
305
- bootstrapScriptContent?: string;
306
- /** Request CSP nonce — stamped by Fizz on the bootstrap and runtime scripts. */
307
- nonce?: string;
308
- deferSuspenseFor?: number;
309
- signal?: AbortSignal;
310
- renderTimeoutMs?: number;
311
- requestInfo?: { method: string; path: string };
312
- onFizzAllReadyResolved?: (resolved: boolean) => void;
313
- }
303
+ options?: SsrStreamOptions
314
304
  ): Promise<ReadableStream<Uint8Array>> {
315
305
  const signal = options?.signal;
316
306
  const timeoutMs = options?.renderTimeoutMs;
@@ -345,9 +335,9 @@ async function renderViaReadableStream(
345
335
  });
346
336
  return;
347
337
  }
348
- // Skip React's sanitized production errors — the original was
349
- // already logged by the RSC onError with full details.
350
- if (isReactSanitizedError(error)) return;
338
+ // Skip errors Flight relayed — the original was already logged by
339
+ // the RSC onError with full details.
340
+ if (isFlightRelayedError(error)) return;
351
341
  logRenderError({
352
342
  method: requestInfo?.method ?? '',
353
343
  path: requestInfo?.path ?? '',
@@ -378,7 +368,7 @@ async function renderViaReadableStream(
378
368
  //
379
369
  // While we're holding, also track whether `stream.allReady` settled
380
370
  // before the timer. That boolean is the Option-1 signal-promotion
381
- // short-circuit key — see NavContext._fizzAllReadyResolved and
371
+ // short-circuit key — see SsrRenderResult.fizzAllReadyResolved and
382
372
  // design/spike-signal-promotion-protocol.md.
383
373
  let fizzAllReadyResolved = false;
384
374
  const allReadyTap = stream.allReady.then(
@@ -454,19 +444,20 @@ export function wrapStreamWithErrorHandling(
454
444
  * React 19.3+ automatically emits `<!DOCTYPE html>` when the root
455
445
  * element is `<html>`, so no framework-level doctype prepending is needed.
456
446
  *
457
- * Sets content-type to text/html if not already set by middleware.
447
+ * Sets content-type to text/html if not already set by middleware. The
448
+ * default goes on a response-local copy: `responseHeaders` is the
449
+ * pipeline's shared bag, handed over on `NavContext`, and SSR only reads
450
+ * it (design/49 §"A2").
458
451
  */
459
452
  export function buildSsrResponse(
460
453
  htmlStream: ReadableStream<Uint8Array>,
461
454
  statusCode: number,
462
455
  responseHeaders: Headers
463
456
  ): Response {
464
- if (!responseHeaders.has('content-type')) {
465
- responseHeaders.set('content-type', 'text/html; charset=utf-8');
457
+ const headers = new Headers(responseHeaders);
458
+ if (!headers.has('content-type')) {
459
+ headers.set('content-type', 'text/html; charset=utf-8');
466
460
  }
467
461
 
468
- return new Response(htmlStream, {
469
- status: statusCode,
470
- headers: responseHeaders,
471
- });
462
+ return new Response(htmlStream, { status: statusCode, headers });
472
463
  }
@@ -30,7 +30,7 @@
30
30
  * Per-request isolation is by construction: the provider values are part
31
31
  * of this request's element tree, so concurrent requests cannot observe
32
32
  * each other's values — stronger than the ALS path, which remains for
33
- * `useCookie()` and the `_navContext` status-code channel.
33
+ * `useCookie()`.
34
34
  *
35
35
  * **What actually shifts a useId is a fork, not depth.** `useId` derives from
36
36
  * React's tree context, which only changes where a fiber has more than one
@@ -142,7 +142,7 @@ export interface SsrWrapOptions {
142
142
  */
143
143
  export function wrapSsrElement(element: ReactNode, opts: SsrWrapOptions): ReactNode {
144
144
  // Build inside-out to match the client's createElement chain in
145
- // hydrate.ts / router-init.ts renderTree().
145
+ // browser-entry/router-init.ts renderTree(), which hydration builds with too.
146
146
 
147
147
  // 1. Innermost: PayloadRoot publishes the payload's params over the tree.
148
148
  const withParams = createElement(PayloadRoot, { source: opts.paramsSource }, element);
@@ -22,6 +22,8 @@
22
22
  import type { ManifestRoot, ManifestSegmentNode, ManifestFile } from './route-matcher.ts';
23
23
  import { hasDynamicSegments, hasUserSitemap, resolvePathWithParams } from './sitemap-generator.ts';
24
24
  import { loadModule } from './safe-load.ts';
25
+ import { readAllBytesWithDeadline } from './stream-utils.ts';
26
+ import { DEFAULT_RENDER_TIMEOUT_MS, resolveRenderTimeoutMs } from './render-timeout.ts';
25
27
  import { METADATA_ROUTE_CONVENTIONS, resolveServePathForFile } from './metadata-routes.ts';
26
28
  import { RSC_CONTENT_TYPE } from '../shared/rsc-media-type.ts';
27
29
  import {
@@ -346,8 +348,6 @@ function normalizeRedirectTarget(rawLocation: string): string {
346
348
 
347
349
  // ─── Rendering ───────────────────────────────────────────────────────────
348
350
 
349
- const DEFAULT_RENDER_TIMEOUT_MS = 30_000;
350
-
351
351
  async function loadModuleWithTimeout(
352
352
  file: ManifestFile,
353
353
  timeoutMs: number
@@ -365,44 +365,6 @@ async function loadModuleWithTimeout(
365
365
  }
366
366
  }
367
367
 
368
- async function drainResponse(response: Response, timeoutMs: number): Promise<Uint8Array> {
369
- if (!response.body) return new Uint8Array(0);
370
-
371
- const reader = response.body.getReader();
372
- const chunks: Uint8Array[] = [];
373
- let timer: ReturnType<typeof setTimeout> | undefined;
374
- let timedOut = false;
375
-
376
- const deadline = new Promise<never>((_, reject) => {
377
- timer = setTimeout(() => {
378
- timedOut = true;
379
- reject(new Error(`response did not complete within ${timeoutMs}ms`));
380
- }, timeoutMs);
381
- });
382
-
383
- try {
384
- for (;;) {
385
- const { done, value } = await Promise.race([reader.read(), deadline]);
386
- if (done) break;
387
- chunks.push(value as Uint8Array);
388
- }
389
- } finally {
390
- clearTimeout(timer);
391
- // Always cancel — design/13-security.md A3: never leave a reader open.
392
- await reader.cancel().catch(() => {});
393
- }
394
-
395
- let total = 0;
396
- for (const c of chunks) total += c.byteLength;
397
- const out = new Uint8Array(total);
398
- let off = 0;
399
- for (const c of chunks) {
400
- out.set(c, off);
401
- off += c.byteLength;
402
- }
403
- return out;
404
- }
405
-
406
368
  function headersToRecord(headers: Headers): Record<string, string> {
407
369
  const record: Record<string, string> = {};
408
370
  headers.forEach((value, key) => {
@@ -428,7 +390,7 @@ export async function generateStaticSite(
428
390
  options: StaticGenerationOptions
429
391
  ): Promise<StaticGenerationSummary> {
430
392
  const log = options.log ?? ((msg: string) => console.log(msg));
431
- const timeoutMs = options.renderTimeoutMs ?? DEFAULT_RENDER_TIMEOUT_MS;
393
+ const timeoutMs = resolveRenderTimeoutMs(options.renderTimeoutMs);
432
394
  const summary: StaticGenerationSummary = {
433
395
  rendered: 0,
434
396
  errors: [],
@@ -705,7 +667,10 @@ async function renderUrl(
705
667
  clearTimeout(timer);
706
668
  }
707
669
 
708
- const body = await drainResponse(response, timeoutMs);
670
+ // The reader is cancelled on every exit — design/13-security.md A3.
671
+ const body = response.body
672
+ ? await readAllBytesWithDeadline(response.body, timeoutMs, 'response')
673
+ : new Uint8Array(0);
709
674
 
710
675
  return {
711
676
  status: response.status,
@@ -51,9 +51,9 @@ export interface NotFoundResult {
51
51
  /**
52
52
  * Whether the not-found chain has anything to render for this root.
53
53
  *
54
- * Asks the resolver rather than inspecting file names: `renderNoMatchPage`
55
- * builds its chain from the root segment alone and resolves through exactly
56
- * these two calls, so this cannot drift from what the request path does. A
54
+ * Asks the resolver rather than inspecting file names: the no-match 404 (the
55
+ * deny fallback with no match, `rsc-entry/deny-fallback.ts`) builds its chain
56
+ * from the root segment alone and resolves through exactly these two calls, so this cannot drift from what the request path does. A
57
57
  * hand-rolled key check gets it wrong — a root that declares only `500.tsx`
58
58
  * has status files but nothing a 404 can select.
59
59
  */
@@ -290,3 +290,54 @@ function formatBytes(bytes: number): string {
290
290
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
291
291
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
292
292
  }
293
+
294
+ /**
295
+ * Read a byte stream to completion under one overall deadline and return
296
+ * the concatenated bytes. Every read is raced against the time remaining,
297
+ * and the reader is cancelled on every exit, so a stalled upstream never
298
+ * outlives the deadline. See design/02-rendering-pipeline.md §"Always
299
+ * Timeout-Guard Stream Reads".
300
+ *
301
+ * @param label - Prefix for the timeout error message. Both ways the deadline
302
+ * can pass (between reads, or while a read is pending) reject with the same
303
+ * `${label} did not complete within ${timeoutMs}ms`.
304
+ */
305
+ export async function readAllBytesWithDeadline(
306
+ stream: ReadableStream<Uint8Array>,
307
+ timeoutMs: number,
308
+ label: string
309
+ ): Promise<Uint8Array> {
310
+ const reader = stream.getReader();
311
+ const chunks: Uint8Array[] = [];
312
+ let totalLength = 0;
313
+ const deadline = Date.now() + timeoutMs;
314
+ const deadlineError = () => new Error(`${label} did not complete within ${timeoutMs}ms`);
315
+ try {
316
+ for (;;) {
317
+ const remaining = deadline - Date.now();
318
+ if (remaining <= 0) throw deadlineError();
319
+ let timer: ReturnType<typeof setTimeout> | undefined;
320
+ const timeout = new Promise<never>((_, reject) => {
321
+ timer = setTimeout(() => reject(deadlineError()), remaining);
322
+ });
323
+ let result: ReadableStreamReadResult<Uint8Array>;
324
+ try {
325
+ result = await Promise.race([reader.read(), timeout]);
326
+ } finally {
327
+ clearTimeout(timer);
328
+ }
329
+ if (result.done) break;
330
+ chunks.push(result.value);
331
+ totalLength += result.value.byteLength;
332
+ }
333
+ } finally {
334
+ reader.cancel().catch(() => {});
335
+ }
336
+ const bytes = new Uint8Array(totalLength);
337
+ let offset = 0;
338
+ for (const chunk of chunks) {
339
+ bytes.set(chunk, offset);
340
+ offset += chunk.byteLength;
341
+ }
342
+ return bytes;
343
+ }