@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
@@ -5,12 +5,11 @@
5
5
  * pipeline construction. This module owns the steps that happen *after*
6
6
  * the pipeline has matched a route and before it commits a response:
7
7
  * element-tree build, RSC Flight render, and dispatch to either the SSR
8
- * HTML path or the RSC payload path. It also handles the
9
- * synchronous-signal escape hatches (deny / redirect / render error
10
- * thrown during stream creation) so the entry doesn't carry that logic.
8
+ * HTML path or the RSC payload path. A deny or redirect captured during the
9
+ * render is rethrown to the pipeline, which answers it.
11
10
  *
12
11
  * The function is parameterized over its dependencies — `clientBootstrap`,
13
- * `clientJsDisabled`, `rootSegment`, `globalError` — so the entry passes
12
+ * `clientJsDisabled`, `renderDenyFallback`, `globalError` — so the entry passes
14
13
  * them in once at handler-construction time and they ride along on every
15
14
  * call. No globals, no closures over the entry's createRequestHandler
16
15
  * scope.
@@ -27,25 +26,19 @@ import {
27
26
  collectRouteFonts,
28
27
  collectRouteModulepreloads,
29
28
  } from '../build-manifest.ts';
30
- import type { LayoutEntry } from '../deny-renderer.ts';
31
- import { renderDenyPage, renderDenyPageAsRsc } from '../deny-renderer.ts';
32
29
  import type { ClientBootstrapConfig } from '../html-injectors.ts';
33
30
  import type { InterceptionContext, RouteMatch } from '../pipeline.ts';
31
+ import { DenySignal } from '../primitives.ts';
34
32
  import { buildRouteElement, NoPageComponentError } from '../route-element-builder.ts';
35
- import { ParamCoercionError } from '../param-coercion.ts';
36
- import type { ManifestSegmentNode } from '../route-matcher.ts';
37
33
  import { recordTiming } from '../server-timing.ts';
38
34
  import { parseClientStateTree } from '../state-tree-diff.ts';
39
35
 
40
- import { getFirstDeniedSegmentIndex } from '../deny-boundary.ts';
41
36
  import { handleApiRoute } from './api-handler.ts';
42
- import { renderErrorPage, renderNoMatchPage } from './error-renderer.ts';
43
- import { buildRedirectResponse } from './helpers.ts';
37
+ import type { DenyFallbackRenderer } from './deny-fallback.ts';
44
38
  import { isRscRequest } from '../../shared/rsc-media-type.ts';
45
39
  import { buildRscPayloadResponse } from './rsc-payload.ts';
46
40
  import { renderRscStream } from './rsc-stream.ts';
47
41
  import { renderSsrResponse } from './ssr-renderer.ts';
48
- import { callSsr } from './ssr-bridge.ts';
49
42
 
