@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
@@ -0,0 +1,124 @@
1
+ /**
2
+ * React.cache bridge — one `React.cache` scope per request, shared by
3
+ * `proxy.ts`, `middleware.ts`, route handlers, and the render.
4
+ *
5
+ * `React.cache(fn)` stores its memo table in whatever Map
6
+ * `ReactSharedInternals.A.getCacheForType()` returns. `A` is Flight's
7
+ * `DefaultAsyncDispatcher`, whose `getCacheForType` returns the active Flight
8
+ * request's `cache` Map, or a throwaway `new Map()` outside a render. So
9
+ * without this bridge a `React.cache` call in middleware silently never
10
+ * dedupes with the same call in `access.ts` or a layout.
11
+ *
12
+ * The bridge wraps that one method on the existing dispatcher object:
13
+ *
14
+ * - When a timber scope is active (`reactCacheScopeAls`), it returns the
15
+ * scope's Map — inside or outside a Flight render.
16
+ * - Otherwise it calls Flight's original method, so behaviour outside a
17
+ * request (build-time capture, tests, isolated renders) is unchanged.
18
+ *
19
+ * Opening, resuming, and leaving scopes lives in `react-cache-scope.ts`,
20
+ * which does not import `react` so request-context and cookie code can use it.
21
+ *
22
+ * Constraints (TIM-1529, design/spike-TIM-1529-react-cache-bridge.md):
23
+ *
24
+ * - Never reassign `ReactSharedInternals.A`. Flight's `Request` constructor
25
+ * throws "Currently React only supports one RSC renderer at a time" when
26
+ * `A` is set to anything but its own dispatcher.
27
+ * - Never shim the `react` module's `cache` export and never patch the
28
+ * vendored Flight bundle.
29
+ * - Flight installs `A` lazily, in the `Request` constructor, so it is
30
+ * `null` until the first render. `installReactCacheBridge` takes a
31
+ * `warmUp` callback that constructs one throwaway render to install it.
32
+ * - Idempotent: a program reload that re-evaluates this module but not
33
+ * Flight finds the brand on the live method and does not wrap it twice.
34
+ * A reload that re-evaluates Flight too hands back a fresh dispatcher,
35
+ * which the re-evaluated RSC entry patches again. The wrapper closes over
36
+ * nothing but the `globalThis`-anchored ALS, so an old wrapper that
37
+ * survives a reload still reads the current scope.
38
+ */
39
+
40
+ import * as React from 'react';
41
+ import { reactCacheScopeAls } from './als-registry.ts';
42
+
43
+ const INTERNALS_KEY = '__SERVER_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE';
44
+ const BRIDGED = Symbol.for('timber:react-cache-bridge');
45
+
46
+ type GetCacheForType = (resourceType: () => unknown) => unknown;
47
+
48
+ interface AsyncDispatcher {
49
+ getCacheForType: GetCacheForType;
50
+ }
51
+
52
+ interface ServerInternals {
53
+ A: unknown;
54
+ }
55
+
56
+ function isServerInternals(value: unknown): value is ServerInternals {
57
+ return typeof value === 'object' && value !== null && 'A' in value;
58
+ }
59
+
60
+ function isAsyncDispatcher(value: unknown): value is AsyncDispatcher {
61
+ return (
62
+ typeof value === 'object' &&
63
+ value !== null &&
64
+ 'getCacheForType' in value &&
65
+ typeof value.getCacheForType === 'function'
66
+ );
67
+ }
68
+
69
+ /** Result of `installReactCacheBridge`, for the boot log and the canary test. */
70
+ export type ReactCacheBridgeStatus =
71
+ | { installed: true; alreadyBridged: boolean }
72
+ | { installed: false; reason: string };
73
+
74
+ /**
75
+ * Patch Flight's dispatcher so `React.cache` resolves the active timber
76
+ * scope. Call once from the RSC entry, after the Flight server has loaded.
77
+ *
78
+ * `warmUp` must construct a Flight render (e.g. `renderToReadableStream(null)`
79
+ * and cancel it) — that is the only public way to make Flight install `A`.
80
+ *
81
+ * Never throws: if React's internals change shape the bridge is skipped,
82
+ * `React.cache` keeps its stock per-render behaviour, and the reason is
83
+ * returned. `tests/react-cache-bridge.test.ts` fails CI on that path.
84
+ */
85
+ export function installReactCacheBridge(warmUp: () => void): ReactCacheBridgeStatus {
86
+ const internals: unknown = Reflect.get(React, INTERNALS_KEY);
87
+ if (!isServerInternals(internals)) {
88
+ return {
89
+ installed: false,
90
+ reason: `react does not export ${INTERNALS_KEY}`,
91
+ };
92
+ }
93
+ if (internals.A === null || internals.A === undefined) {
94
+ try {
95
+ warmUp();
96
+ } catch (error) {
97
+ return { installed: false, reason: `warm-up render threw: ${String(error)}` };
98
+ }
99
+ }
100
+ const dispatcher = internals.A;
101
+ if (!isAsyncDispatcher(dispatcher)) {
102
+ return {
103
+ installed: false,
104
+ reason: 'ReactSharedInternals.A has no getCacheForType()',
105
+ };
106
+ }
107
+
108
+ const original = dispatcher.getCacheForType;
109
+ if (BRIDGED in original) return { installed: true, alreadyBridged: true };
110
+
111
+ const bridged: GetCacheForType = function getCacheForType(resourceType) {
112
+ const scope = reactCacheScopeAls.getStore();
113
+ if (!scope) return original.call(dispatcher, resourceType);
114
+ let entry = scope.get(resourceType);
115
+ if (entry === undefined) {
116
+ entry = resourceType();
117
+ scope.set(resourceType, entry);
118
+ }
119
+ return entry;
120
+ };
121
+ Object.defineProperty(bridged, BRIDGED, { value: true });
122
+ dispatcher.getCacheForType = bridged;
123
+ return { installed: true, alreadyBridged: false };
124
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * React.cache scopes — opening, resuming, and leaving the per-request
3
+ * `React.cache` scope that `react-cache-bridge.ts` makes Flight read.
4
+ *
5
+ * Kept apart from the bridge so request-context and cookie code can use
6
+ * it without importing `react`. See design/spike-TIM-1529-react-cache-bridge.md.
7
+ */
8
+
9
+ import { reactCacheScopeAls, type ReactCacheScope } from './als-registry.ts';
10
+ import { isDevMode } from './debug.ts';
11
+
12
+ export type { ReactCacheScope };
13
+
14
+ /** A new, empty `React.cache` scope. */
15
+ export function createReactCacheScope(): ReactCacheScope {
16
+ return new Map();
17
+ }
18
+
19
+ /**
20
+ * Run `fn` in a `React.cache` scope — a fresh one unless `scope` is given.
21
+ * Every `React.cache` call made from `fn` — synchronously, in its async
22
+ * continuations, and in any Flight render it starts — shares one memo table.
23
+ *
24
+ * Opened by `runWithRequestContext`, so each request context gets its own
25
+ * scope. Pass `scope` to resume one across two ALS runs: the post-action
26
+ * revalidation opens a fresh scope for the target route's middleware and
27
+ * renders the revalidated tree in that same scope later.
28
+ */
29
+ export function runWithReactCacheScope<T>(
30
+ fn: () => T,
31
+ scope: ReactCacheScope = createReactCacheScope()
32
+ ): T {
33
+ return reactCacheScopeAls.run(scope, fn);
34
+ }
35
+
36
+ /**
37
+ * Run `fn` with no timber scope, so `React.cache` behaves as stock React:
38
+ * no dedupe outside a render, Flight's own per-render cache inside one.
39
+ *
40
+ * Used for server action bodies — an action reads, writes cookies, and
41
+ * mutates, so memoized reads would go stale mid-action (the same choice
42
+ * Next.js makes) — and for renders whose output outlives the request
43
+ * (`cache.component` capture), which must not bake request-memoized values
44
+ * into a cross-request cache entry.
45
+ */
46
+ export function runOutsideReactCacheScope<T>(fn: () => T): T {
47
+ return reactCacheScopeAls.exit(fn);
48
+ }
49
+
50
+ // ─── Dev diagnostic: cookie written after a cached read ──────────────────
51
+ //
52
+ // A value React.cache stored was computed from the request inputs it read,
53
+ // and does not see a later write — a cached getUser() that read the session
54
+ // cookie still returns the old user after middleware deletes the cookie.
55
+ // The scope is deliberately NOT cleared on a write: that would silently
56
+ // discard every value middleware warmed (spike doc §Decisions D3). Instead,
57
+ // dev mode flags the one case that can go stale: a cookie read while the
58
+ // scope held values, then written later in the same request. Tracking is
59
+ // per scope, so it ends with the request; production does none of it.
60
+
61
+ /** Stands for "every cookie" — a getAll()/size read, or a clear() write. */
62
+ export const ANY_COOKIE = '*';
63
+
64
+ const cookieReads = new WeakMap<ReactCacheScope, Set<string>>();
65
+ const warnedScopes = new WeakSet<ReactCacheScope>();
66
+
67
+ /**
68
+ * Dev-only: record that cookie `name` (or {@link ANY_COOKIE}) was read
69
+ * while `React.cache` held values in this request — the read may have
70
+ * happened inside a cached function.
71
+ */
72
+ export function noteCookieReadForReactCache(name: string): void {
73
+ if (!isDevMode()) return;
74
+ const scope = reactCacheScopeAls.getStore();
75
+ if (!scope || scope.size === 0) return;
76
+ let reads = cookieReads.get(scope);
77
+ if (!reads) {
78
+ reads = new Set();
79
+ cookieReads.set(scope, reads);
80
+ }
81
+ reads.add(name);
82
+ }
83
+
84
+ /**
85
+ * Dev-only: warn (once per request) when a cookie recorded by
86
+ * {@link noteCookieReadForReactCache} is written. `name` is the written
87
+ * cookie, or {@link ANY_COOKIE} for `clear()`. Dev-only because reads are
88
+ * only recorded in dev.
89
+ */
90
+ export function warnIfCachedCookieIsWritten(name: string): void {
91
+ const scope = reactCacheScopeAls.getStore();
92
+ if (!scope || warnedScopes.has(scope)) return;
93
+ const reads = cookieReads.get(scope);
94
+ if (!reads) return;
95
+ const stale = name === ANY_COOKIE ? reads.size > 0 : reads.has(name) || reads.has(ANY_COOKIE);
96
+ if (!stale) return;
97
+ warnedScopes.add(scope);
98
+ const which = name === ANY_COOKIE ? 'Cookies were cleared' : `Cookie "${name}" was written`;
99
+ console.warn(
100
+ `[timber] ${which} after being read while React.cache held values for this request. ` +
101
+ `A cached function that read it keeps returning the old result — pass the cookie ` +
102
+ `value in as an argument (e.g. getUser(sessionToken)) so a change is a new cache key.`
103
+ );
104
+ }
@@ -8,6 +8,26 @@
8
8
  * Design doc: 02-rendering-pipeline.md §"Streaming Constraints"
9
9
  */
10
10
 
11
+ /** `renderTimeoutMs` when timber.config.ts leaves it unset. */
12
+ export const DEFAULT_RENDER_TIMEOUT_MS = 30_000;
13
+
14
+ /**
15
+ * What `renderTimeoutMs: 0` means: a safety ceiling, never "no timeout" —
16
+ * an unbounded render or singleflight wait can hang a connection or
17
+ * deadlock a cache key forever.
18
+ */
19
+ export const RENDER_TIMEOUT_CEILING_MS = 120_000;
20
+
21
+ /**
22
+ * The one mapping from configured `renderTimeoutMs` to the timeout every
23
+ * consumer enforces. Config enters the runtime already resolved (the
24
+ * runtime config module, static generation's options), so readers never
25
+ * see 0 or undefined.
26
+ */
27
+ export function resolveRenderTimeoutMs(configured: number | undefined): number {
28
+ return (configured ?? DEFAULT_RENDER_TIMEOUT_MS) || RENDER_TIMEOUT_CEILING_MS;
29
+ }
30
+
11
31
  /**
12
32
  * Error thrown when an SSR render or RSC stream read exceeds the
13
33
  * configured timeout. Callers can check `instanceof RenderTimeoutError`
@@ -6,7 +6,17 @@
6
6
  * ssr-render.ts, and rsc-entry/helpers.ts. See TIM-1071 item 1.
7
7
  */
8
8
 
9
- import { nonceAttr } from './csp-nonce.ts';
9
+ /**
10
+ * The ` nonce="…"` attribute fragment for a timber-generated `<script>` tag,
11
+ * or `''` when the request has no nonce. Callers interpolate it directly
12
+ * after the tag name: `` `<script${nonceAttr(nonce)}>` ``.
13
+ *
14
+ * The value comes from `generateNonce` in csp-nonce.ts and is base64, so no attribute
15
+ * escaping is required.
16
+ */
17
+ export function nonceAttr(nonce: string | undefined): string {
18
+ return nonce ? ` nonce="${nonce}"` : '';
19
+ }
10
20
 
11
21
  /**
12
22
  * Check if an error is an abort error (connection closed by client).
@@ -17,7 +17,6 @@
17
17
  import type { CoercedParams } from '../shared/param-value.ts';
18
18
  import { requestContextAls, type RequestContextStore } from './als-registry.ts';
19
19
  import { _setGetSearchParamsFn, _setGetSegmentParamsFn } from '../shared/als-slots.ts';
20
- import { consumeSeededCookies } from './cookie-context.ts';
21
20
  import { appVisibleSearch } from '../shared/rsc-cache-key.ts';
22
21
  import {
23
22
  mergeSlotParams,
@@ -25,6 +24,7 @@ import {
25
24
  type SlotParamsRecord,
26
25
  } from '../shared/slot-params.ts';
27
26
  import { isDebug } from './debug.ts';
27
+ import { runWithReactCacheScope, type ReactCacheScope } from './react-cache-scope.ts';
28
28
 
29
29
  // Re-export the ALS for framework-internal consumers that need direct access.
30
30
  export { requestContextAls };
@@ -306,26 +306,53 @@ export type ReadonlyHeaders = Pick<
306
306
 
307
307
  // ─── Framework-Internal Helpers ───────────────────────────────────────────
308
308
 
309
+ /** Options for `runWithRequestContext()`. */
310
+ export interface RequestContextOptions {
311
+ /**
312
+ * Resume this `React.cache` scope instead of opening a fresh one. Only the
313
+ * post-action revalidation passes it.
314
+ */
315
+ reactCacheScope?: ReactCacheScope;
316
+ /**
317
+ * The request's cookies, already parsed. Re-entry callers (the no-JS form
318
+ * rerender and the revalidation middleware) pass the action's
319
+ * post-mutation cookie state here instead of round-tripping it through a
320
+ * `Cookie:` header — the same parse the H-3 smuggling primitive abused
321
+ * (TIM-868).
322
+ */
323
+ cookies?: Map<string, string>;
324
+ }
325
+
309
326
  /**
310
327
  * Run a callback within a request context. Used by the pipeline to establish
311
328
  * per-request ALS scope so that `getHeaders()` and `getCookies()` work.
312
329
  *
313
- * If the request was previously registered via `seedRequestCookies`, the
314
- * resulting context's `parsedCookies` map is initialized from the seed and
315
- * the raw `cookieHeader` is left empty — `parseCookieHeader` is never called
316
- * for that request. This is the no-JS form-rerender path. See TIM-868.
330
+ * When `options.cookies` is given, the context's `parsedCookies` map is a
331
+ * copy of it and the raw `cookieHeader` is left empty, so
332
+ * `parseCookieHeader` never runs for that request. Re-entry callers pass the
333
+ * action's post-mutation cookie state this way (TIM-868).
334
+ *
335
+ * Each request context also opens its own `React.cache` scope, shared by
336
+ * everything that runs inside it — proxy.ts, middleware.ts, route handlers,
337
+ * and the render (design/02-rendering-pipeline.md §"Cache Scoping Model").
317
338
  *
318
339
  * @param req - The incoming Request object.
319
340
  * @param fn - The function to run within the request context.
320
341
  */
321
- export function runWithRequestContext<T>(req: Request, fn: () => T): T {
342
+ export function runWithRequestContext<T>(
343
+ req: Request,
344
+ fn: () => T,
345
+ { reactCacheScope, cookies }: RequestContextOptions = {}
346
+ ): T {
322
347
  const originalCopy = new Headers(req.headers);
323
348
  const appVisible = appVisibleSearch(new URL(req.url));
324
- const seed = consumeSeededCookies(req);
349
+ // A copy: the caller keeps its map, and this request's writes stay here.
350
+ const seed = cookies ? new Map(cookies) : undefined;
325
351
  const store: RequestContextStore = {
352
+ request: req,
326
353
  headers: freezeHeaders(req.headers),
327
354
  originalHeaders: originalCopy,
328
- // When seeded, leave the raw header empty — parseCookieHeader is the
355
+ // Given parsed cookies, leave the raw header empty — parseCookieHeader is the
329
356
  // exact code path the smuggling primitive abused, and lazy parsing is
330
357
  // gated on `parsedCookies` being undefined.
331
358
  cookieHeader: seed ? '' : (req.headers.get('cookie') ?? ''),
@@ -340,7 +367,7 @@ export function runWithRequestContext<T>(req: Request, fn: () => T): T {
340
367
  flushed: false,
341
368
  mutableContext: false,
342
369
  };
343
- return requestContextAls.run(store, fn);
370
+ return requestContextAls.run(store, () => runWithReactCacheScope(fn, reactCacheScope));
344
371
  }
345
372
 
346
373
  /**
@@ -20,7 +20,8 @@ import { createElement, Fragment } from 'react';
20
20
  import { withSpan } from './tracing.ts';
21
21
  import type { RouteMatch } from './pipeline.ts';
22
22
  import type { ManifestSegmentNode } from './route-matcher.ts';
23
- import { isDenySignal, DenySignal } from './primitives.ts';
23
+ import { DenySignal } from './primitives.ts';
24
+ import { isDenySignal } from './signal-identity.ts';
24
25
  import { isClientReference } from './utils/element-type.ts';
25
26
  import { loadRouteModules, type MetadataSource, type AccessFn } from './route-module-loader.ts';
26
27
  import { MetadataCollector, MetadataHead } from './metadata-collector.ts';
@@ -46,7 +47,8 @@ import type { ClientStateTree } from './state-tree-diff.ts';
46
47
  import { computeSkippableSet } from './skippable-prefix.ts';
47
48
  import { computeSegmentKeys, computeSegmentTreePaths } from '../routing/segment-keys.ts';
48
49
  import { setFirstDeniedSegmentIndex } from './deny-boundary.ts';
49
- import { loadModule } from './safe-load.ts';
50
+ import { loadModule, type ManifestLoader } from './safe-load.ts';
51
+ import { loadFallbackModule } from './pipeline-helpers.ts';
50
52
  import { replaceOutermostSegmentOutlet } from './route-element-helpers.ts';
51
53
 
52
54
  /**
@@ -205,6 +207,9 @@ export async function buildRouteElement(
205
207
  metadataRouteHashes?: Record<string, string>
206
208
  ): Promise<RouteElementResult> {
207
209
  const segments = match.segments;
210
+ // Status and error pages the boundaries need: a load failure is reported,
211
+ // and the boundary is skipped rather than failing the render.
212
+ const loadBoundaryModule = (file: ManifestLoader) => loadFallbackModule(file, req, segments);
208
213
 
209
214
  // ── Module loading ──────────────────────────────────────────────────
210
215
  // Load layout/page modules and collect metadata sources. Metadata
@@ -239,7 +244,7 @@ export async function buildRouteElement(
239
244
  // can tell a file it owns from an ancestor's. See TIM-666, TIM-1356.
240
245
  const denyPageChains = new Map<number, DenyPageEntry[]>();
241
246
  for (let i = 0; i < segments.length; i++) {
242
- const chain = await buildDenyPageChain(segments, i, segmentKeys);
247
+ const chain = await buildDenyPageChain(segments, i, segmentKeys, req);
243
248
  if (chain.length > 0) {
244
249
  denyPageChains.set(i, chain);
245
250
  }
@@ -424,7 +429,7 @@ export async function buildRouteElement(
424
429
  // rather than catching it first and rendering at the wrong depth
425
430
  // (TIM-1356).
426
431
  element = await wrapSegmentWithErrorBoundaries(segment, element, {
427
- loadModule,
432
+ loadModule: loadBoundaryModule,
428
433
  createElement: h,
429
434
  errorBoundaryComponent: TimberErrorBoundary,
430
435
  segmentKey: segmentKeys[i],
@@ -449,7 +454,7 @@ export async function buildRouteElement(
449
454
  h,
450
455
  interception,
451
456
  parentTreePath,
452
- destinationUrl,
457
+ req,
453
458
  clientStateTree: clientStateTree ?? null,
454
459
  slotSkipInfo,
455
460
  });
@@ -517,7 +522,7 @@ export async function buildRouteElement(
517
522
  // provider into the client's mounted outlet, carries it along.
518
523
  // See TIM-1450, design/04-authorization.md §"Where a Deny Page Renders".
519
524
  layoutElement = await wrapSegmentWithErrorBoundaries(segment, layoutElement, {
520
- loadModule,
525
+ loadModule: loadBoundaryModule,
521
526
  createElement: h,
522
527
  errorBoundaryComponent: TimberErrorBoundary,
523
528
  segmentKey: segmentId,
@@ -9,9 +9,10 @@
9
9
  */
10
10
 
11
11
  import type { RouteContext } from './types.ts';
12
- import { logRouteError } from './logger.ts';
13
- import { isDenySignal, isRedirectSignal } from './primitives.ts';
14
12
  import { stripHeadBody } from './head-response.ts';
13
+ import { setMutableCookieContext } from './request-context.ts';
14
+ import { getSetCookieHeaders } from './cookie-context.ts';
15
+ import { syncCookieJar } from './pipeline-helpers.ts';
15
16
 
16
17
  // ─── Types ───────────────────────────────────────────────────────────────
17
18
 
@@ -79,15 +80,16 @@ export async function handleRouteRequest(mod: RouteModule, ctx: RouteContext): P
79
80
  const allowed = resolveAllowedMethods(mod);
80
81
  const allowHeader = allowed.join(', ');
81
82
 
82
- // Auto OPTIONS — 204 with Allow header
83
+ // Auto OPTIONS — 204 with Allow header. Merged like any handler response,
84
+ // so a CORS header middleware set reaches the preflight.
83
85
  if (method === 'OPTIONS') {
84
86
  if (mod.OPTIONS) {
85
87
  return runHandler(mod.OPTIONS, ctx);
86
88
  }
87
- return new Response(null, {
88
- status: 204,
89
- headers: { Allow: allowHeader },
90
- });
89
+ return mergeResponseHeaders(
90
+ new Response(null, { status: 204, headers: { Allow: allowHeader } }),
91
+ ctx.headers
92
+ );
91
93
  }
92
94
 
93
95
  // HEAD fallback — dispatch to GET when the module exports no HEAD, so the
@@ -107,32 +109,43 @@ export async function handleRouteRequest(mod: RouteModule, ctx: RouteContext): P
107
109
  // Dispatch to the named handler
108
110
  const handler = mod[method];
109
111
  if (!handler) {
110
- return new Response(null, {
111
- status: 405,
112
- headers: { Allow: allowHeader },
113
- });
112
+ return mergeResponseHeaders(
113
+ new Response(null, { status: 405, headers: { Allow: allowHeader } }),
114
+ ctx.headers
115
+ );
114
116
  }
115
117
 
116
118
  return runHandler(handler, ctx);
117
119
  }
118
120
 
119
121
  /**
120
- * Run a handler, merge ctx.headers into the response, and catch errors.
122
+ * Run a handler with cookie writes enabled and merge ctx.headers into its
123
+ * response.
124
+ *
125
+ * Cookies (design/29-cookies.md §"Where Cookies Can Be Set"): the render
126
+ * phase applied the jar to `ctx.headers` before the handler ran, so on the
127
+ * way out only what the handler changed is synced onto that bag. It happens
128
+ * whether the handler returns or throws, so a cookie set before `redirect()`
129
+ * rides the redirect, and the pipeline's 500 for a throw carries the same
130
+ * bag.
131
+ *
132
+ * Nothing is caught. A signal goes to the pipeline, whose deny fallback
133
+ * answers a route.ts match in JSON and whose redirect outcome sends the 3xx
134
+ * (TIM-1533). Any other error goes to the pipeline, which logs it,
135
+ * reports it to `onRequestError` as phase `'route'`, and answers it in the
136
+ * same format as every other route.ts error (TIM-1537).
121
137
  */
122
138
  async function runHandler(handler: RouteHandler, ctx: RouteContext): Promise<Response> {
139
+ const applied = getSetCookieHeaders();
140
+ setMutableCookieContext(true);
141
+ let res: Response;
123
142
  try {
124
- const res = await handler(ctx);
125
- return mergeResponseHeaders(res, ctx.headers);
126
- } catch (error) {
127
- // Control-flow signals — propagate to the API route dispatcher so deny()
128
- // gets the JSON status-file chain and redirect() gets a proper 3xx with
129
- // Location. Not errors; don't log them.
130
- if (isDenySignal(error) || isRedirectSignal(error)) {
131
- throw error;
132
- }
133
- logRouteError({ method: ctx.req.method, path: new URL(ctx.req.url).pathname, error });
134
- return new Response(null, { status: 500 });
143
+ res = await handler(ctx);
144
+ } finally {
145
+ setMutableCookieContext(false);
146
+ syncCookieJar(ctx.headers, applied);
135
147
  }
148
+ return mergeResponseHeaders(res, ctx.headers);
136
149
  }
137
150
 
138
151
  /**
@@ -85,7 +85,10 @@ function matchPathname(root: ManifestSegmentNode, pathname: string): RouteMatch
85
85
 
86
86
  return {
87
87
  segments: result.chain,
88
- segmentParams: result.params,
88
+ rawSegmentParams: result.params,
89
+ // Uncoerced until the pipeline runs the codecs; a copy, so nothing that
90
+ // later replaces or edits it can reach the raw record.
91
+ segmentParams: { ...result.params },
89
92
  middlewareChain: collectMiddlewareChain(result.chain),
90
93
  };
91
94
  }
@@ -117,6 +120,17 @@ export function collectMiddlewareChain(chain: ManifestSegmentNode[]): Middleware
117
120
  return middlewareChain;
118
121
  }
119
122
 
123
+ /**
124
+ * Whether a matched chain renders as an API route: its leaf has a
125
+ * `route.ts` and no `page.tsx`. The same test `renderRoute` dispatches on,
126
+ * so every answer about a route's format — early hints, deny format, error
127
+ * format, error reporting — agrees with what actually ran.
128
+ */
129
+ export function isApiRouteChain(segments: readonly ManifestSegmentNode[]): boolean {
130
+ const leaf = segments[segments.length - 1];
131
+ return !!leaf?.route && !leaf.page;
132
+ }
133
+
120
134
  // ─── Metadata Route Matcher ─────────────────────────────────────────────
121
135
 
122
136
  /** Result of matching a metadata route. */