@timber-js/app 0.2.0-alpha.207 → 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 (526) 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-BndF-3Td.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-DwQBrLBz.js → status-page-marker-gaihi0KZ.js} +140 -28
  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 +20 -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 +95 -108
  132. package/dist/client/internal.js.map +1 -1
  133. package/dist/client/navigation-commit.d.ts +20 -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 +3 -8
  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/segment-cache.d.ts +44 -4
  149. package/dist/client/segment-cache.d.ts.map +1 -1
  150. package/dist/client/ssr-data.d.ts +18 -64
  151. package/dist/client/ssr-data.d.ts.map +1 -1
  152. package/dist/client/state.d.ts +2 -5
  153. package/dist/client/state.d.ts.map +1 -1
  154. package/dist/client/use-pathname.d.ts +1 -1
  155. package/dist/config-types.d.ts +2 -1
  156. package/dist/config-types.d.ts.map +1 -1
  157. package/dist/config-validation.d.ts.map +1 -1
  158. package/dist/cookies/index.js +1 -1
  159. package/dist/dev-tools/dev-page-shell.d.ts +17 -0
  160. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
  161. package/dist/dev-tools/index.d.ts +1 -1
  162. package/dist/dev-tools/index.d.ts.map +1 -1
  163. package/dist/dev-tools/instrumentation.d.ts +17 -2
  164. package/dist/dev-tools/instrumentation.d.ts.map +1 -1
  165. package/dist/dev-tools/overlay.d.ts +6 -27
  166. package/dist/dev-tools/overlay.d.ts.map +1 -1
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +632 -373
  169. package/dist/index.js.map +1 -1
  170. package/dist/plugin-context.d.ts +26 -40
  171. package/dist/plugin-context.d.ts.map +1 -1
  172. package/dist/plugins/build-manifest.d.ts.map +1 -1
  173. package/dist/plugins/build-report.d.ts +15 -2
  174. package/dist/plugins/build-report.d.ts.map +1 -1
  175. package/dist/plugins/dev-server.d.ts.map +1 -1
  176. package/dist/plugins/entries.d.ts.map +1 -1
  177. package/dist/plugins/fonts.d.ts +19 -1
  178. package/dist/plugins/fonts.d.ts.map +1 -1
  179. package/dist/plugins/post-build.d.ts +110 -0
  180. package/dist/plugins/post-build.d.ts.map +1 -0
  181. package/dist/plugins/prebuilt-capture.d.ts +11 -4
  182. package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
  183. package/dist/plugins/prebuilt.d.ts +17 -1
  184. package/dist/plugins/prebuilt.d.ts.map +1 -1
  185. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  186. package/dist/plugins/react-resolve.d.ts +49 -0
  187. package/dist/plugins/react-resolve.d.ts.map +1 -0
  188. package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
  189. package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
  190. package/dist/plugins/shims.d.ts.map +1 -1
  191. package/dist/plugins/static-build.d.ts +32 -9
  192. package/dist/plugins/static-build.d.ts.map +1 -1
  193. package/dist/routing/codegen-write.d.ts +0 -9
  194. package/dist/routing/codegen-write.d.ts.map +1 -1
  195. package/dist/routing/index.js +2 -2
  196. package/dist/routing/segment-codegen.d.ts.map +1 -1
  197. package/dist/server/access-gate.d.ts.map +1 -1
  198. package/dist/server/action-handler.d.ts +5 -4
  199. package/dist/server/action-handler.d.ts.map +1 -1
  200. package/dist/server/actions.d.ts +46 -7
  201. package/dist/server/actions.d.ts.map +1 -1
  202. package/dist/server/als-registry.d.ts +58 -5
  203. package/dist/server/als-registry.d.ts.map +1 -1
  204. package/dist/server/children-interception.d.ts.map +1 -1
  205. package/dist/server/cookie-context.d.ts +2 -23
  206. package/dist/server/cookie-context.d.ts.map +1 -1
  207. package/dist/server/csp-nonce.d.ts +0 -9
  208. package/dist/server/csp-nonce.d.ts.map +1 -1
  209. package/dist/server/csrf.d.ts +27 -4
  210. package/dist/server/csrf.d.ts.map +1 -1
  211. package/dist/server/debug.d.ts +0 -1
  212. package/dist/server/debug.d.ts.map +1 -1
  213. package/dist/server/default-logger.d.ts +2 -1
  214. package/dist/server/default-logger.d.ts.map +1 -1
  215. package/dist/server/deny-boundary.d.ts +12 -6
  216. package/dist/server/deny-boundary.d.ts.map +1 -1
  217. package/dist/server/deny-renderer.d.ts +2 -2
  218. package/dist/server/deny-renderer.d.ts.map +1 -1
  219. package/dist/server/error-boundary-wrapper.d.ts +7 -3
  220. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  221. package/dist/server/fallback-error.d.ts +9 -2
  222. package/dist/server/fallback-error.d.ts.map +1 -1
  223. package/dist/server/head-response.d.ts +4 -4
  224. package/dist/server/html-injectors.d.ts.map +1 -1
  225. package/dist/server/index.d.ts +0 -1
  226. package/dist/server/index.d.ts.map +1 -1
  227. package/dist/server/index.js +3 -4
  228. package/dist/server/index.js.map +1 -1
  229. package/dist/server/instrumentation.d.ts +10 -3
  230. package/dist/server/instrumentation.d.ts.map +1 -1
  231. package/dist/server/internal.d.ts +1 -4
  232. package/dist/server/internal.d.ts.map +1 -1
  233. package/dist/server/internal.js +961 -581
  234. package/dist/server/internal.js.map +1 -1
  235. package/dist/server/json-status-response.d.ts +34 -0
  236. package/dist/server/json-status-response.d.ts.map +1 -0
  237. package/dist/server/logger.d.ts +26 -0
  238. package/dist/server/logger.d.ts.map +1 -1
  239. package/dist/server/param-coercion.d.ts +11 -6
  240. package/dist/server/param-coercion.d.ts.map +1 -1
  241. package/dist/server/pipeline-helpers.d.ts +95 -7
  242. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  243. package/dist/server/pipeline-interception.d.ts +11 -0
  244. package/dist/server/pipeline-interception.d.ts.map +1 -1
  245. package/dist/server/pipeline-outcome.d.ts +11 -1
  246. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  247. package/dist/server/pipeline-phases.d.ts +2 -2
  248. package/dist/server/pipeline-phases.d.ts.map +1 -1
  249. package/dist/server/pipeline.d.ts +23 -35
  250. package/dist/server/pipeline.d.ts.map +1 -1
  251. package/dist/server/prebuilt/capture-render.d.ts +25 -0
  252. package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
  253. package/dist/server/prebuilt/capture-routes.d.ts +37 -0
  254. package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
  255. package/dist/server/prebuilt/capture-state.d.ts +79 -35
  256. package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
  257. package/dist/server/prebuilt/lifetime.d.ts +38 -0
  258. package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
  259. package/dist/server/prebuilt/slots.d.ts +7 -0
  260. package/dist/server/prebuilt/slots.d.ts.map +1 -1
  261. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
  262. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  263. package/dist/server/prebuilt-runtime.d.ts.map +1 -1
  264. package/dist/server/primitives.d.ts +6 -81
  265. package/dist/server/primitives.d.ts.map +1 -1
  266. package/dist/server/react-cache-bridge.d.ts +59 -0
  267. package/dist/server/react-cache-bridge.d.ts.map +1 -0
  268. package/dist/server/react-cache-scope.d.ts +49 -0
  269. package/dist/server/react-cache-scope.d.ts.map +1 -0
  270. package/dist/server/render-timeout.d.ts +15 -0
  271. package/dist/server/render-timeout.d.ts.map +1 -1
  272. package/dist/server/render-utils.d.ts +9 -0
  273. package/dist/server/render-utils.d.ts.map +1 -1
  274. package/dist/server/request-context.d.ts +26 -5
  275. package/dist/server/request-context.d.ts.map +1 -1
  276. package/dist/server/route-element-builder.d.ts.map +1 -1
  277. package/dist/server/route-handler.d.ts.map +1 -1
  278. package/dist/server/route-matcher.d.ts +7 -0
  279. package/dist/server/route-matcher.d.ts.map +1 -1
  280. package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
  281. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
  282. package/dist/server/rsc-entry/api-handler.d.ts +7 -0
  283. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  284. package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
  285. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  286. package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
  287. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  288. package/dist/server/rsc-entry/helpers.d.ts +0 -1
  289. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  290. package/dist/server/rsc-entry/index.d.ts +5 -15
  291. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  292. package/dist/server/rsc-entry/render-route.d.ts +5 -6
  293. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  294. package/dist/server/rsc-entry/render-signals.d.ts +65 -0
  295. package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
  296. package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
  297. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  298. package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
  299. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  300. package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
  301. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  302. package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
  303. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  304. package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
  305. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  306. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
  307. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
  308. package/dist/server/signal-identity.d.ts +43 -0
  309. package/dist/server/signal-identity.d.ts.map +1 -0
  310. package/dist/server/slot-resolver.d.ts +4 -3
  311. package/dist/server/slot-resolver.d.ts.map +1 -1
  312. package/dist/server/slot-subtree-contain.d.ts.map +1 -1
  313. package/dist/server/ssr-bridge-types.d.ts +91 -53
  314. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  315. package/dist/server/ssr-entry.d.ts +8 -5
  316. package/dist/server/ssr-entry.d.ts.map +1 -1
  317. package/dist/server/ssr-render.d.ts +26 -40
  318. package/dist/server/ssr-render.d.ts.map +1 -1
  319. package/dist/server/ssr-wrappers.d.ts +1 -1
  320. package/dist/server/static-generator.d.ts.map +1 -1
  321. package/dist/server/stream-utils.d.ts +12 -0
  322. package/dist/server/stream-utils.d.ts.map +1 -1
  323. package/dist/server/tracing.d.ts +12 -16
  324. package/dist/server/tracing.d.ts.map +1 -1
  325. package/dist/server/types.d.ts +1 -1
  326. package/dist/server/version-skew.d.ts +3 -3
  327. package/dist/shared/csrf-reject.d.ts +16 -0
  328. package/dist/shared/csrf-reject.d.ts.map +1 -0
  329. package/dist/shared/error-digest.d.ts +28 -0
  330. package/dist/shared/error-digest.d.ts.map +1 -0
  331. package/dist/shared/payload-root.d.ts +11 -10
  332. package/dist/shared/payload-root.d.ts.map +1 -1
  333. package/dist/shared/rsc-payload-path.d.ts +6 -0
  334. package/dist/shared/rsc-payload-path.d.ts.map +1 -1
  335. package/dist/utils/write-file-atomic.d.ts +17 -0
  336. package/dist/utils/write-file-atomic.d.ts.map +1 -0
  337. package/docs/api/30-api-server.mdx +17 -14
  338. package/docs/api/32-api-cache.mdx +51 -23
  339. package/docs/api/34-api-config.mdx +34 -6
  340. package/docs/api/36-cli.mdx +11 -1
  341. package/docs/learn/03-fetching-data.mdx +17 -1
  342. package/docs/learn/04-access-control.mdx +1 -1
  343. package/docs/learn/10-caching.mdx +29 -11
  344. package/docs/learn/11-middleware.mdx +8 -2
  345. package/docs/learn/12-error-handling.mdx +6 -1
  346. package/package.json +7 -3
  347. package/src/adapters/build-output-helper.ts +55 -53
  348. package/src/adapters/canonicalize-module.ts +29 -0
  349. package/src/adapters/cloudflare.ts +105 -63
  350. package/src/adapters/compress-module.ts +16 -5
  351. package/src/adapters/fs-identity.ts +2 -3
  352. package/src/adapters/nitro-presets.ts +0 -15
  353. package/src/adapters/nitro-preview.ts +272 -136
  354. package/src/adapters/nitro.ts +119 -82
  355. package/src/adapters/shared.ts +23 -14
  356. package/src/adapters/types.ts +110 -21
  357. package/src/analyze/graph-cache.ts +3 -4
  358. package/src/cache/json-lossy-check.ts +3 -9
  359. package/src/cache/singleflight.ts +5 -2
  360. package/src/cache/sizeof.ts +3 -1
  361. package/src/cache/tag-aware-handler.ts +43 -26
  362. package/src/cli-check.ts +8 -98
  363. package/src/cli-context.ts +119 -0
  364. package/src/cli.ts +19 -28
  365. package/src/client/browser-dev.ts +1 -1
  366. package/src/client/browser-entry/action-dispatch.ts +26 -4
  367. package/src/client/browser-entry/hydrate.ts +53 -58
  368. package/src/client/browser-entry/index.ts +16 -27
  369. package/src/client/browser-entry/post-hydration.ts +6 -40
  370. package/src/client/browser-entry/router-init.ts +66 -84
  371. package/src/client/error-boundary.tsx +9 -41
  372. package/src/client/error-reconstituter.tsx +10 -5
  373. package/src/client/history.ts +35 -21
  374. package/src/client/index.ts +0 -1
  375. package/src/client/internal.ts +2 -7
  376. package/src/client/navigation-commit.ts +41 -18
  377. package/src/client/navigation-context.ts +3 -39
  378. package/src/client/react-root.ts +3 -2
  379. package/src/client/router-pipeline.ts +96 -132
  380. package/src/client/router-types.ts +46 -44
  381. package/src/client/router-url.ts +32 -0
  382. package/src/client/router.ts +62 -21
  383. package/src/client/rsc-fetch.ts +117 -155
  384. package/src/client/segment-cache.ts +110 -11
  385. package/src/client/ssr-data.ts +19 -80
  386. package/src/client/state.ts +2 -9
  387. package/src/client/use-pathname.ts +1 -1
  388. package/src/config-types.ts +2 -1
  389. package/src/config-validation.ts +2 -1
  390. package/src/dev-tools/dev-page-shell.ts +18 -0
  391. package/src/dev-tools/index.ts +0 -2
  392. package/src/dev-tools/instrumentation.ts +50 -2
  393. package/src/dev-tools/overlay.ts +8 -238
  394. package/src/index.ts +26 -14
  395. package/src/plugin-context.ts +39 -40
  396. package/src/plugins/build-manifest.ts +4 -11
  397. package/src/plugins/build-report.ts +70 -70
  398. package/src/plugins/dev-server.ts +24 -44
  399. package/src/plugins/entries.ts +2 -1
  400. package/src/plugins/fonts.ts +35 -7
  401. package/src/plugins/post-build.ts +327 -0
  402. package/src/plugins/prebuilt-capture.ts +28 -32
  403. package/src/plugins/prebuilt.ts +54 -39
  404. package/src/plugins/prerender-sugar.ts +0 -4
  405. package/src/plugins/react-resolve.ts +149 -0
  406. package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
  407. package/src/plugins/shims.ts +1 -0
  408. package/src/plugins/static-build.ts +42 -74
  409. package/src/routing/codegen-write.ts +25 -3
  410. package/src/routing/segment-codegen.ts +3 -2
  411. package/src/rsc-runtime/vendor-types.d.ts +8 -0
  412. package/src/server/access-gate.tsx +2 -1
  413. package/src/server/action-client.ts +1 -1
  414. package/src/server/action-handler.ts +253 -110
  415. package/src/server/actions.ts +73 -25
  416. package/src/server/als-registry.ts +73 -5
  417. package/src/server/chain-url-parts.ts +1 -1
  418. package/src/server/children-interception.ts +2 -1
  419. package/src/server/cookie-context.ts +18 -48
  420. package/src/server/csp-nonce.ts +0 -12
  421. package/src/server/csrf.ts +140 -8
  422. package/src/server/debug.ts +0 -1
  423. package/src/server/default-logger.ts +2 -1
  424. package/src/server/deny-boundary.ts +25 -13
  425. package/src/server/deny-renderer.ts +30 -97
  426. package/src/server/error-boundary-wrapper.ts +7 -3
  427. package/src/server/fallback-error.ts +26 -11
  428. package/src/server/flight-scripts.ts +1 -1
  429. package/src/server/head-response.ts +4 -4
  430. package/src/server/html-injector-core.ts +2 -2
  431. package/src/server/html-injectors.ts +2 -4
  432. package/src/server/index.ts +0 -4
  433. package/src/server/instrumentation.ts +10 -3
  434. package/src/server/internal.ts +1 -6
  435. package/src/server/json-status-response.ts +105 -0
  436. package/src/server/logger.ts +39 -3
  437. package/src/server/param-coercion.ts +15 -12
  438. package/src/server/pipeline-helpers.ts +257 -12
  439. package/src/server/pipeline-interception.ts +133 -0
  440. package/src/server/pipeline-outcome.ts +103 -31
  441. package/src/server/pipeline-phases.ts +127 -237
  442. package/src/server/pipeline.ts +204 -207
  443. package/src/server/prebuilt/capture-render.ts +118 -0
  444. package/src/server/prebuilt/capture-routes.ts +104 -0
  445. package/src/server/prebuilt/capture-state.ts +155 -48
  446. package/src/server/prebuilt/lifetime.ts +151 -0
  447. package/src/server/prebuilt/slots.ts +14 -2
  448. package/src/server/prebuilt/synthetic-store.ts +3 -0
  449. package/src/server/prebuilt-builder.ts +30 -320
  450. package/src/server/prebuilt-runtime.ts +125 -129
  451. package/src/server/primitives.ts +8 -168
  452. package/src/server/react-cache-bridge.ts +124 -0
  453. package/src/server/react-cache-scope.ts +104 -0
  454. package/src/server/render-timeout.ts +20 -0
  455. package/src/server/render-utils.ts +11 -1
  456. package/src/server/request-context.ts +36 -9
  457. package/src/server/route-element-builder.ts +11 -6
  458. package/src/server/route-handler.ts +36 -23
  459. package/src/server/route-matcher.ts +15 -1
  460. package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
  461. package/src/server/rsc-entry/api-handler.ts +27 -103
  462. package/src/server/rsc-entry/deny-fallback.ts +93 -26
  463. package/src/server/rsc-entry/error-renderer.ts +39 -91
  464. package/src/server/rsc-entry/helpers.ts +2 -4
  465. package/src/server/rsc-entry/index.ts +64 -58
  466. package/src/server/rsc-entry/render-route.ts +15 -80
  467. package/src/server/rsc-entry/render-signals.ts +108 -0
  468. package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
  469. package/src/server/rsc-entry/rsc-payload.ts +28 -61
  470. package/src/server/rsc-entry/rsc-stream.ts +113 -213
  471. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  472. package/src/server/rsc-entry/ssr-renderer.ts +182 -263
  473. package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
  474. package/src/server/signal-identity.ts +112 -0
  475. package/src/server/slot-resolver.ts +18 -18
  476. package/src/server/slot-subtree-contain.ts +2 -1
  477. package/src/server/ssr-bridge-types.ts +92 -56
  478. package/src/server/ssr-entry.ts +87 -111
  479. package/src/server/ssr-render.ts +55 -64
  480. package/src/server/ssr-wrappers.tsx +2 -2
  481. package/src/server/static-generator.ts +7 -42
  482. package/src/server/static-not-found.ts +3 -3
  483. package/src/server/stream-utils.ts +51 -0
  484. package/src/server/tracing.ts +58 -75
  485. package/src/server/types.ts +1 -1
  486. package/src/server/version-skew.ts +5 -5
  487. package/src/shared/csrf-reject.ts +15 -0
  488. package/src/shared/error-digest.ts +46 -0
  489. package/src/shared/payload-root.ts +11 -10
  490. package/src/shared/rsc-payload-path.ts +8 -1
  491. package/src/utils/write-file-atomic.ts +32 -0
  492. package/dist/_chunks/actions-jNrXdzgs.js +0 -346
  493. package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
  494. package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
  495. package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
  496. package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
  497. package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
  498. package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
  499. package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
  500. package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
  501. package/dist/_chunks/error-boundary-BndF-3Td.js.map +0 -1
  502. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
  503. package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
  504. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
  505. package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
  506. package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
  507. package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
  508. package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
  509. package/dist/_chunks/segment-context-D9_89u34.js +0 -34
  510. package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
  511. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
  512. package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
  513. package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
  514. package/dist/_chunks/state-FippDgxN.js.map +0 -1
  515. package/dist/_chunks/status-page-marker-DwQBrLBz.js.map +0 -1
  516. package/dist/client/types.d.ts +0 -14
  517. package/dist/client/types.d.ts.map +0 -1
  518. package/dist/plugins/adapter-build.d.ts +0 -38
  519. package/dist/plugins/adapter-build.d.ts.map +0 -1
  520. package/dist/server/asset-headers.d.ts +0 -32
  521. package/dist/server/asset-headers.d.ts.map +0 -1
  522. package/dist/server/dev-source-map.d.ts +0 -22
  523. package/dist/server/dev-source-map.d.ts.map +0 -1
  524. package/src/client/types.ts +0 -21
  525. package/src/server/asset-headers.ts +0 -59
  526. package/src/server/dev-source-map.ts +0 -31