50
43
  /**
51
44
  * Static-per-handler dependencies for `renderRoute` — captured once at
@@ -56,7 +49,7 @@ export interface RenderRouteDeps {
56
49
  clientBootstrap: ClientBootstrapConfig;
57
50
  clientJsDisabled: boolean;
58
51
  clientSegmentCache: boolean;
59
- rootSegment: ManifestSegmentNode;
52
+ renderDenyFallback: DenyFallbackRenderer;
60
53
  buildManifest: BuildManifest;
61
54
  globalError?: { load: () => Promise<unknown>; filePath: string };
62
55
  }
@@ -78,7 +71,7 @@ export async function renderRoute(
78
71
  deps: RenderRouteDeps,
79
72
  interception?: InterceptionContext
80
73
  ): Promise<Response> {
81
- const { clientBootstrap, clientJsDisabled, rootSegment, buildManifest, globalError } = deps;
74
+ const { clientBootstrap, clientJsDisabled, buildManifest, globalError } = deps;
82
75
  const segments = match.segments;
83
76
  const leaf = segments[segments.length - 1];
84
77
 
@@ -113,19 +106,16 @@ export async function renderRoute(
113
106
  buildManifest.metadataRouteHashes
114
107
  );
115
108
  } catch (error) {
116
- // Param coercion failed — render the custom 404 page via status files.
117
- // Previously returned a bare Response(null, { status: 404 }) which bypassed
118
- // custom 404 pages. Now routes through renderNoMatchPage so apps with
119
- // 404.tsx render their custom page.
120
- if (error instanceof ParamCoercionError) {
121
- return renderNoMatchPage(req, rootSegment, responseHeaders, clientBootstrap);
122
- }
123
- // No PageComponent found — same treatment as param coercion: render custom 404.
109
+ // No PageComponent found — render the app's 404 page as for an
110
+ // unmatched URL: the root chain, not the matched one. No access.ts has
111
+ // run for the matched chain yet, so its layouts must not wrap the page
112
+ // (design/13-security.md). The deny fallback is the one assembler of
113
+ // that page; calling it with no match selects the root chain.
124
114
  if (error instanceof NoPageComponentError) {
125
115
  if (process.env.NODE_ENV !== 'production') {
126
116
  console.warn(`[timber] ${error.message}`);
127
117
  }
128
- return renderNoMatchPage(req, rootSegment, responseHeaders, clientBootstrap);
118
+ return deps.renderDenyFallback(new DenySignal(404), req, responseHeaders);
129
119
  }
130
120
  throw error;
131
121
  }
@@ -205,67 +195,12 @@ export async function renderRoute(
205
195
  desc: 'RSC stream init',
206
196
  });
207
197
 
208
- // Synchronous redirect — redirect() in access.ts or a non-async component
209
- // throws during renderToReadableStream creation. Return HTTP redirect.
210
- if (signals.redirectSignal) {
211
- return buildRedirectResponse(signals.redirectSignal, req, responseHeaders);
212
- }
213
-
214
- // Synchronous deny — deny() in a non-async component throws during
215
- // renderToReadableStream creation, caught in the try/catch above.
216
- if (signals.denySignal) {
217
- if (isRscRequest(req)) {
218
- return renderDenyPageAsRsc(
219
- signals.denySignal,
220
- segments,
221
- layoutComponents as LayoutEntry[],
222
- req,
223
- responseHeaders,
224
- getFirstDeniedSegmentIndex()
225
- );
226
- }
227
- return renderDenyPage(
228
- signals.denySignal,
229
- segments,
230
- layoutComponents as LayoutEntry[],
231
- req,
232
- match,
233
- responseHeaders,
234
- clientBootstrap,
235
- callSsr,
236
- undefined,
237
- getFirstDeniedSegmentIndex()
238
- );
239
- }
240
-
241
- // Synchronous render error — renderToReadableStream threw before
242
- // creating the stream. Render the error page with correct 5xx status.
243
- // (Async render errors are tracked in onError and handled after SSR.)
244
- // An RSC payload request gets the hard-navigate envelope rather than an
245
- // error page — `renderErrorPage` owns that branch, so every one of its call
246
- // sites is covered rather than this one alone (TIM-1322).
247
- if (signals.renderError && !rscStream) {
248
- return renderErrorPage(
249
- signals.renderError.error,
250
- signals.renderError.status,
251
- segments,
252
- layoutComponents as LayoutEntry[],
253
- req,
254
- match,
255
- responseHeaders,
256
- clientBootstrap,
257
- globalError,
258
- getFirstDeniedSegmentIndex()
259
- );
260
- }
261
-
262
198
  // For RSC payload requests (client navigation), return the RSC Flight
263
199
  // stream directly — skip SSR HTML rendering entirely.
264
200
  // See design/19-client-navigation.md §"RSC Payload Handling"
265
201
  if (isRscRequest(req)) {
266
202
  return buildRscPayloadResponse(
267
- req,
268
- rscStream!,
203
+ rscStream,
269
204
  signals,
270
205
  segments,
271
206
  layoutComponents,
@@ -278,7 +213,7 @@ export async function renderRoute(
278
213
  // Pipe through SSR for HTML rendering with streaming Suspense support.
279
214
  return renderSsrResponse({
280
215
  req,
281
- rscStream: rscStream!,
216
+ rscStream,
282
217
  signals,
283
218
  segments,
284
219
  layoutComponents,
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Render signals — the deny / redirect / unhandled-error state one RSC
3
+ * render captures, and the recorder that writes it.
4
+ *
5
+ * Kept apart from `rsc-stream.ts` so the contract carries no Flight runtime:
6
+ * consumers and tests can hold signals without loading the renderer.
7
+ *
8
+ * Design docs: 02-rendering-pipeline.md §"Single-Pass Rendering",
9
+ * 49-explicit-subsystem-boundaries.md §"C"
10
+ */
11
+
12
+ import type { DenySignal, RedirectSignal } from '../primitives.ts';
13
+
14
+ /**
15
+ * Signal state captured during RSC rendering. Read-only for consumers: only
16
+ * the render that produced it records into it (`createSignalRecorder`).
17
+ *
18
+ * Signals fire asynchronously via `onError` during stream consumption.
19
+ * The first deny wins; a later redirect replaces an earlier one.
20
+ *
21
+ * The two notification channels are values the producer owns and returns,
22
+ * not callback slots a consumer assigns after the fact. A slot only works if
23
+ * no `await` separates `renderRscStream()` from the assignment — add one and
24
+ * an early signal fires into an empty slot with no trace. A promise that has
25
+ * already resolved, and an `AbortSignal` that is already aborted, carry the
26
+ * early event to a late reader.
27
+ */
28
+ export interface RenderSignals {
29
+ readonly denySignal: DenySignal | null;
30
+ /**
31
+ * The first deny that no in-tree catch site could place — no `owners`, so
32
+ * no boundary may claim its error row and only the re-render fallback can
33
+ * produce a page for it.
34
+ *
35
+ * Tracked apart from `denySignal` because one render can produce both. A
36
+ * deep page can hoist a 404 to a boundary that will render it while an
37
+ * outer layout separately throws a 403 nothing matches; whichever lands in
38
+ * `denySignal` first, the unplaced one still needs the fallback, and
39
+ * deciding from `denySignal.owners` alone would strand it. See TIM-1356.
40
+ */
41
+ readonly unplacedDeny: DenySignal | null;
42
+ readonly redirectSignal: RedirectSignal | null;
43
+ /**
44
+ * Resolves when the first deny or redirect is captured; never rejects.
45
+ * Consumers race it to react the instant `onError` fires instead of
46
+ * polling with setTimeout/queueMicrotask.
47
+ */
48
+ readonly captured: Promise<void>;
49
+ /**
50
+ * Aborted when the first unhandled (non-signal) error is captured. Halts
51
+ * Flight data injection into the inline stream (TIM-938).
52
+ */
53
+ readonly unhandledError: AbortSignal;
54
+ }
55
+
56
+ /** The write side of `RenderSignals`, held by the render that captures. */
57
+ export interface SignalRecorder {
58
+ readonly signals: RenderSignals;
59
+ deny(signal: DenySignal): void;
60
+ redirect(signal: RedirectSignal): void;
61
+ unhandledError(): void;
62
+ }
63
+
64
+ /**
65
+ * Create the signal state for one render. `renderRscStream()` records into
66
+ * it from Flight's `onError`; tests record into it to stand in for Flight.
67
+ */
68
+ export function createSignalRecorder(): SignalRecorder {
69
+ let denySignal: DenySignal | null = null;
70
+ let unplacedDeny: DenySignal | null = null;
71
+ let redirectSignal: RedirectSignal | null = null;
72
+ let notifyCaptured!: () => void;
73
+ const captured = new Promise<void>((resolve) => {
74
+ notifyCaptured = resolve;
75
+ });
76
+ const errorAbort = new AbortController();
77
+
78
+ return {
79
+ signals: {
80
+ get denySignal() {
81
+ return denySignal;
82
+ },
83
+ get unplacedDeny() {
84
+ return unplacedDeny;
85
+ },
86
+ get redirectSignal() {
87
+ return redirectSignal;
88
+ },
89
+ captured,
90
+ unhandledError: errorAbort.signal,
91
+ },
92
+ deny(signal) {
93
+ // First-wins: two concurrent denies from separately serialized
94
+ // subtrees must commit a deterministic status. See
95
+ // spike-TIM-1441 §"two-concurrent-denials scenario".
96
+ denySignal ??= signal;
97
+ if (!signal.owners) unplacedDeny ??= signal;
98
+ notifyCaptured();
99
+ },
100
+ redirect(signal) {
101
+ redirectSignal = signal;
102
+ notifyCaptured();
103
+ },
104
+ unhandledError() {
105
+ errorAbort.abort();
106
+ },
107
+ };
108
+ }
@@ -30,34 +30,25 @@ import { stringifyCookie } from 'cookie';
30
30
 