@@ -2,10 +2,10 @@
2
2
  * Server action primitives: revalidatePath, revalidateTag, and the action handler.
3
3
  *
4
4
  * - revalidatePath(path) re-renders the route at that path and returns the RSC
5
- * flight payload for inline reconciliation.
6
- * - revalidateTag(tag) invalidates timber.cache entries by tag.
7
- *
8
- * Both are callable from anywhere on the server — actions, API routes, handlers.
5
+ * flight payload for inline reconciliation. Server actions only.
6
+ * - revalidateTag(tag) invalidates timber.cache entries by tag. Callable from
7
+ * any server code: deferred to the end of the action inside one, immediate
8
+ * anywhere else.
9
9
  *
10
10
  * The action handler processes incoming action requests, validates CSRF,
11
11
  * enforces body limits, executes the action, and returns the response
@@ -16,9 +16,10 @@
16
16
 
17
17
  import { cache } from '../cache/cache-api.ts';
18
18
  import { canonicalize } from './canonicalize.ts';
19
- import { isDenySignal, isRedirectSignal } from './primitives.ts';
19
+ import { isDenySignal, isRedirectSignal } from './signal-identity.ts';
20
20
  import { withSpan } from './tracing.ts';
21
21
  import { revalidationAls, type RevalidationState } from './als-registry.ts';
22
+ import type { ReactCacheScope } from './react-cache-scope.ts';
22
23
  // ─── Types ───────────────────────────────────────────────────────────────
23
24
 
24
25
  /** Result of rendering a revalidation — payload root before RSC serialization. */
@@ -28,11 +29,33 @@ export interface RevalidationResult {
28
29
  * ordinary route payload. The client splits it in `applyActionResult`.
29
30
  */
30
31
  payload: unknown;
32
+ /**
33
+ * The `React.cache` scope the target route's middleware ran in. The
34
+ * revalidated tree renders in it, so middleware, access.ts and components
35
+ * share one scope — fresh, never the action body's (TIM-1529).
36
+ */
37
+ reactCacheScope: ReactCacheScope;
31
38
  }
32
39
 
33
40
  /** Renderer function that builds a React element tree for a given path. */
34
41
  export type RevalidateRenderer = (path: string) => Promise<RevalidationResult>;
35
42
 
43
+ /**
44
+ * Thrown by a `RevalidateRenderer` that decided not to render: the path
45
+ * was rejected, its params failed coercion, or its middleware answered
46
+ * with a `Response` that cannot become an element tree. `executeAction`
47
+ * drops the revalidation — the action result is still delivered, with no
48
+ * `_tree` piggybacked — and, because the drop was a decision, does not
49
+ * return it as an error to report. Identified by `instanceof`, so the
50
+ * message text never reaches clients.
51
+ */
52
+ export class RevalidationDropped extends Error {
53
+ constructor(message: string) {
54
+ super(message);
55
+ this.name = 'RevalidationDropped';
56
+ }
57
+ }
58
+
36
59
  // Re-export the type from the registry for public API consumers.