31
31
  import type { BuildManifest } from '../build-manifest.ts';
32
32
  import { canonicalize } from '../canonicalize.ts';
33
- import { getCookiesForSsr, seedRequestCookies } from '../cookie-context.ts';
33
+ import { getCookiesForSsr } from '../cookie-context.ts';
34
34
  import { logRenderError } from '../logger.ts';
35
+ import { ParamCoercionError } from '../param-coercion.ts';
35
36
  import type { RouteMatch, RouteMatcher } from '../pipeline.ts';
36
37
  import { DenySignal, RedirectSignal } from '../primitives.ts';
37
38
  import { applyRequestHeaderOverlay, setSegmentParams } from '../request-context.ts';
38
39
  import { requestContextAls } from '../als-registry.ts';
39
40
  import { buildRouteElement } from '../route-element-builder.ts';
40
- import type { RevalidateRenderer, RevalidationResult } from '../actions.ts';
41
+ import { createReactCacheScope } from '../react-cache-scope.ts';
42
+ import {
43
+ RevalidationDropped,
44
+ type RevalidateRenderer,
45
+ type RevalidationResult,
46
+ } from '../actions.ts';
47
+ import type { CoercedParams } from '../../shared/param-value.ts';
41
48
 
42
- import { runMiddlewareForAction, type CoerceSegmentParamsFn } from './action-middleware-runner.ts';
49
+ import { runMiddlewareForAction } from './action-middleware-runner.ts';
43
50
  import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.ts';