37
60
  export type { RevalidationState } from './als-registry.ts';
38
61
 
@@ -67,6 +90,14 @@ export interface ActionHandlerResult {
67
90
  redirectTo?: string;
68
91
  /** Redirect status code. */
69
92
  redirectStatus?: number;
93
+ /**
94
+ * Errors the action survived after its body returned: a `revalidateTag`
95
+ * invalidation that rejected, or a `revalidatePath` render that threw.
96
+ * Each is already logged. They are returned rather than reported here
97
+ * because reporting needs the request, which the caller owns; the caller
98
+ * passes each to `onRequestError` once.
99
+ */
100
+ revalidationErrors: unknown[];
70
101
  }
71
102
 
72
103
  // ─── Revalidation State ──────────────────────────────────────────────────
@@ -83,49 +114,56 @@ export function _runWithRevalidationState<T>(state: RevalidationState, fn: () =>
83
114
  return revalidationAls.run(state, fn);
84
115
  }
85
116
 
86
- /**
87
- * Get the current revalidation state. Throws if called outside an action context.
88
- * @internal
89
- */
90
- function getRevalidationState(): RevalidationState {
91
- const state = revalidationAls.getStore();
92
- if (!state) {
93
- throw new Error(
94
- 'revalidatePath/revalidateTag called outside of a server action context. ' +
95
- 'These functions can only be called during action execution.'
96
- );
97
- }
98
- return state;
99
- }
100
-
101
117
  // ─── Public API ──────────────────────────────────────────────────────────
102
118
 
103
119
  /**
104
120
  * Re-render the route at `path` and include the RSC flight payload in the
105
121
  * action response. The client reconciles inline — no separate fetch needed.
106
122
  *
107
- * Can be called from server actions, API routes, or any server-side context.
123
+ * Only callable inside a server action: it attaches a render to the action
124
+ * response, and nothing else has one. To refresh cached data from a
125
+ * `route.ts` handler, a webhook, or a job, use `revalidateTag()` or
126
+ * `cache.invalidate()`.
108
127
  *
109
128
  * @param path - The path to re-render (e.g. '/dashboard', '/todos').
110
129
  */
111
130
  export function revalidatePath(path: string): void {
112
- const state = getRevalidationState();
131
+ const state = revalidationAls.getStore();
132
+ if (!state || state.closed) {
133
+ throw new Error(
134
+ 'revalidatePath() can only be called inside a server action: it re-renders ' +
135
+ 'the route into the action response, and there is no action response here. ' +
136
+ 'To refresh cached data from a route handler or other server code, call ' +
137
+ 'revalidateTag() or cache.invalidate() for the tags the route reads.'
138
+ );
139
+ }
113
140
  if (!state.paths.includes(path)) {
114
141
  state.paths.push(path);
115
142
  }
116
143
  }
117
144
 
118
145
  /**
119
- * Invalidate all timber.cache entries tagged with `tag`.
146
+ * Invalidate all timber.cache entries tagged with `tag`, and tombstone the
147
+ * pre-rendered component seeds that carry it.
120
148
  * Does not return a payload — the next request for an invalidated entry re-executes.
121
149
  *
150
+ * Callable from any server code. Inside a server action the invalidation is
151
+ * deferred until the action body returns, so a `revalidatePath()` render in
152
+ * the same action reads fresh data; the returned promise resolves at once.
153
+ * Anywhere else — a `route.ts` webhook, a job, or background work an action
154
+ * started that runs after the action body returned — it is
155
+ * `cache.invalidate({ tag })`, and the promise settles when the invalidation
156
+ * has. Await it before responding.
157
+ *
122
158
  * @param tag - The cache tag to invalidate (e.g. 'products', 'user:123').
123
159
  */
124
- export function revalidateTag(tag: string): void {
125
- const state = getRevalidationState();
160
+ export function revalidateTag(tag: string): Promise<void> {
161
+ const state = revalidationAls.getStore();
162
+ if (!state || state.closed) return cache.invalidate({ tag });
126
163
  if (!state.tags.includes(tag)) {
127
164
  state.tags.push(tag);
128
165
  }
166
+ return Promise.resolve();
129
167
  }
130
168
 
131
169
  // ─── Helpers ────────────────────────────────────────────────────────────
@@ -157,6 +195,7 @@ export async function executeAction(
157
195
  spanMeta?: { actionFile?: string; actionName?: string }
158
196
  ): Promise<ActionHandlerResult> {
159
197
  const state: RevalidationState = { paths: [], tags: [] };
198
+ const revalidationErrors: unknown[] = [];
160
199
  let actionResult: unknown;
161
200
  let redirectTo: string | undefined;
162
201
  let redirectStatus: number | undefined;
@@ -180,6 +219,10 @@ export async function executeAction(
180
219
  } else {
181
220
  throw error;
182
221
  }
222
+ } finally {
223
+ // From here `paths` and `tags` are snapshotted below (or abandoned on
224
+ // a throw); later calls from un-awaited work must not queue into them.
225
+ state.closed = true;
183
226
  }
184
227
  });
185
228
 
@@ -201,6 +244,7 @@ export async function executeAction(
201
244
  for (const r of results) {
202
245
  if (r.status === 'rejected') {
203
246
  console.error('[timber] revalidateTag invalidation failed:', r.reason);
247
+ revalidationErrors.push(r.reason);
204
248
  }
205
249
  }
206
250
  }
@@ -232,8 +276,11 @@ export async function executeAction(
232
276
  console.error(
233
277
  `[timber] revalidatePath dropped — target middleware denied (status ${renderError.status})`
234
278
  );
279
+ } else if (renderError instanceof RevalidationDropped) {
280
+ console.error(`[timber] ${renderError.message}`);
235
281
  } else {
236
282
  console.error('[timber] revalidatePath render failed:', renderError);
283
+ revalidationErrors.push(renderError);
237
284
  }
238
285
  }
239
286
  }
@@ -243,6 +290,7 @@ export async function executeAction(
243
290
  actionResult,
244
291
  revalidation,
245
292
  invalidatedPaths,
293
+ revalidationErrors,
246
294
  ...(redirectTo ? { redirectTo, redirectStatus } : {}),
247
295
  };
248
296
  }
@@ -66,6 +66,14 @@ export const requestContextAls = getOrCreateAls<RequestContextStore>(
66
66
  );
67
67
 