44
51
 
45
- /**
46
- * Sentinel thrown when revalidation cannot proceed because middleware
47
- * returned a short-circuit `Response` (a non-redirect HTTP response that
48
- * we cannot translate back to an element tree). `executeAction` catches
49
- * this and drops the revalidation — the action result is still delivered,
50
- * but no `_tree` is piggybacked onto the response. The matching name
51
- * `RevalidationDropped` is exported so callers can identify it via
52
- * `instanceof` without leaking the message text to clients.
53
- */
54
- export class RevalidationDropped extends Error {
55
- constructor(message: string) {
56
- super(message);
57
- this.name = 'RevalidationDropped';
58
- }
59
- }
60
-
61
52
  /** Result of validating a `revalidatePath()` argument. */
62
53
  type PathValidation =
63
54
  | { ok: true; pathname: string; search: string }
@@ -137,6 +128,9 @@ function serializeCookieMap(cookies: Map<string, string>): string {
137
128
  }
138
129
  }
139
130
 
131
+ /** Coerce a matched route's raw segment params via its `app/schema.ts` codecs. */
132
+ export type CoerceSegmentParamsFn = (match: RouteMatch) => Promise<CoercedParams>;
133
+
140
134
  /** Dependencies for the revalidate renderer factory. */
141
135
  export interface RevalidateRendererDeps {
142
136
  matchRoute: RouteMatcher;
@@ -150,7 +144,7 @@ export interface RevalidateRendererDeps {
150
144
  * The returned renderer:
151
145
  * 1. Validates the requested path.
152
146
  * 2. Matches the canonicalized path against the route tree.
153
- * 3. Coerces segment params via the matched chain's `params.ts` codecs.
147
+ * 3. Coerces segment params via the `app/schema.ts` codecs.
154
148
  * 4. Runs the matched route's `middleware.ts` chain inside a fresh
155
149
  * `runWithRequestContext` scope (via `runMiddlewareForAction`).
156
150
  * Deny/redirect signals are re-thrown so `executeAction` can apply
@@ -222,9 +216,13 @@ export function createRevalidateRendererFactory(
222
216
  // Only attempt this inside a request context — `getCookiesForSsr`
223
217
  // throws otherwise — and bail out gracefully if no context is
224
218
  // active (the legacy call-site contract permitted this).
225
- const inRequestContext = Boolean(requestContextAls.getStore());
226
- const ryw = inRequestContext ? getCookiesForSsr() : new Map<string, string>();
227
- if (inRequestContext) {
219
+ //
220
+ // The same map becomes the middleware scope's parsed cookies, so
221
+ // its `runWithRequestContext` skips `parseCookieHeader` — the H-3
222
+ // smuggling primitive mitigated by TIM-868. The Cookie header stays
223
+ // for code that reads `ctx.req.headers.get('cookie')` directly.
224
+ const ryw = requestContextAls.getStore() ? getCookiesForSsr() : undefined;
225
+ if (ryw) {
228
226
  if (ryw.size === 0) {
229
227
  revalidateHeaders.delete('cookie');
230
228
  } else {
@@ -234,20 +232,29 @@ export function createRevalidateRendererFactory(
234
232
  const revalidateReq = new Request(revalidateUrl.toString(), {
235
233
  headers: revalidateHeaders,
236
234
  });
237
- // Seed the parsed map directly so the child `runWithRequestContext`
238
- // inside `runMiddlewareForAction` skips `parseCookieHeader` — the
239
- // same H-3 smuggling primitive mitigated by TIM-868. The Cookie
240
- // header above remains in place for code that reads
241
- // `ctx.req.headers.get('cookie')` directly.
242
- if (inRequestContext) {
243
- seedRequestCookies(revalidateReq, new Map(ryw));
244
- }
245
235
 
246
- // ── 3. Match the canonical path ─────────────────────────────────
247
- const match = deps.matchRoute(validation.pathname);
248
- if (!match) {
236
+ // ── 3. Match the canonical path and coerce its params ───────────
237
+ //
238
+ // Coercion runs before middleware, as in the page pipeline, and on
239
+ // both branches below. The match keeps its raw params beside the
240
+ // coerced ones, so slot resolution in step 6 reads URL values.
241
+ const rawMatch = deps.matchRoute(validation.pathname);
242
+ if (!rawMatch) {
249
243
  throw new Error(`revalidatePath('${path}') — no matching route`);
250
244
  }
245
+ let match: RouteMatch;
246
+ try {
247
+ match = { ...rawMatch, segmentParams: await deps.coerceSegmentParams(rawMatch) };
248
+ } catch (error) {
249
+ // Bad params on the target path — drop revalidation. The action's
250
+ // own response still goes back to the client.
251
+ if (error instanceof ParamCoercionError) {
252
+ throw new RevalidationDropped(
253
+ `revalidatePath('${path}') — segment param coercion failed`
254
+ );
255
+ }
256
+ throw error;
257
+ }
251
258
 
252
259
  // ── 4. Run middleware in a fresh ALS scope ──────────────────────
253
260
  //
@@ -256,25 +263,22 @@ export function createRevalidateRendererFactory(
256
263
  // overlay) — matching the page pipeline's behavior in
257
264
  // `handleRequest` where `runMiddlewarePhase` is gated on
258
265
  // `middlewareChain.length > 0`.
266
+ //
267
+ // The scope opened here is fresh — the action body read through its
268
+ // own scope before it mutated — and the revalidated tree renders in it
269
+ // later, so this middleware shares React.cache with that render.
270
+ const reactCacheScope = createReactCacheScope();
259
271
  let overlay: Headers | undefined;
260
272
  if (match.middlewareChain.length > 0) {
261
- const outcome = await runMiddlewareForAction(
262
- revalidateReq,
263
- match,
264
- deps.coerceSegmentParams
265
- );
273
+ const outcome = await runMiddlewareForAction(revalidateReq, match, {
274
+ reactCacheScope,
275
+ cookies: ryw,
276
+ });
266
277
 
267
- if (outcome.kind === 'param-coercion-error') {
268
- // Bad params on the target path — drop revalidation. The
269
- // action's own response still goes back to the client.
270
- throw new RevalidationDropped(
271
- `revalidatePath('${path}') — segment param coercion failed`
272
- );
273
- }
274
278
  if (outcome.kind === 'error') {
275
- // Re-throw unhandled middleware errors so `executeAction`'s
276
- // existing `console.error` fallback logs them. Not surfaced
277
- // to the action client (revalidation is best-effort).
279
+ // Re-throw unhandled middleware errors so `executeAction` logs
280
+ // them and the action handler reports them. Not surfaced to the
281
+ // action client (revalidation is best-effort).
278
282
  throw outcome.error;
279
283
  }
280
284
  if (outcome.kind === 'redirect') {
@@ -311,15 +315,9 @@ export function createRevalidateRendererFactory(
311
315
  }
312
316
 
313
317
  // `continue` — capture the overlay so we can apply it to the
314
- // action's request-context store below. We deliberately do NOT
315
- // forward `outcome.cookies` or `outcome.setCookieHeaders` here;
316
- // see the module docstring for why.
318
+ // action's request-context store below. Cookies the middleware set
319
+ // are not forwarded; see this factory's docstring for why.
317
320
  overlay = outcome.overlay;
318
- } else {
319
- // No middleware on the target — still coerce params so segment
320
- // params reach `setSegmentParams` typed. `runMiddlewareForAction`
321
- // would have done this for us; do it manually on the bypass path.
322
- await deps.coerceSegmentParams(match);
323
321
  }
324
322
 
325
323
  // ── 5. Lift state onto the action's ALS store ───────────────────
@@ -344,6 +342,7 @@ export function createRevalidateRendererFactory(
344
342
  );
345
343
  return {
346
344
  payload: routeResult.payload,
345
+ reactCacheScope,
347
346
  };
348
347
  };
349
348
  };
@@ -19,19 +19,16 @@
19
19
  * 04-authorization.md §"Status codes on the RSC payload path"
20
20
  */
21
21
 
22
- import type { LayoutEntry } from '../deny-renderer.ts';
23
- import { renderDenyPageAsRsc } from '../deny-renderer.ts';
24
- import type { RedirectSignal } from '../primitives.ts';
25
22
  import type { LayoutComponentEntry } from '../route-element-builder.ts';
26
23
  import type { ManifestSegmentNode } from '../route-matcher.ts';
27
24
  import type { SlotSkipEntry } from '../slot-resolver.ts';
28
25
 
29
- import { buildRedirectResponse, buildSegmentInfo } from './helpers.ts';
26
+ import { buildSegmentInfo } from './helpers.ts';
30
27
  import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.ts';
31
28
 
32
29
  import { rscErrorEnvelope } from '../rsc-error-envelope.ts';
33
30
 
34
- import type { RenderSignals } from './rsc-stream.ts';
31
+ import type { RenderSignals } from './render-signals.ts';
35
32
 
36
33
  /**
37
34
  * Ceiling on waiting for a first chunk that is already in flight, used only
@@ -55,14 +52,17 @@ const FIRST_CHUNK_CEILING_MS = 50;
55
52
  * plus one macrotask turn. Nothing is held for it. A signal that lands
56
53
  * inside the window still gets a server-level answer — a redirect response,
57
54
  * the fallback deny page, the hard-navigate envelope — because the race
58
- * below and the one timer turn after it deliver it for free. A signal that
55
+ * below and the one timer turn after it deliver it for free. This function
56
+ * reports that signal rather than answering it: it cancels the stream and
57
+ * rethrows, and the pipeline's outcome translator builds the redirect or
58
+ * calls the deny fallback (`rsc-entry/deny-fallback.ts`), exactly as for a
59
+ * signal thrown out of render (design/49 §"C"). A signal that
59
60
  * lands after it is a row in the stream, and the client's boundaries answer
60
61
  * it. Waiting for the shell components to settle (TIM-1045, TIM-1208) made
61
62
  * the payload path pretend to a status contract it could not keep for
62
63
  * nested components, and was removed in TIM-1495.
63
64
  */
64
65
  export async function buildRscPayloadResponse(
65
- req: Request,
66
66
  rscStream: ReadableStream<Uint8Array>,
67
67
  signals: RenderSignals,
68
68
  segments: ManifestSegmentNode[],
@@ -73,8 +73,8 @@ export async function buildRscPayloadResponse(
73
73
  ): Promise<Response> {
74
74
  // Read the first chunk from the RSC stream before committing headers.
75
75
  // Race the first read against signal detection — if an async component
76
- // throws a RedirectSignal or DenySignal, the onError callback fires
77
- // signals.onSignal() and we can react immediately without waiting for
76
+ // throws a RedirectSignal or DenySignal, the onError callback resolves
77
+ // signals.captured and we can react immediately without waiting for
78
78
  // the full macrotask queue.
79
79
  //
80
80
  // The rejection chain for an async-wrapped page component:
@@ -88,9 +88,6 @@ export async function buildRscPayloadResponse(
88
88
  // (no signal). A 50ms ceiling timeout guards against edge cases
89
89
  // where onError never fires.
90
90
  const reader = rscStream.getReader();
91
- const signalDetected = new Promise<void>((resolve) => {
92
- signals.onSignal = resolve;
93
- });
94
91
 
95
92
  type RaceResult =
96
93
  | { type: 'data'; chunk: ReadableStreamReadResult<Uint8Array> }
@@ -108,14 +105,14 @@ export async function buildRscPayloadResponse(
108
105
  try {
109
106
  first = await Promise.race([
110
107
  pendingRead.then((chunk) => ({ type: 'data' as const, chunk })),
111
- signalDetected.then(() => ({ type: 'signal' as const })),
108
+ signals.captured.then(() => ({ type: 'signal' as const })),
112
109
  ]);
113
110
  } catch (_readError) {
114
- // RSC stream failed on first read — unhandled error in the page component.
111
+ // The RSC stream itself errored on first read. (A component's error is
112
+ // not this: it arrives as an error row in a stream that reads fine.)
115
113
  // Return an error response so the client can hard-navigate for the
116
114
  // SSR-rendered error page. See design/10-error-handling.md.
117
115
  reader.cancel().catch(() => {});
118
- signals.onSignal = undefined;
119
116
  return rscErrorEnvelope(500, responseHeaders);
120
117
  }
121
118
 
@@ -136,15 +133,14 @@ export async function buildRscPayloadResponse(
136
133
  await new Promise<void>((r) => setTimeout(r, 0));
137
134
  }
138
135
 
139
- // Detach the callback — the window has closed, and a signal arriving after
140
- // it is a row in the stream the client answers.
141
- signals.onSignal = undefined;
142
-
143
- // Check for redirect/deny signals detected during initial rendering
144
- const trackedRedirect = signals.redirectSignal as RedirectSignal | null;
145
- if (trackedRedirect) {
136
+ // The window has closed: signals are read once, here, and one arriving
137
+ // after this is a row in the stream the client answers.
138
+ //
139
+ // A redirect or an unplaced deny replaces the payload, so the stream is
140
+ // released before the signal is rethrown to the pipeline.
141
+ if (signals.redirectSignal) {
146
142
  reader.cancel().catch(() => {});
147
- return buildRedirectResponse(trackedRedirect, req, responseHeaders);
143
+ throw signals.redirectSignal;
148
144
  }
149
145
  // An addressed deny needs no fallback: the payload already carries its error
150
146
  // row, aimed at the boundary the client has mounted at that segment, which
@@ -156,47 +152,18 @@ export async function buildRscPayloadResponse(
156
152
  // of them. A deny nothing could place has no boundary that may claim it, so
157
153
  // its row would otherwise stream to a client with nothing to render it —
158
154
  // and it needs the fallback whether or not some other deny was addressed
159
- // first. See TIM-1356.
155
+ // first. See TIM-1356. The fallback also owns the hard-navigate answer
156
+ // for a deny AccessGate marked `_hardNavigate` (TIM-1363).
160
157
  if (signals.unplacedDeny) {
161
158
  reader.cancel().catch(() => {});
162
-
163
- // A skipped segment whose access just flipped to deny marks the signal
164
- // for hard-navigate: rendering a deny page here would execute the denied
165
- // segment's protected layout and place it inside cached client chrome
166
- // (TIM-1074). Return rscErrorEnvelope so the client hard-navigates for
167
- // a clean full render with correct deny page placement. See TIM-1363.
168
- if (signals.unplacedDeny._hardNavigate) {
169
- return rscErrorEnvelope(signals.unplacedDeny.status, responseHeaders);
170
- }
171
-
172
- // Read the denied segment index from ALS — set by AccessGate during
173
- // render. See TIM-1358, TIM-1365.
174
- const { getFirstDeniedSegmentIndex: getDeniedIdx } = await import('../deny-boundary.ts');
175
- return renderDenyPageAsRsc(
176
- signals.unplacedDeny,
177
- segments,
178
- layoutComponents as LayoutEntry[],
179
- req,
180
- responseHeaders,
181
- getDeniedIdx()
182
- );
183
- }
184
-
185
- // Check for unhandled errors (RenderError or plain Error).
186
- // These aren't redirect/deny signals but the RSC stream will be broken.
187
- // Return an error response so the client can hard-navigate for the
188
- // SSR-rendered error page. See design/10-error-handling.md
189
- // §"Error Page Rendering for Client Navigation".
190
- if (signals.renderError) {
191
- reader.cancel().catch(() => {});
192
- return rscErrorEnvelope(signals.renderError.status, responseHeaders);
159
+ throw signals.unplacedDeny;
193
160
  }
194
161
 
195
- // Extract the first chunk from the race result.
196
- // If the signal won the race but neither redirect nor deny was detected
197
- // (edge case), cancel the reader immediately rather than issuing a bare
198
- // read() that could hang forever if the RSC stream has stalled.
199
- // See TIM-519.
162
+ // Extract the first chunk from the race result. If a signal won the race,
163
+ // the redirect and the unplaced deny were rethrown above, so only an
164
+ // addressed deny reaches the second branch. The last branch is a fail-safe
165
+ // for a signal that is neither: it cancels the reader rather than issuing
166
+ // a bare read() that could hang forever on a stalled stream (TIM-519).
200
167
  let firstRead: ReadableStreamReadResult<Uint8Array>;
201
168
  if (first.type === 'data') {
202
169
  firstRead = first.chunk;
@@ -219,7 +186,7 @@ export async function buildRscPayloadResponse(
219
186
  // absent, and fabricating `done: true` here would produce the very empty
220
187
  // 4xx this branch exists to prevent.
221
188
  //
222
- // Nor can it fall to `renderDenyPageAsRsc`. That renderer re-resolves from
189
+ // Nor can it fall to the deny fallback. That renderer re-resolves from
223
190
  // the FULL leaf chain and wraps whatever it finds, ignoring `ownerKey` —
224
191
  // so an `/admin` denial addressed to a root `4xx.tsx` would come back as
225
192
  // `/admin/secret/403.tsx` with the denied layouts executed, which is the