68
68
  export interface RequestContextStore {
69
+ /**
70
+ * The request this context was opened for, or `null` in the build-time
71
+ * capture store, where there is none. Read only to report a failed
72
+ * `cache.component` background re-render, which outlives the code that had the request
73
+ * in hand (design/17 §"Which errors reach it"). Everything a page may read
74
+ * has its own field below.
75
+ */
76
+ request: Request | null;
69
77
  /** Incoming request headers (read-only view). */
70
78
  headers: Headers;
71
79
  /** Raw cookie header string, parsed lazily into a Map on first access. */
@@ -167,16 +175,26 @@ export interface CookieEntry {
167
175
  // Used by: tracing.ts (getTraceId(), getSpanId())
168
176
  // Design doc: design/17-logging.md
169
177
 
178
+ /**
179
+ * One trace scope. The pipeline opens the request's scope; withSpan() opens a
180
+ * copy per span, so the span pointers below always name the span the code is
181
+ * running in, however sibling spans interleave (TIM-1538).
182
+ */
170
183
  export interface TraceStore {
171
- /** 32-char lowercase hex trace ID (OTEL or UUID fallback). */
172
- traceId: string;
173
- /** OTEL span ID if available, undefined otherwise. */
184
+ /**
185
+ * The request's trace, shared by reference by every span scope in it.
186
+ * `traceId` is the 32-char lowercase hex trace ID (OTEL or UUID fallback);
187
+ * replaceTraceId() swaps it from inside the first span, and code outside
188
+ * that span (the request's completion log) sees the swap.
189
+ */
190
+ request: { traceId: string };
191
+ /** The enclosing OTEL span's ID if an SDK is active, undefined otherwise. */
174
192
  spanId?: string;
175
193
  /**
176
- * Innermost active native platform span (e.g. Cloudflare's `Span` from
194
+ * The enclosing native platform span (e.g. Cloudflare's `Span` from
177
195
  * tracing.enterSpan()). Tracked so setSpanAttribute() can set attributes
178
196
  * after span creation — the platform API has no getActiveSpan() equivalent.
179
- * Saved/restored by withSpan() around each callback. See TIM-1135.
197
+ * See TIM-1135.
180
198
  */
181
199
  platformSpan?: import('./tracing.ts').PlatformSpan;
182
200
  }
@@ -204,6 +222,13 @@ export interface RevalidationState {
204
222
  paths: string[];
205
223
  /** Tags to invalidate (populated by revalidateTag calls). */
206
224
  tags: string[];
225
+ /**
226
+ * Set once the action body has settled. ALS still hands this state to
227
+ * work the action started and did not await (a `waitUntil()` job), but
228
+ * `paths` and `tags` are no longer read, so a late `revalidateTag` must
229
+ * invalidate immediately instead of queueing into a list nobody drains.
230
+ */
231
+ closed?: boolean;
207
232
  }
208
233
 
209
234
  /** @internal — import via actions.ts public API */
@@ -255,3 +280,46 @@ export interface WorkersCachePurgeCtx {
255
280
  export const workersCachePurgeAls = getOrCreateAls<WorkersCachePurgeCtx>(
256
281
  Symbol.for('timber:workers-cache-purge-als')
257
282
  );
283
+
284
+ // ─── React.cache Scope ───────────────────────────────────────────────────
285
+ // Used by: react-cache-bridge.ts (runWithReactCacheScope(), the patched
286
+ // getCacheForType on Flight's dispatcher)
287
+ // Design doc: design/02-rendering-pipeline.md §"Cache Scoping Model"
288
+
289
+ /**
290
+ * One request's `React.cache` storage — the Map React's `cache()` hands to
291
+ * `getCacheForType`, owned by timber instead of by a Flight `Request` so
292
+ * `middleware.ts`, `proxy.ts`, and route handlers share it with the render.
293
+ */
294
+ export type ReactCacheScope = Map<() => unknown, unknown>;
295
+
296
+ /** @internal — import via react-cache-bridge.ts public API */
297
+ export const reactCacheScopeAls = getOrCreateAls<ReactCacheScope>(
298
+ Symbol.for('timber:react-cache-scope-als')
299
+ );
300
+
301
+ // ─── Prebuilt Capture ────────────────────────────────────────────────────
302
+ // Used by: prebuilt/capture-state.ts (createCaptureScope(), noteWrapperRender())
303
+ // Design doc: design/45-cache-lifetimes.md §Nesting Semantics
304
+
305
+ /**
306
+ * One in-flight `cache.component` payload capture — a build-time entry or
307
+ * a request-time re-render. Scoped to the capture's async context so a
308
+ * concurrent request's render does not observe it.
309
+ */
310
+ export interface PrebuiltCaptureStore {
311
+ /** The component being captured. */
312
+ outerId: string;
313
+ /**
314
+ * Props half of the captured entry's cache key (null when unkeyable).
315
+ * Rendering `outerId` again with this key is a cycle (TIM-1547).
316
+ */
317
+ outerPropsKey: string | null;
318
+ /** Wrapped components that rendered inside this capture, by component id. */
319
+ nested: Map<string, import('./prebuilt/capture-state.ts').NestedRecord>;
320
+ }
321
+
322
+ /** @internal — import via prebuilt/capture-state.ts */
323
+ export const prebuiltCaptureAls = getOrCreateAls<PrebuiltCaptureStore>(
324
+ Symbol.for('timber:prebuilt-capture-als')
325
+ );
@@ -129,7 +129,7 @@ export function consumedUrlParts(
129
129
  index: number,
130
130
  match: RouteMatch
131
131
  ): string[] {
132
- const rawParams = match.rawSegmentParams ?? match.segmentParams ?? {};
132
+ const rawParams = match.rawSegmentParams;
133
133
  const partsThrough = (from: number, to: number) =>
134
134
  extractUrlParts(segments.slice(from, to + 1), rawParams);
135
135
 
@@ -77,7 +77,8 @@ export function createInterceptedRouteMatcher(root: ManifestSegmentNode): Interc
77
77
  // `validateInterceptionPlacement` rejects a dynamic one at build time,
78
78
  // precisely because the intercepted URL carries no value to bind it
79
79
  // with. So the intercepting subtree's params are the whole record.
80
- segmentParams: result.slotParams,
80
+ rawSegmentParams: result.slotParams,
81
+ segmentParams: { ...result.slotParams },
81
82
  middlewareChain: collectMiddlewareChain(segments),
82
83
  };
83
84
  };
@@ -2,8 +2,8 @@
2
2
  * Cookie Context — per-request cookie API and on-the-wire helpers.
3
3
  *
4
4
  * Split out of `request-context.ts` (TIM-853) so the cookie subsystem
5
- * — encoding contract, options grammar, parser, serializer, RYW map,
6
- * and rerender seed — lives in one file. The headers/scope/params APIs
5
+ * — encoding contract, options grammar, parser, serializer, and RYW map
6
+ * — lives in one file. The headers/scope/params APIs
7
7
  * stay in `request-context.ts` and call into this module via the
8
8
  * exported helpers.
9
9
  *
@@ -14,6 +14,11 @@
14
14
 
15
15
  import { requestContextAls, type RequestContextStore } from './als-registry.ts';
16
16
  import { isDebug } from './debug.ts';
17
+ import {
18
+ ANY_COOKIE,
19
+ noteCookieReadForReactCache,
20
+ warnIfCachedCookieIsWritten,
21
+ } from './react-cache-scope.ts';
17
22
  import {
18
23
  assertValidCookieName,
19
24
  assertValidCookieValue,
@@ -69,16 +74,22 @@ export function getCookieJar(): RequestCookies {
69
74
 
70
75
  const map = store.parsedCookies;
71
76
  return {
77
+ // Reads are noted (dev only) so a later write of the same cookie can
78
+ // warn if React.cache may have memoized the old value (TIM-1529 D3).
72
79
  get(name: string): string | undefined {
80
+ noteCookieReadForReactCache(name);
73
81
  return map.get(name);
74
82
  },
75
83
  has(name: string): boolean {
84
+ noteCookieReadForReactCache(name);
76
85
  return map.has(name);
77
86
  },
78
87
  getAll(): Array<{ name: string; value: string }> {
88
+ noteCookieReadForReactCache(ANY_COOKIE);
79
89
  return Array.from(map.entries()).map(([name, value]) => ({ name, value }));
80
90
  },
81
91
  get size(): number {
92
+ noteCookieReadForReactCache(ANY_COOKIE);
82
93
  return map.size;
83
94
  },
84
95
 
@@ -148,6 +159,7 @@ export function getCookieJar(): RequestCookies {
148
159
  // exactly what the developer wrote — never the encoded form.
149
160
  // For `{ raw: true }`, the wire form IS the logical form.
150
161
  map.set(name, raw ? wireValue : value);
162
+ warnIfCachedCookieIsWritten(name);
151
163
  },
152
164
 
153
165
  setFromHeaders(headers: Headers): void {
@@ -203,6 +215,7 @@ export function getCookieJar(): RequestCookies {
203
215
  store.cookieJar.set(name, { name, value: '', options: opts });
204
216
  // Remove from read view
205
217
  map.delete(name);
218
+ warnIfCachedCookieIsWritten(name);
206
219
  },
207
220
 
208
221
  clear(): void {
@@ -217,9 +230,11 @@ export function getCookieJar(): RequestCookies {
217
230
  });
218
231
  }
219
232
  map.clear();
233
+ warnIfCachedCookieIsWritten(ANY_COOKIE);
220
234
  },
221
235
 
222
236
  toString(): string {
237
+ noteCookieReadForReactCache(ANY_COOKIE);
223
238
  // Re-encode values when serializing as a Cookie header — the
224
239
  // RYW map holds decoded logical values, but a Cookie header has
225
240
  // to satisfy `cookie-octet`. Mirror the auto-encode contract on
@@ -341,52 +356,6 @@ const DEFAULT_COOKIE_OPTIONS: CookieOptions = {
341
356
 
342
357
  // ─── Framework-Internal Helpers ───────────────────────────────────────────
343
358
 
344
- /**
345
- * Per-request seed map of cookie name → value, registered out-of-band so the
346
- * pipeline's `runWithRequestContext` call can pick it up without changing
347
- * the function's calling convention. Stored in a WeakMap keyed by the
348
- * synthetic Request object built for the rerender path, so the seed lives
349
- * exactly as long as the request and is collected with it.
350
- *
351
- * The seed exists to eliminate the parse/serialize round-trip on the no-JS
352
- * form-rerender path — see ONGOING_SECURITY.md H-3 (TIM-868). The action's
353
- * post-mutation RYW snapshot is threaded directly into the rerender scope's
354
- * `parsedCookies` map, bypassing `parseCookieHeader` entirely.
355
- */
356
- const seededRequestCookies = new WeakMap<Request, Map<string, string>>();
357
-
358
- /**
359
- * Register a pre-parsed cookie map to use as the request context seed for
360
- * the next `runWithRequestContext(req, …)` call with this exact `req`.
361
- *
362
- * Used by the no-JS form-rerender dispatcher in
363
- * `rsc-entry/wrap-action-dispatch.ts` to thread the action's post-mutation
364
- * cookie state into the rerender scope without serializing back through a
365
- * `Cookie:` header. See TIM-868 / TIM-837.
366
- *
367
- * @internal — framework use only.
368
- */
369
- export function seedRequestCookies(req: Request, cookies: Map<string, string>): void {
370
- // Defensive copy: callers must not be able to mutate the rerender scope's
371
- // map after seeding, and the rerender scope must not mutate the snapshot
372
- // we hand back to other observers.
373
- seededRequestCookies.set(req, new Map(cookies));
374
- }
375
-
376
- /**
377
- * Pop the seed (if any) for `req` and return it. Called from
378
- * `runWithRequestContext` exactly once per request — the seed is consumed
379
- * eagerly so it cannot leak into a hypothetical future re-use of the same
380
- * Request reference.
381
- *
382
- * @internal — framework use only.
383
- */
384
- export function consumeSeededCookies(req: Request): Map<string, string> | undefined {
385
- const seed = seededRequestCookies.get(req);
386
- if (seed) seededRequestCookies.delete(req);
387
- return seed;
388
- }
389
-
390
359
  /**
391
360
  * Build a Map of cookie name → value reflecting the current request's
392
361
  * read-your-own-writes state. Includes incoming cookies plus any
@@ -472,6 +441,7 @@ function setRaw(
472
441
  // the caller. See design/29-cookies.md §"Cookie Attribute Validation".
473
442
  assertValidCookieOptions(options);
474
443
  store.cookieJar.set(name, { name, value, options });
444
+ warnIfCachedCookieIsWritten(name);
475
445
  // Deletion cookies (Max-Age=0) should not appear in the read map.
476
446
  if (options.maxAge === 0) {
477
447
  readMap.delete(name);
@@ -56,15 +56,3 @@ export function requestCspNonce(): string {
56
56
  export function getCspNonce(): string | undefined {
57
57
  return requestContextAls.getStore()?.cspNonce;
58
58
  }
59
-
60
- /**
61
- * The ` nonce="…"` attribute fragment for a timber-generated `<script>` tag,
62
- * or `''` when the request has no nonce. Callers interpolate it directly
63
- * after the tag name: `` `<script${nonceAttr(nonce)}>` ``.
64
- *
65
- * The value comes from `generateNonce` and is base64, so no attribute
66
- * escaping is required.
67
- */
68
- export function nonceAttr(nonce: string | undefined): string {
69
- return nonce ? ` nonce="${nonce}"` : '';
70
- }
@@ -9,6 +9,9 @@
9
9
  * See design/13-security.md §"Security Testing Checklist" #6
10
10
  */
11
11
 
12
+ import { logCsrfRejected } from './logger.ts';
13
+ import { CSRF_REJECT_HEADER, CSRF_REJECT_VALUE } from '../shared/csrf-reject.ts';
14
+
12
15
  // ─── Types ────────────────────────────────────────────────────────────────
13
16
 
14
17
  export interface CsrfConfig {
@@ -18,7 +21,31 @@ export interface CsrfConfig {
18
21
  csrf?: boolean;
19
22
  }
20
23
 
21
- export type CsrfResult = { ok: true } | { ok: false; status: 403 };
24
+ /** Why a request failed the Origin check — one value per rejection path. */
25
+ export type CsrfRejectReason =
26
+ | 'missing-origin'
27
+ | 'origin-not-allowed'
28
+ | 'missing-host'
29
+ | 'invalid-host'
30
+ | 'invalid-origin'
31
+ | 'origin-mismatch';
32
+
33
+ /**
34
+ * A failed Origin check. `origin` is the request's Origin header (null when
35
+ * absent); `expected` is the origin(s) it was compared against — the
36
+ * `allowedOrigins` list, or the one origin derived from the Host header.
37
+ * `expected` is empty when the check failed before an expected origin could
38
+ * be determined. Both are for the server log only — never the response.
39
+ */
40
+ export interface CsrfRejection {
41
+ ok: false;
42
+ status: 403;
43
+ reason: CsrfRejectReason;
44
+ origin: string | null;
45
+ expected: readonly string[];
46
+ }
47
+
48
+ export type CsrfResult = { ok: true } | CsrfRejection;
22
49
 
23
50
  // ─── Constants ────────────────────────────────────────────────────────────
24
51
 
@@ -76,19 +103,20 @@ export function validateCsrf(req: Request, config: CsrfConfig): CsrfResult {
76
103
 
77
104
  // No Origin header on a mutation → reject
78
105
  if (!origin) {
79
- return { ok: false, status: 403 };
106
+ return reject('missing-origin', null, []);
80
107
  }
81
108
 
82
109
  // If allowedOrigins is configured, use that instead of Host-based derivation
83
110
  if (config.allowedOrigins) {
84
- const allowed = config.allowedOrigins.includes(origin);
85
- return allowed ? { ok: true } : { ok: false, status: 403 };
111
+ return config.allowedOrigins.includes(origin)
112
+ ? { ok: true }
113
+ : reject('origin-not-allowed', origin, config.allowedOrigins);
86
114
  }
87
115
 
88
116
  // Auto-derive from Host header
89
117
  const host = req.headers.get('Host');
90
118
  if (!host) {
91
- return { ok: false, status: 403 };
119
+ return reject('missing-host', origin, []);
92
120
  }
93
121
 
94
122
  // Compare full origins (scheme + host + port) using URL.origin for
@@ -97,7 +125,7 @@ export function validateCsrf(req: Request, config: CsrfConfig): CsrfResult {
97
125
  try {
98
126
  originOrigin = new URL(origin).origin;
99
127
  } catch {
100
- return { ok: false, status: 403 };
128
+ return reject('invalid-origin', origin, []);
101
129
  }
102
130
 
103
131
  const scheme = deriveRequestScheme(req);
@@ -105,8 +133,112 @@ export function validateCsrf(req: Request, config: CsrfConfig): CsrfResult {
105
133
  try {
106
134
  expectedOrigin = new URL(`${scheme}://${host}`).origin;
107
135
  } catch {
108
- return { ok: false, status: 403 };
136
+ return reject('invalid-host', origin, []);
109
137
  }
110
138
 
111
- return originOrigin === expectedOrigin ? { ok: true } : { ok: false, status: 403 };
139
+ return originOrigin === expectedOrigin
140
+ ? { ok: true }
141
+ : reject('origin-mismatch', origin, [expectedOrigin]);
142
+ }
143
+
144
+ function reject(
145
+ reason: CsrfRejectReason,
146
+ origin: string | null,
147
+ expected: readonly string[]
148
+ ): CsrfRejection {
149
+ return { ok: false, status: 403, reason, origin, expected };
150
+ }
151
+
152
+ // ─── Rejection Response// ─── Rejection Response ───────────────────────────────────────────────────
153
+
154
+ /**
155
+ * Longest request-derived value echoed into the server log. Origin, Host,
156
+ * and the path are attacker-controlled; a request can carry kilobytes in
157
+ * each, and every rejection writes a log line. Real values are far shorter.
158
+ */
159
+ const MAX_LOGGED_VALUE = 200;
160
+
161
+ function clip(value: string): string {
162
+ return value.length > MAX_LOGGED_VALUE ? `${value.slice(0, MAX_LOGGED_VALUE)}…` : value;
163
+ }
164
+
165
+ /**
166
+ * Clip and quote a request-derived value for the log. JSON quoting escapes
167
+ * quotes and control characters, so a crafted header cannot close the quote
168
+ * and forge `key=value` fields or a second line.
169
+ */
170
+ function quote(value: string): string {
171
+ return JSON.stringify(clip(value));
172
+ }
173
+
174
+ const PROXY_HINT =
175
+ 'If the app runs behind a proxy that rewrites Host or terminates TLS, forward the ' +
176
+ 'original Host and X-Forwarded-Proto, or list the public origin in allowedOrigins ' +
177
+ 'in timber.config.ts.';
178
+
179
+ /**
180
+ * Browsers send `Origin: null` from opaque contexts: sandboxed iframes, a POST
181
+ * redirected across origins, file: pages. Every such context shares the one
182
+ * value — an attacker's `<iframe sandbox>` included — so the hint must never
183
+ * suggest allowlisting it.
184
+ */
185
+ const OPAQUE_ORIGIN_DETAIL =
186
+ 'origin "null" is an opaque origin (sandboxed iframe, a POST redirected across ' +
187
+ 'origins, or a file: page). Do not add "null" to allowedOrigins: every opaque ' +
188
+ "context sends it, including an attacker's sandboxed iframe.";
189
+
190
+ /** One sentence per rejection path: what was observed, and what to change. */
191
+ function describeRejection(r: CsrfRejection, host: string | null): string {
192
+ const opaque = r.origin === 'null';
193
+ const origin = quote(r.origin ?? '');
194
+ const expected = r.expected.map(quote).join(', ');
195
+ switch (r.reason) {
196
+ case 'missing-origin':
197
+ return (
198
+ 'request has no Origin header. Browsers send Origin on fetch and form POSTs; ' +
199
+ 'non-browser clients calling an unsafe method must set it.'
200
+ );
201
+ // The opaque-origin note replaces only the reasons where the origin
202
+ // itself is the fault. A null-origin request that fails for another
203
+ // reason (no Host, a bad Host) keeps that reason's diagnosis and hint.
204
+ case 'origin-not-allowed':
205
+ if (opaque) return OPAQUE_ORIGIN_DETAIL;
206
+ return (
207
+ `origin ${origin} is not in allowedOrigins [${expected}]. ` +
208
+ 'If this origin is legitimate, add it to allowedOrigins in timber.config.ts.'
209
+ );
210
+ case 'missing-host':
211
+ return `origin ${origin} could not be checked: request has no Host header. ${PROXY_HINT}`;
212
+ case 'invalid-host':
213
+ return `origin ${origin} could not be checked: Host header ${quote(host ?? '')} is not a valid host. ${PROXY_HINT}`;
214
+ case 'invalid-origin':
215
+ if (opaque) return OPAQUE_ORIGIN_DETAIL;
216
+ return `Origin header ${origin} is not a valid origin.`;
217
+ case 'origin-mismatch':
218
+ return `origin ${origin} does not match the request origin ${expected}. ${PROXY_HINT}`;
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Turn a failed check into the response the client sees, and log why.
224
+ *
225
+ * The response is a 403 marked as a CSRF rejection (header + plain-text
226
+ * body) so it cannot be mistaken for an access-control 403. It never
227
+ * carries the observed or expected origins — `allowedOrigins` is server
228
+ * configuration, and a Host-derived origin can be an internal hostname
229
+ * behind a proxy. The server log gets the full diagnosis.
230
+ */
231
+ export function csrfRejectionResponse(req: Request, rejection: CsrfRejection): Response {
232
+ logCsrfRejected(describeRejection(rejection, req.headers.get('Host')), {
233
+ method: req.method,
234
+ path: clip(new URL(req.url).pathname),
235
+ reason: rejection.reason,
236
+ });
237
+ return new Response('Forbidden: CSRF origin check failed\n', {
238
+ status: rejection.status,
239
+ headers: {
240
+ 'Content-Type': 'text/plain; charset=utf-8',
241
+ [CSRF_REJECT_HEADER]: CSRF_REJECT_VALUE,
242
+ },
243
+ });
112
244
  }
@@ -48,7 +48,6 @@
48
48
  *
49
49
  * This is the ONLY function that should gate client-visible dev behavior:
50
50
  * - Dev error pages with stack traces
51
- * - Server-Timing mode default (`'detailed'` in dev, `'total'` in prod)
52
51
  * - Error messages in action `INTERNAL_ERROR` payloads
53
52
  * - Pipeline error handler wiring (Vite overlay)
54
53
  *