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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (520) hide show
  1. package/dist/_chunks/{primitives-DLAnvsrk.js → actions-BerlqoXA.js} +640 -410
  2. package/dist/_chunks/actions-BerlqoXA.js.map +1 -0
  3. package/dist/_chunks/{als-registry-C6kcfprT.js → als-registry-DaxkVjt5.js} +6 -2
  4. package/dist/_chunks/als-registry-DaxkVjt5.js.map +1 -0
  5. package/dist/_chunks/{build-manifest-DTmSGLRz.js → build-manifest-DWppEdLB.js} +2 -51
  6. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  7. package/dist/_chunks/{build-output-helper-9dqCv1pZ.js → build-output-helper-RV_BRcF1.js} +50 -53
  8. package/dist/_chunks/build-output-helper-RV_BRcF1.js.map +1 -0
  9. package/dist/_chunks/{cache-api-CUD9Ezaq.js → cache-api-CR23J_NC.js} +64 -32
  10. package/dist/_chunks/cache-api-CR23J_NC.js.map +1 -0
  11. package/dist/_chunks/{chains-B4bgOl2g.js → chains-CpFg56UB.js} +2 -2
  12. package/dist/_chunks/{chains-B4bgOl2g.js.map → chains-CpFg56UB.js.map} +1 -1
  13. package/dist/_chunks/{cli-check-G8o30ldg.js → cli-check-C6Ev6wBO.js} +11 -52
  14. package/dist/_chunks/cli-check-C6Ev6wBO.js.map +1 -0
  15. package/dist/_chunks/cli-context-By7k2xVo.js +70 -0
  16. package/dist/_chunks/cli-context-By7k2xVo.js.map +1 -0
  17. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js → cli-schema-sync-CbT2AUUI.js} +3 -3
  18. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js.map → cli-schema-sync-CbT2AUUI.js.map} +1 -1
  19. package/dist/_chunks/{cloudflare-BFb__LYG.js → cloudflare-Byxl8FWP.js} +96 -53
  20. package/dist/_chunks/{cloudflare-BFb__LYG.js.map → cloudflare-Byxl8FWP.js.map} +1 -1
  21. package/dist/_chunks/{convention-lint-5KzoMg_A.js → convention-lint-jKTwKwPe.js} +21 -6
  22. package/dist/_chunks/convention-lint-jKTwKwPe.js.map +1 -0
  23. package/dist/_chunks/{dev-server-BzBxgYAV.js → dev-server-C4WZdB7L.js} +15 -167
  24. package/dist/_chunks/dev-server-C4WZdB7L.js.map +1 -0
  25. package/dist/_chunks/{error-boundary-BrHmG-2X.js → error-boundary-tA7kVfs4.js} +84 -104
  26. package/dist/_chunks/error-boundary-tA7kVfs4.js.map +1 -0
  27. package/dist/_chunks/{fs-identity-D7vb6GdI.js → fs-identity-BRKuL215.js} +3 -4
  28. package/dist/_chunks/fs-identity-BRKuL215.js.map +1 -0
  29. package/dist/_chunks/{graph-cache-CP4GEmf9.js → graph-cache-CYiUS2aS.js} +4 -5
  30. package/dist/_chunks/graph-cache-CYiUS2aS.js.map +1 -0
  31. package/dist/_chunks/{json-lossy-check-ClNvBM_3.js → json-lossy-check-ip0Qi0MT.js} +6 -3
  32. package/dist/_chunks/json-lossy-check-ip0Qi0MT.js.map +1 -0
  33. package/dist/_chunks/{live-graph-Bm5WTvcr.js → live-graph-Dv-JJCZw.js} +3 -3
  34. package/dist/_chunks/{live-graph-Bm5WTvcr.js.map → live-graph-Dv-JJCZw.js.map} +1 -1
  35. package/dist/_chunks/{logger-k2DQ4EUf.js → logger-DiDt5ppH.js} +192 -51
  36. package/dist/_chunks/logger-DiDt5ppH.js.map +1 -0
  37. package/dist/_chunks/{navigation-root-mHSK9psY.js → navigation-root-BQfo1-kG.js} +2 -2
  38. package/dist/_chunks/{navigation-root-mHSK9psY.js.map → navigation-root-BQfo1-kG.js.map} +1 -1
  39. package/dist/_chunks/{plugin-context-8idfR3UZ.js → plugin-context-BPBPc3lL.js} +28 -4
  40. package/dist/_chunks/plugin-context-BPBPc3lL.js.map +1 -0
  41. package/dist/_chunks/{poison-scan-DG5eI2_z.js → poison-scan-CpeT6_OJ.js} +2 -2
  42. package/dist/_chunks/{poison-scan-DG5eI2_z.js.map → poison-scan-CpeT6_OJ.js.map} +1 -1
  43. package/dist/_chunks/render-timeout-DOf_BBcO.js +46 -0
  44. package/dist/_chunks/render-timeout-DOf_BBcO.js.map +1 -0
  45. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js → rsc-payload-path-dffcs4jp.js} +9 -3
  46. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js.map → rsc-payload-path-dffcs4jp.js.map} +1 -1
  47. package/dist/_chunks/{scanner-BQ5sPIJ7.js → scanner-Bw0oq1HB.js} +2 -2
  48. package/dist/_chunks/{scanner-BQ5sPIJ7.js.map → scanner-Bw0oq1HB.js.map} +1 -1
  49. package/dist/_chunks/{navigation-context-D0TU0Jog.js → segment-context-xtPUGfdq.js} +36 -34
  50. package/dist/_chunks/segment-context-xtPUGfdq.js.map +1 -0
  51. package/dist/_chunks/{singleflight-2lUWfcAk.js → singleflight-BeVMMKi0.js} +4 -3
  52. package/dist/_chunks/{singleflight-2lUWfcAk.js.map → singleflight-BeVMMKi0.js.map} +1 -1
  53. package/dist/_chunks/{sizeof-lXffQ1Vr.js → sizeof-UwzwB1uM.js} +3 -2
  54. package/dist/_chunks/sizeof-UwzwB1uM.js.map +1 -0
  55. package/dist/_chunks/ssr-data-nA3I70_n.js +49 -0
  56. package/dist/_chunks/ssr-data-nA3I70_n.js.map +1 -0
  57. package/dist/_chunks/{state-FippDgxN.js → state-BhNGPsdi.js} +6 -8
  58. package/dist/_chunks/state-BhNGPsdi.js.map +1 -0
  59. package/dist/_chunks/{status-page-marker-CNbpUOPB.js → status-page-marker-gaihi0KZ.js} +53 -20
  60. package/dist/_chunks/status-page-marker-gaihi0KZ.js.map +1 -0
  61. package/dist/_chunks/{walkers-CN2N_bA-.js → walkers-BXExhzzk.js} +2 -2
  62. package/dist/_chunks/{walkers-CN2N_bA-.js.map → walkers-BXExhzzk.js.map} +1 -1
  63. package/dist/_chunks/write-file-atomic-D1qWqHb4.js +32 -0
  64. package/dist/_chunks/write-file-atomic-D1qWqHb4.js.map +1 -0
  65. package/dist/adapters/build-output-helper.d.ts +7 -7
  66. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  67. package/dist/adapters/canonicalize-module.d.ts +8 -0
  68. package/dist/adapters/canonicalize-module.d.ts.map +1 -0
  69. package/dist/adapters/cloudflare-dev.js +1 -1
  70. package/dist/adapters/cloudflare-kv-cache.js +2 -2
  71. package/dist/adapters/cloudflare.d.ts +30 -8
  72. package/dist/adapters/cloudflare.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare.js +2 -2
  74. package/dist/adapters/compress-module.d.ts +8 -0
  75. package/dist/adapters/compress-module.d.ts.map +1 -1
  76. package/dist/adapters/fs-identity.d.ts +2 -3
  77. package/dist/adapters/fs-identity.d.ts.map +1 -1
  78. package/dist/adapters/nitro-presets.d.ts +0 -6
  79. package/dist/adapters/nitro-presets.d.ts.map +1 -1
  80. package/dist/adapters/nitro-preview.d.ts +43 -11
  81. package/dist/adapters/nitro-preview.d.ts.map +1 -1
  82. package/dist/adapters/nitro.d.ts +1 -13
  83. package/dist/adapters/nitro.d.ts.map +1 -1
  84. package/dist/adapters/nitro.js +291 -176
  85. package/dist/adapters/nitro.js.map +1 -1
  86. package/dist/adapters/shared.d.ts +7 -2
  87. package/dist/adapters/shared.d.ts.map +1 -1
  88. package/dist/adapters/types.d.ts +105 -21
  89. package/dist/adapters/types.d.ts.map +1 -1
  90. package/dist/adapters/types.js +0 -0
  91. package/dist/analyze/crawl-entry.js +3 -3
  92. package/dist/analyze/graph-cache.d.ts.map +1 -1
  93. package/dist/analyze/graph-command.js +4 -4
  94. package/dist/cache/index.js +2 -2
  95. package/dist/cache/json-lossy-check.d.ts.map +1 -1
  96. package/dist/cache/singleflight.d.ts.map +1 -1
  97. package/dist/cache/sizeof.d.ts.map +1 -1
  98. package/dist/cache/stores/memory.js +1 -1
  99. package/dist/cache/tag-aware-handler.d.ts.map +1 -1
  100. package/dist/cdn/workers-cache-purge.js +1 -1
  101. package/dist/cli-check.d.ts +7 -37
  102. package/dist/cli-check.d.ts.map +1 -1
  103. package/dist/cli-context.d.ts +54 -0
  104. package/dist/cli-context.d.ts.map +1 -0
  105. package/dist/cli.d.ts +9 -9
  106. package/dist/cli.d.ts.map +1 -1
  107. package/dist/cli.js +20 -24
  108. package/dist/cli.js.map +1 -1
  109. package/dist/client/browser-dev.d.ts +1 -1
  110. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  111. package/dist/client/browser-entry/hydrate.d.ts +19 -29
  112. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  113. package/dist/client/browser-entry/index.d.ts +7 -7
  114. package/dist/client/browser-entry/post-hydration.d.ts +6 -9
  115. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  116. package/dist/client/browser-entry/router-init.d.ts +6 -11
  117. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  118. package/dist/client/error-boundary.d.ts +4 -3
  119. package/dist/client/error-boundary.d.ts.map +1 -1
  120. package/dist/client/error-boundary.js +1 -1
  121. package/dist/client/error-reconstituter.d.ts +3 -9
  122. package/dist/client/error-reconstituter.d.ts.map +1 -1
  123. package/dist/client/history.d.ts +12 -11
  124. package/dist/client/history.d.ts.map +1 -1
  125. package/dist/client/index.d.ts +0 -1
  126. package/dist/client/index.d.ts.map +1 -1
  127. package/dist/client/index.js +5 -6
  128. package/dist/client/index.js.map +1 -1
  129. package/dist/client/internal.d.ts +3 -3
  130. package/dist/client/internal.d.ts.map +1 -1
  131. package/dist/client/internal.js +68 -104
  132. package/dist/client/internal.js.map +1 -1
  133. package/dist/client/navigation-commit.d.ts +16 -7
  134. package/dist/client/navigation-commit.d.ts.map +1 -1
  135. package/dist/client/navigation-context.d.ts +3 -5
  136. package/dist/client/navigation-context.d.ts.map +1 -1
  137. package/dist/client/react-root.d.ts +3 -2
  138. package/dist/client/react-root.d.ts.map +1 -1
  139. package/dist/client/router-pipeline.d.ts +1 -6
  140. package/dist/client/router-pipeline.d.ts.map +1 -1
  141. package/dist/client/router-types.d.ts +45 -39
  142. package/dist/client/router-types.d.ts.map +1 -1
  143. package/dist/client/router-url.d.ts +24 -0
  144. package/dist/client/router-url.d.ts.map +1 -0
  145. package/dist/client/router.d.ts.map +1 -1
  146. package/dist/client/rsc-fetch.d.ts +8 -4
  147. package/dist/client/rsc-fetch.d.ts.map +1 -1
  148. package/dist/client/ssr-data.d.ts +18 -64
  149. package/dist/client/ssr-data.d.ts.map +1 -1
  150. package/dist/client/state.d.ts +2 -5
  151. package/dist/client/state.d.ts.map +1 -1
  152. package/dist/client/use-pathname.d.ts +1 -1
  153. package/dist/config-types.d.ts +2 -1
  154. package/dist/config-types.d.ts.map +1 -1
  155. package/dist/config-validation.d.ts.map +1 -1
  156. package/dist/cookies/index.js +1 -1
  157. package/dist/dev-tools/dev-page-shell.d.ts +17 -0
  158. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
  159. package/dist/dev-tools/index.d.ts +1 -1
  160. package/dist/dev-tools/index.d.ts.map +1 -1
  161. package/dist/dev-tools/instrumentation.d.ts +17 -2
  162. package/dist/dev-tools/instrumentation.d.ts.map +1 -1
  163. package/dist/dev-tools/overlay.d.ts +6 -27
  164. package/dist/dev-tools/overlay.d.ts.map +1 -1
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +531 -373
  167. package/dist/index.js.map +1 -1
  168. package/dist/plugin-context.d.ts +26 -40
  169. package/dist/plugin-context.d.ts.map +1 -1
  170. package/dist/plugins/build-manifest.d.ts.map +1 -1
  171. package/dist/plugins/build-report.d.ts +15 -2
  172. package/dist/plugins/build-report.d.ts.map +1 -1
  173. package/dist/plugins/dev-server.d.ts.map +1 -1
  174. package/dist/plugins/entries.d.ts.map +1 -1
  175. package/dist/plugins/fonts.d.ts +19 -1
  176. package/dist/plugins/fonts.d.ts.map +1 -1
  177. package/dist/plugins/post-build.d.ts +110 -0
  178. package/dist/plugins/post-build.d.ts.map +1 -0
  179. package/dist/plugins/prebuilt-capture.d.ts +11 -4
  180. package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
  181. package/dist/plugins/prebuilt.d.ts +17 -1
  182. package/dist/plugins/prebuilt.d.ts.map +1 -1
  183. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  184. package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
  185. package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
  186. package/dist/plugins/shims.d.ts.map +1 -1
  187. package/dist/plugins/static-build.d.ts +32 -9
  188. package/dist/plugins/static-build.d.ts.map +1 -1
  189. package/dist/routing/codegen-write.d.ts +0 -9
  190. package/dist/routing/codegen-write.d.ts.map +1 -1
  191. package/dist/routing/index.js +2 -2
  192. package/dist/routing/segment-codegen.d.ts.map +1 -1
  193. package/dist/server/access-gate.d.ts.map +1 -1
  194. package/dist/server/action-handler.d.ts +5 -4
  195. package/dist/server/action-handler.d.ts.map +1 -1
  196. package/dist/server/actions.d.ts +46 -7
  197. package/dist/server/actions.d.ts.map +1 -1
  198. package/dist/server/als-registry.d.ts +58 -5
  199. package/dist/server/als-registry.d.ts.map +1 -1
  200. package/dist/server/children-interception.d.ts.map +1 -1
  201. package/dist/server/cookie-context.d.ts +2 -23
  202. package/dist/server/cookie-context.d.ts.map +1 -1
  203. package/dist/server/csp-nonce.d.ts +0 -9
  204. package/dist/server/csp-nonce.d.ts.map +1 -1
  205. package/dist/server/csrf.d.ts +27 -4
  206. package/dist/server/csrf.d.ts.map +1 -1
  207. package/dist/server/debug.d.ts +0 -1
  208. package/dist/server/debug.d.ts.map +1 -1
  209. package/dist/server/default-logger.d.ts +2 -1
  210. package/dist/server/default-logger.d.ts.map +1 -1
  211. package/dist/server/deny-boundary.d.ts +12 -6
  212. package/dist/server/deny-boundary.d.ts.map +1 -1
  213. package/dist/server/deny-renderer.d.ts +2 -2
  214. package/dist/server/deny-renderer.d.ts.map +1 -1
  215. package/dist/server/error-boundary-wrapper.d.ts +7 -3
  216. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  217. package/dist/server/fallback-error.d.ts +9 -2
  218. package/dist/server/fallback-error.d.ts.map +1 -1
  219. package/dist/server/head-response.d.ts +4 -4
  220. package/dist/server/html-injectors.d.ts.map +1 -1
  221. package/dist/server/index.d.ts +0 -1
  222. package/dist/server/index.d.ts.map +1 -1
  223. package/dist/server/index.js +3 -4
  224. package/dist/server/index.js.map +1 -1
  225. package/dist/server/instrumentation.d.ts +10 -3
  226. package/dist/server/instrumentation.d.ts.map +1 -1
  227. package/dist/server/internal.d.ts +1 -4
  228. package/dist/server/internal.d.ts.map +1 -1
  229. package/dist/server/internal.js +961 -581
  230. package/dist/server/internal.js.map +1 -1
  231. package/dist/server/json-status-response.d.ts +34 -0
  232. package/dist/server/json-status-response.d.ts.map +1 -0
  233. package/dist/server/logger.d.ts +26 -0
  234. package/dist/server/logger.d.ts.map +1 -1
  235. package/dist/server/param-coercion.d.ts +11 -6
  236. package/dist/server/param-coercion.d.ts.map +1 -1
  237. package/dist/server/pipeline-helpers.d.ts +95 -7
  238. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  239. package/dist/server/pipeline-interception.d.ts +11 -0
  240. package/dist/server/pipeline-interception.d.ts.map +1 -1
  241. package/dist/server/pipeline-outcome.d.ts +11 -1
  242. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  243. package/dist/server/pipeline-phases.d.ts +2 -2
  244. package/dist/server/pipeline-phases.d.ts.map +1 -1
  245. package/dist/server/pipeline.d.ts +23 -35
  246. package/dist/server/pipeline.d.ts.map +1 -1
  247. package/dist/server/prebuilt/capture-render.d.ts +25 -0
  248. package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
  249. package/dist/server/prebuilt/capture-routes.d.ts +37 -0
  250. package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
  251. package/dist/server/prebuilt/capture-state.d.ts +79 -35
  252. package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
  253. package/dist/server/prebuilt/lifetime.d.ts +38 -0
  254. package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
  255. package/dist/server/prebuilt/slots.d.ts +7 -0
  256. package/dist/server/prebuilt/slots.d.ts.map +1 -1
  257. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
  258. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  259. package/dist/server/prebuilt-runtime.d.ts.map +1 -1
  260. package/dist/server/primitives.d.ts +6 -81
  261. package/dist/server/primitives.d.ts.map +1 -1
  262. package/dist/server/react-cache-bridge.d.ts +59 -0
  263. package/dist/server/react-cache-bridge.d.ts.map +1 -0
  264. package/dist/server/react-cache-scope.d.ts +49 -0
  265. package/dist/server/react-cache-scope.d.ts.map +1 -0
  266. package/dist/server/render-timeout.d.ts +15 -0
  267. package/dist/server/render-timeout.d.ts.map +1 -1
  268. package/dist/server/render-utils.d.ts +9 -0
  269. package/dist/server/render-utils.d.ts.map +1 -1
  270. package/dist/server/request-context.d.ts +26 -5
  271. package/dist/server/request-context.d.ts.map +1 -1
  272. package/dist/server/route-element-builder.d.ts.map +1 -1
  273. package/dist/server/route-handler.d.ts.map +1 -1
  274. package/dist/server/route-matcher.d.ts +7 -0
  275. package/dist/server/route-matcher.d.ts.map +1 -1
  276. package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
  277. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
  278. package/dist/server/rsc-entry/api-handler.d.ts +7 -0
  279. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  280. package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
  281. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  282. package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
  283. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  284. package/dist/server/rsc-entry/helpers.d.ts +0 -1
  285. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  286. package/dist/server/rsc-entry/index.d.ts +5 -15
  287. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  288. package/dist/server/rsc-entry/render-route.d.ts +5 -6
  289. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  290. package/dist/server/rsc-entry/render-signals.d.ts +65 -0
  291. package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
  292. package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
  293. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  294. package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
  295. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  296. package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
  297. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  298. package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
  299. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  300. package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
  301. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  302. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
  303. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
  304. package/dist/server/signal-identity.d.ts +43 -0
  305. package/dist/server/signal-identity.d.ts.map +1 -0
  306. package/dist/server/slot-resolver.d.ts +4 -3
  307. package/dist/server/slot-resolver.d.ts.map +1 -1
  308. package/dist/server/slot-subtree-contain.d.ts.map +1 -1
  309. package/dist/server/ssr-bridge-types.d.ts +91 -53
  310. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  311. package/dist/server/ssr-entry.d.ts +8 -5
  312. package/dist/server/ssr-entry.d.ts.map +1 -1
  313. package/dist/server/ssr-render.d.ts +26 -40
  314. package/dist/server/ssr-render.d.ts.map +1 -1
  315. package/dist/server/ssr-wrappers.d.ts +1 -1
  316. package/dist/server/static-generator.d.ts.map +1 -1
  317. package/dist/server/stream-utils.d.ts +12 -0
  318. package/dist/server/stream-utils.d.ts.map +1 -1
  319. package/dist/server/tracing.d.ts +12 -16
  320. package/dist/server/tracing.d.ts.map +1 -1
  321. package/dist/server/types.d.ts +1 -1
  322. package/dist/server/version-skew.d.ts +3 -3
  323. package/dist/shared/csrf-reject.d.ts +16 -0
  324. package/dist/shared/csrf-reject.d.ts.map +1 -0
  325. package/dist/shared/error-digest.d.ts +28 -0
  326. package/dist/shared/error-digest.d.ts.map +1 -0
  327. package/dist/shared/payload-root.d.ts +11 -10
  328. package/dist/shared/payload-root.d.ts.map +1 -1
  329. package/dist/shared/rsc-payload-path.d.ts +6 -0
  330. package/dist/shared/rsc-payload-path.d.ts.map +1 -1
  331. package/dist/utils/write-file-atomic.d.ts +17 -0
  332. package/dist/utils/write-file-atomic.d.ts.map +1 -0
  333. package/docs/api/30-api-server.mdx +17 -14
  334. package/docs/api/32-api-cache.mdx +51 -23
  335. package/docs/api/34-api-config.mdx +34 -6
  336. package/docs/api/36-cli.mdx +11 -1
  337. package/docs/learn/03-fetching-data.mdx +17 -1
  338. package/docs/learn/04-access-control.mdx +1 -1
  339. package/docs/learn/10-caching.mdx +29 -11
  340. package/docs/learn/11-middleware.mdx +8 -2
  341. package/docs/learn/12-error-handling.mdx +6 -1
  342. package/package.json +5 -1
  343. package/src/adapters/build-output-helper.ts +55 -53
  344. package/src/adapters/canonicalize-module.ts +29 -0
  345. package/src/adapters/cloudflare.ts +105 -63
  346. package/src/adapters/compress-module.ts +16 -5
  347. package/src/adapters/fs-identity.ts +2 -3
  348. package/src/adapters/nitro-presets.ts +0 -15
  349. package/src/adapters/nitro-preview.ts +272 -136
  350. package/src/adapters/nitro.ts +119 -82
  351. package/src/adapters/shared.ts +23 -14
  352. package/src/adapters/types.ts +110 -21
  353. package/src/analyze/graph-cache.ts +3 -4
  354. package/src/cache/json-lossy-check.ts +3 -9
  355. package/src/cache/singleflight.ts +5 -2
  356. package/src/cache/sizeof.ts +3 -1
  357. package/src/cache/tag-aware-handler.ts +43 -26
  358. package/src/cli-check.ts +8 -98
  359. package/src/cli-context.ts +119 -0
  360. package/src/cli.ts +19 -28
  361. package/src/client/browser-dev.ts +1 -1
  362. package/src/client/browser-entry/action-dispatch.ts +26 -4
  363. package/src/client/browser-entry/hydrate.ts +53 -58
  364. package/src/client/browser-entry/index.ts +16 -27
  365. package/src/client/browser-entry/post-hydration.ts +6 -40
  366. package/src/client/browser-entry/router-init.ts +66 -84
  367. package/src/client/error-boundary.tsx +9 -41
  368. package/src/client/error-reconstituter.tsx +10 -5
  369. package/src/client/history.ts +18 -21
  370. package/src/client/index.ts +0 -1
  371. package/src/client/internal.ts +2 -7
  372. package/src/client/navigation-commit.ts +35 -18
  373. package/src/client/navigation-context.ts +3 -39
  374. package/src/client/react-root.ts +3 -2
  375. package/src/client/router-pipeline.ts +65 -128
  376. package/src/client/router-types.ts +46 -44
  377. package/src/client/router-url.ts +32 -0
  378. package/src/client/router.ts +43 -22
  379. package/src/client/rsc-fetch.ts +117 -155
  380. package/src/client/ssr-data.ts +19 -80
  381. package/src/client/state.ts +2 -9
  382. package/src/client/use-pathname.ts +1 -1
  383. package/src/config-types.ts +2 -1
  384. package/src/config-validation.ts +2 -1
  385. package/src/dev-tools/dev-page-shell.ts +18 -0
  386. package/src/dev-tools/index.ts +0 -2
  387. package/src/dev-tools/instrumentation.ts +50 -2
  388. package/src/dev-tools/overlay.ts +8 -238
  389. package/src/index.ts +24 -14
  390. package/src/plugin-context.ts +39 -40
  391. package/src/plugins/build-manifest.ts +4 -11
  392. package/src/plugins/build-report.ts +70 -70
  393. package/src/plugins/dev-server.ts +24 -44
  394. package/src/plugins/entries.ts +2 -1
  395. package/src/plugins/fonts.ts +35 -7
  396. package/src/plugins/post-build.ts +327 -0
  397. package/src/plugins/prebuilt-capture.ts +28 -32
  398. package/src/plugins/prebuilt.ts +54 -39
  399. package/src/plugins/prerender-sugar.ts +0 -4
  400. package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
  401. package/src/plugins/shims.ts +1 -0
  402. package/src/plugins/static-build.ts +42 -74
  403. package/src/routing/codegen-write.ts +25 -3
  404. package/src/routing/segment-codegen.ts +3 -2
  405. package/src/rsc-runtime/vendor-types.d.ts +8 -0
  406. package/src/server/access-gate.tsx +2 -1
  407. package/src/server/action-client.ts +1 -1
  408. package/src/server/action-handler.ts +253 -110
  409. package/src/server/actions.ts +73 -25
  410. package/src/server/als-registry.ts +73 -5
  411. package/src/server/chain-url-parts.ts +1 -1
  412. package/src/server/children-interception.ts +2 -1
  413. package/src/server/cookie-context.ts +18 -48
  414. package/src/server/csp-nonce.ts +0 -12
  415. package/src/server/csrf.ts +140 -8
  416. package/src/server/debug.ts +0 -1
  417. package/src/server/default-logger.ts +2 -1
  418. package/src/server/deny-boundary.ts +25 -13
  419. package/src/server/deny-renderer.ts +30 -97
  420. package/src/server/error-boundary-wrapper.ts +7 -3
  421. package/src/server/fallback-error.ts +26 -11
  422. package/src/server/flight-scripts.ts +1 -1
  423. package/src/server/head-response.ts +4 -4
  424. package/src/server/html-injector-core.ts +2 -2
  425. package/src/server/html-injectors.ts +2 -4
  426. package/src/server/index.ts +0 -4
  427. package/src/server/instrumentation.ts +10 -3
  428. package/src/server/internal.ts +1 -6
  429. package/src/server/json-status-response.ts +105 -0
  430. package/src/server/logger.ts +39 -3
  431. package/src/server/param-coercion.ts +15 -12
  432. package/src/server/pipeline-helpers.ts +257 -12
  433. package/src/server/pipeline-interception.ts +133 -0
  434. package/src/server/pipeline-outcome.ts +103 -31
  435. package/src/server/pipeline-phases.ts +127 -237
  436. package/src/server/pipeline.ts +204 -207
  437. package/src/server/prebuilt/capture-render.ts +118 -0
  438. package/src/server/prebuilt/capture-routes.ts +104 -0
  439. package/src/server/prebuilt/capture-state.ts +155 -48
  440. package/src/server/prebuilt/lifetime.ts +151 -0
  441. package/src/server/prebuilt/slots.ts +14 -2
  442. package/src/server/prebuilt/synthetic-store.ts +3 -0
  443. package/src/server/prebuilt-builder.ts +30 -320
  444. package/src/server/prebuilt-runtime.ts +125 -129
  445. package/src/server/primitives.ts +8 -168
  446. package/src/server/react-cache-bridge.ts +124 -0
  447. package/src/server/react-cache-scope.ts +104 -0
  448. package/src/server/render-timeout.ts +20 -0
  449. package/src/server/render-utils.ts +11 -1
  450. package/src/server/request-context.ts +36 -9
  451. package/src/server/route-element-builder.ts +11 -6
  452. package/src/server/route-handler.ts +36 -23
  453. package/src/server/route-matcher.ts +15 -1
  454. package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
  455. package/src/server/rsc-entry/api-handler.ts +27 -103
  456. package/src/server/rsc-entry/deny-fallback.ts +93 -26
  457. package/src/server/rsc-entry/error-renderer.ts +39 -91
  458. package/src/server/rsc-entry/helpers.ts +2 -4
  459. package/src/server/rsc-entry/index.ts +64 -58
  460. package/src/server/rsc-entry/render-route.ts +15 -80
  461. package/src/server/rsc-entry/render-signals.ts +108 -0
  462. package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
  463. package/src/server/rsc-entry/rsc-payload.ts +28 -61
  464. package/src/server/rsc-entry/rsc-stream.ts +113 -213
  465. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  466. package/src/server/rsc-entry/ssr-renderer.ts +182 -263
  467. package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
  468. package/src/server/signal-identity.ts +112 -0
  469. package/src/server/slot-resolver.ts +18 -18
  470. package/src/server/slot-subtree-contain.ts +2 -1
  471. package/src/server/ssr-bridge-types.ts +92 -56
  472. package/src/server/ssr-entry.ts +87 -111
  473. package/src/server/ssr-render.ts +55 -64
  474. package/src/server/ssr-wrappers.tsx +2 -2
  475. package/src/server/static-generator.ts +7 -42
  476. package/src/server/static-not-found.ts +3 -3
  477. package/src/server/stream-utils.ts +51 -0
  478. package/src/server/tracing.ts +58 -75
  479. package/src/server/types.ts +1 -1
  480. package/src/server/version-skew.ts +5 -5
  481. package/src/shared/csrf-reject.ts +15 -0
  482. package/src/shared/error-digest.ts +46 -0
  483. package/src/shared/payload-root.ts +11 -10
  484. package/src/shared/rsc-payload-path.ts +8 -1
  485. package/src/utils/write-file-atomic.ts +32 -0
  486. package/dist/_chunks/actions-jNrXdzgs.js +0 -346
  487. package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
  488. package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
  489. package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
  490. package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
  491. package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
  492. package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
  493. package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
  494. package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
  495. package/dist/_chunks/error-boundary-BrHmG-2X.js.map +0 -1
  496. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
  497. package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
  498. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
  499. package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
  500. package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
  501. package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
  502. package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
  503. package/dist/_chunks/segment-context-D9_89u34.js +0 -34
  504. package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
  505. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
  506. package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
  507. package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
  508. package/dist/_chunks/state-FippDgxN.js.map +0 -1
  509. package/dist/_chunks/status-page-marker-CNbpUOPB.js.map +0 -1
  510. package/dist/client/types.d.ts +0 -14
  511. package/dist/client/types.d.ts.map +0 -1
  512. package/dist/plugins/adapter-build.d.ts +0 -38
  513. package/dist/plugins/adapter-build.d.ts.map +0 -1
  514. package/dist/server/asset-headers.d.ts +0 -32
  515. package/dist/server/asset-headers.d.ts.map +0 -1
  516. package/dist/server/dev-source-map.d.ts +0 -22
  517. package/dist/server/dev-source-map.d.ts.map +0 -1
  518. package/src/client/types.ts +0 -21
  519. package/src/server/asset-headers.ts +0 -59
  520. package/src/server/dev-source-map.ts +0 -31
@@ -5,23 +5,29 @@
5
5
  // compression, graceful shutdown, static file serving, and platform quirks.
6
6
  // See design/11-platform.md and design/25-production-deployments.md.
7
7
 
8
+ import { existsSync } from 'node:fs';
8
9
  import { cp, glob, readFile, writeFile } from 'node:fs/promises';
9
- import { basename, dirname, join } from 'node:path';
10
+ import { basename, dirname, join, relative, sep } from 'node:path';
10
11
  import {
11
12
  buildStaticDirectoryOutput,
12
- findUnhashedStaticFiles,
13
13
  runSharedBuildSteps,
14
14
  writeHeadersFile,
15
15
  } from './build-output-helper.ts';
16
16
  import { generateCompressModule } from './compress-module.ts';
17
+ import { generateCanonicalizeModule } from './canonicalize-module.ts';
17
18
  import { LOCALLY_PREVIEWABLE, PRESET_CONFIGS, type NitroPreset } from './nitro-presets.ts';
18
19
  import {
19
20
  generatePreviewScript,
20
21
  generateSendResponseModule,
21
22
  spawnNitroPreview,
22
23
  } from './nitro-preview.ts';
23
- import { IMMUTABLE_CACHE } from './shared.ts';
24
- import type { TimberConfig, TimberPlatformAdapter } from './types.ts';
24
+ import { adapterBase, IMMUTABLE_CACHE } from './shared.ts';
25
+ import type {
26
+ BuildArtifacts,
27
+ PreviewTarget,
28
+ TimberConfig,
29
+ TimberPlatformAdapter,
30
+ } from './types.ts';
25
31
 
26
32
  // NitroPreset is part of the public adapter API (NitroAdapterOptions.preset),
27
33
  // so it stays importable from this module.
@@ -101,18 +107,30 @@ export function nitro(options: NitroAdapterOptions = {}): TimberPlatformAdapter
101
107
  return {
102
108
  name: `nitro-${preset}`,
103
109
 
104
- async buildOutput(config: TimberConfig, buildDir: string) {
105
- const outDir = join(buildDir, 'nitro');
110
+ async buildOutput(config: TimberConfig, artifacts: BuildArtifacts) {
111
+ const outDir = join(artifacts.outputDir, 'nitro');
106
112
 
107
113
  // ── Static mode: plain directory output ────────────────────────
108
114
  // No Nitro server — just pre-rendered HTML + client assets.
109
- if (config.output === 'static' && config.staticPagesDir) {
110
- await buildStaticDirectoryOutput(config, buildDir, outDir, 'public');
115
+ if (artifacts.output === 'static') {
116
+ await buildStaticDirectoryOutput(config, artifacts, outDir, 'public');
111
117
  const publicDir = join(outDir, 'public');
112
118
 
113
119
  // Write _headers for cache control + extensionless Content-Type.
114
120
  // Netlify supports the _headers convention just like Cloudflare.
115
- await writeHeadersFile(publicDir, config, await findUnhashedStaticFiles(publicDir));
121
+ await writeHeadersFile(publicDir, config, artifacts);
122
+
123
+ // Local preview serves the site as the build recorded it.
124
+ await writeFile(join(outDir, CANONICALIZE_MODULE), await generateCanonicalizeModule());
125
+ await writeFile(
126
+ join(outDir, PREVIEW_SCRIPT),
127
+ generatePreviewScript({
128
+ output: 'static',
129
+ immutableDirs: artifacts.immutableDirs,
130
+ base: adapterBase(config),
131
+ contentTypes: artifacts.contentTypes,
132
+ })
133
+ );
116
134
 
117
135
  // Platform-specific files for static deploy targets.
118
136
  const target = options.staticTarget ?? 'generic';
@@ -143,7 +161,7 @@ export function nitro(options: NitroAdapterOptions = {}): TimberPlatformAdapter
143
161
  // write _headers, write manifest-init).
144
162
  await runSharedBuildSteps({
145
163
  config,
146
- buildDir,
164
+ artifacts,
147
165
  outDir,
148
166
  publicDirName: 'public',
149
167
  });
@@ -156,76 +174,116 @@ export function nitro(options: NitroAdapterOptions = {}): TimberPlatformAdapter
156
174
  // Web→Node response bridge with backpressure. See TIM-1154.
157
175
  await writeFile(join(outDir, '_send-response.mjs'), generateSendResponseModule());
158
176
 
177
+ // Standalone preview server for presets with a local runtime. It loads
178
+ // the build's own RSC bundle — not the copy under nitro/rsc/ — because
179
+ // the handler reads prebuilt payloads from ../prebuilt beside its
180
+ // bundle, and the build's prebuilt/ is cleaned every build while
181
+ // nitro/prebuilt/ is not: a build that captured nothing would otherwise
182
+ // preview an earlier build's payloads.
183
+ if (LOCALLY_PREVIEWABLE.has(preset)) {
184
+ await writeFile(join(outDir, CANONICALIZE_MODULE), await generateCanonicalizeModule());
185
+ await writeFile(
186
+ join(outDir, PREVIEW_SCRIPT),
187
+ generatePreviewScript({
188
+ output: 'server',
189
+ runtimeName: PRESET_CONFIGS[preset].runtimeName,
190
+ rscEntry: importSpecifier(outDir, join(artifacts.rsc.path, 'index.js')),
191
+ hasManifestInit: !!artifacts.manifestInit,
192
+ immutableDirs: artifacts.immutableDirs,
193
+ base: adapterBase(config),
194
+ })
195
+ );
196
+ }
197
+
159
198
  // Prepend the manifest assignment directly into the RSC entry so
160
199
  // globalThis.__TIMBER_BUILD_MANIFEST__ is set before any module reads it.
161
200
  // This must be top-level code, not an import, because rollup tree-shakes
162
201
  // side-effect-only globalThis assignments from imported modules.
163
- if (config.manifestInit) {
202
+ if (artifacts.manifestInit) {
164
203
  const rscEntry = join(outDir, 'rsc', 'index.js');
165
204
  const rscContent = await readFile(rscEntry, 'utf-8');
166
- await writeFile(rscEntry, `${config.manifestInit}\n${rscContent}`);
205
+ await writeFile(rscEntry, `${artifacts.manifestInit}\n${rscContent}`);
167
206
  }
168
207
 
169
208
  // Generate the Nitro entry point (imports from ./rsc/ within nitro dir)
170
- const entry = generateNitroEntry(buildDir, outDir, preset, compress);
209
+ const entry = generateNitroEntry(preset, compress);
171
210
  await writeFile(join(outDir, 'entry.ts'), entry);
172
211
 
173
212
  // Run the Nitro build to produce a production-ready server bundle.
174
213
  // The output goes to dist/nitro/.output/server/index.mjs (for node-server preset).
175
214
  // Config is passed programmatically — no nitro.config.ts file needed.
176
- const { serverDir } = await runNitroBuild(outDir, preset, options.nitroConfig);
177
-
178
- // Copy prebuilt flight payloads from the canonical build source
179
- // (buildDir/prebuilt, cleaned by the prebuilt plugin each build) into
180
- // the Nitro output. The RSC entry resolves `../prebuilt/` relative to
181
- // its bundled chunk (<serverDir>/_chunks/), so prebuilt/ must live at
215
+ const { serverDir } = await runNitroBuild(
216
+ outDir,
217
+ preset,
218
+ artifacts.immutableDirs,
219
+ options.nitroConfig
220
+ );
221
+
222
+ // Copy prebuilt flight payloads into the Nitro output. The RSC entry
223
+ // resolves `../prebuilt/` relative to its bundled chunk
224
+ // (<serverDir>/_chunks/), so prebuilt/ must live at
182
225
  // <serverDir>/prebuilt/. serverDir is the resolved path from Nitro
183
226
  // (honors user overrides via nitroConfig.output.serverDir).
184
- const prebuiltSrc = join(buildDir, 'prebuilt');
185
- await cp(prebuiltSrc, join(serverDir, 'prebuilt'), {
186
- recursive: true,
187
- }).catch((e: NodeJS.ErrnoException) => {
188
- if (e.code !== 'ENOENT') throw e;
189
- });
190
-
191
- // Vercel with functionRules clones __server.func to per-route .func
192
- // directories during the Nitro build. Copy prebuilt into those clones
193
- // so requests routed to them also resolve ../prebuilt correctly.
194
- if (preset === 'vercel' || preset === 'vercel-edge') {
195
- const functionsDir = dirname(serverDir);
196
- const baseFuncName = basename(serverDir);
197
- await copyPrebuiltToVercelFuncClones(functionsDir, prebuiltSrc, baseFuncName);
227
+ if (artifacts.prebuilt) {
228
+ const prebuiltSrc = artifacts.prebuilt.path;
229
+ await cp(prebuiltSrc, join(serverDir, 'prebuilt'), { recursive: true });
230
+
231
+ // Vercel with functionRules clones __server.func to per-route .func
232
+ // directories during the Nitro build. Copy prebuilt into those clones
233
+ // so requests routed to them also resolve ../prebuilt correctly.
234
+ if (preset === 'vercel' || preset === 'vercel-edge') {
235
+ const functionsDir = dirname(serverDir);
236
+ const baseFuncName = basename(serverDir);
237
+ await copyPrebuiltToVercelFuncClones(functionsDir, prebuiltSrc, baseFuncName);
238
+ }
198
239
  }
199
240
  },
200
241
 
201
- // Only presets that produce a locally-runnable server get preview().
202
- // Serverless presets (vercel, netlify, aws-lambda, etc.) have no
203
- // local runtime — Vite's built-in preview is the fallback.
204
- preview: LOCALLY_PREVIEWABLE.has(preset)
205
- ? async (_config: TimberConfig, buildDir: string) => {
206
- // Generate a standalone preview server that uses Node's built-in
207
- // HTTP server. The Nitro entry.ts can't be run directly because
208
- // it imports h3 (a Nitro dependency not available at runtime).
209
- const previewScript = generatePreviewScript(buildDir, preset);
210
- const scriptPath = join(buildDir, 'nitro', '_preview-server.mjs');
211
- await writeFile(scriptPath, previewScript);
212
-
213
- const command = preset === 'bun' ? 'bun' : 'node';
214
- await spawnNitroPreview(command, [scriptPath], join(buildDir, 'nitro'));
215
- }
216
- : undefined,
242
+ // buildOutput wrote the preview server for this build: a static file
243
+ // server for a static build, and for a server build on a preset with a
244
+ // local runtime (node-server, bun), one that routes to the RSC handler.
245
+ // Serverless presets (vercel, netlify, aws-lambda, etc.) have no local
246
+ // runtime, so a server build on one has nothing to preview.
247
+ async preview(_config: TimberConfig, { output, outputDir }: PreviewTarget) {
248
+ if (output === 'server' && !LOCALLY_PREVIEWABLE.has(preset)) {
249
+ throw new Error(
250
+ `[timber] The nitro '${preset}' preset has no local runtime, so \`timber preview\` ` +
251
+ `cannot run its server build. Preview with a node-server build, or with the ` +
252
+ `platform's own tooling.`
253
+ );
254
+ }
255
+ const nitroDir = join(outputDir, 'nitro');
256
+ const script = join(nitroDir, PREVIEW_SCRIPT);
257
+ if (!existsSync(script)) {
258
+ throw new Error(
259
+ `[timber] No preview server at ${script}. Run \`timber build\` before \`timber preview\`.`
260
+ );
261
+ }
262
+ // Only a bun server build needs Bun. The static file server uses Node
263
+ // built-ins, so it runs on the Node already running timber, as does a
264
+ // node-server build — no PATH lookup for either.
265
+ const command = output === 'server' && preset === 'bun' ? 'bun' : process.execPath;
266
+ await spawnNitroPreview(command, [script], nitroDir);
267
+ },
217
268
  };
218
269
  }
219
270
 
271
+ /** The preview server buildOutput writes into the Nitro output directory. */
272
+ const PREVIEW_SCRIPT = '_preview-server.mjs';
273
+
274
+ /** The request-path canonicalizer the preview server imports beside it. */
275
+ const CANONICALIZE_MODULE = '_canonicalize.mjs';
276
+
277
+ /** A relative ESM import specifier for `file`, as imported from a module in `fromDir`. */
278
+ function importSpecifier(fromDir: string, file: string): string {
279
+ const path = relative(fromDir, file).split(sep).join('/');
280
+ return path.startsWith('../') ? path : './' + path;
281
+ }
282
+
220
283
  // ─── Entry Generation ────────────────────────────────────────────────────────
221
284
 
222
285
  /** @internal Exported for testing. */
223
- export function generateNitroEntry(
224
- buildDir: string,
225
- outDir: string,
226
- preset: NitroPreset,
227
- compress = true
228
- ): string {
286
+ export function generateNitroEntry(preset: NitroPreset, compress = true): string {
229
287
  // The RSC entry is the main request handler — it exports the fetch handler as default.
230
288
  // rsc/ is copied into the nitro dir so the import is local.
231
289
  // The manifest init is prepended to rsc/index.js before the nitro build,
@@ -408,6 +466,7 @@ interface NitroBuildResult {
408
466
  async function runNitroBuild(
409
467
  nitroDir: string,
410
468
  preset: NitroPreset,
469
+ immutableDirs: readonly string[],
411
470
  userConfig?: Record<string, unknown>
412
471
  ): Promise<NitroBuildResult> {
413
472
  const presetConfig = PRESET_CONFIGS[preset];
@@ -426,10 +485,10 @@ async function runNitroBuild(
426
485
  // Using `entry` directly would bypass the Nitro server runtime.
427
486
  renderer: { handler: join(nitroDir, 'entry.ts') },
428
487
  output: { dir: join(nitroDir, presetConfig.outputDir) },
429
- routeRules: {
430
- '/assets/**': { headers: { 'Cache-Control': IMMUTABLE_CACHE } },
431
- '/_timber/fonts/**': { headers: { 'Cache-Control': IMMUTABLE_CACHE } },
432
- },
488
+ // One rule per content-hashed directory the build recorded.
489
+ routeRules: Object.fromEntries(
490
+ immutableDirs.map((dir) => [`/${dir}/**`, { headers: { 'Cache-Control': IMMUTABLE_CACHE } }])
491
+ ),
433
492
  // Don't bundle the timber RSC/SSR build output — it has its own
434
493
  // internal file references that nitro's bundler can't follow.
435
494
  // Mark them as external so rollup leaves the imports as-is.
@@ -471,22 +530,6 @@ async function runNitroBuild(
471
530
  }
472
531
  // ─── Helpers ─────────────────────────────────────────────────────────────────
473
532
 
474
- /**
475
- * Resolve the destination path for prebuilt flight payloads in the Nitro
476
- * output directory. The RSC entry resolves `../prebuilt/` relative to its
477
- * bundled chunk location (`<serverBundleDir>/_chunks/`), so prebuilt/ must
478
- * live at `<serverBundleDir>/prebuilt/`.
479
- *
480
- * The serverBundleDir varies by preset — Nitro's Vercel preset uses
481
- * `functions/__server.func` while most others use `server`.
482
- *
483
- * @internal Exported for testing.
484
- */
485
- export function resolvePrebuiltOutputPath(outDir: string, preset: NitroPreset): string {
486
- const presetConfig = PRESET_CONFIGS[preset];
487
- return join(outDir, presetConfig.outputDir, presetConfig.serverBundleDir, 'prebuilt');
488
- }
489
-
490
533
  /**
491
534
  * Copy prebuilt payloads into cloned Vercel function directories.
492
535
  *
@@ -513,12 +556,6 @@ export async function copyPrebuiltToVercelFuncClones(
513
556
  return;
514
557
  }
515
558
  await Promise.all(
516
- funcDirs.map((dir) =>
517
- cp(prebuiltSrc, join(dir, 'prebuilt'), { recursive: true }).catch(
518
- (e: NodeJS.ErrnoException) => {
519
- if (e.code !== 'ENOENT') throw e;
520
- }
521
- )
522
- )
559
+ funcDirs.map((dir) => cp(prebuiltSrc, join(dir, 'prebuilt'), { recursive: true }))
523
560
  );
524
561
  }
@@ -19,7 +19,7 @@ import { withBasePath } from '../shared/base-path.ts';
19
19
  * by callers that predate it (a hand-written adapter, a test harness). Falling
20
20
  * back to `'/'` reproduces the pre-TIM-1274 output exactly, which is correct
21
21
  * for the only deployments those callers can have: a build under a non-root
22
- * base always goes through `plugins/adapter-build.ts`, which populates it.
22
+ * base always goes through `plugins/post-build.ts`, which populates it.
23
23
  *
24
24
  * Typed structurally rather than as `TimberConfig` so this module keeps no
25
25
  * import of `./types.js` at runtime.
@@ -43,7 +43,9 @@ export const STATIC_CACHE = 'public, max-age=3600, must-revalidate';
43
43
  * Static Assets, Cloudflare Pages, and Netlify. It maps URL patterns to
44
44
  * HTTP response headers.
45
45
  *
46
- * Only hashed (immutable) asset paths are listed here by default. When
46
+ * The build's content-hashed directories (`immutableDirs`, recorded on
47
+ * `BuildArtifacts` by the phases that hashed them) get one wildcard rule
48
+ * each. When
47
49
  * `unhashedPaths` is provided, per-file rules are appended for unhashed
48
50
  * static assets (favicon.ico, robots.txt, etc.) so they get Cache-Control
49
51
  * on platforms like Cloudflare Workers Static Assets where the server
@@ -62,13 +64,13 @@ export const STATIC_CACHE = 'public, max-age=3600, must-revalidate';
62
64
  * Cloudflare Workers Static Assets without one.
63
65
  *
64
66
  * The prefix is applied at exactly one point, `rulePath()`, which every rule
65
- * in this function goes through. Prefixing the three wildcards and
67
+ * in this function goes through. Prefixing the wildcards and
66
68
  * hand-checking that the per-file rules agree is how the next rule gets
67
69
  * missed.
68
70
  */
69
- // Cloudflare Workers Static Assets caps _headers at 100 rules.
70
- // Reserve 3 for the wildcard hashed-asset rules (/assets/*, /_timber/fonts/*, /_rsc/*).
71
- const MAX_PER_FILE_RULES = 97;
71
+ // Cloudflare Workers Static Assets caps _headers at 100 rules. The wildcard
72
+ // rules for the immutable directories come out of the same budget.
73
+ const MAX_RULES = 100;
72
74
 
73
75
  export interface HeadersFileOptions {
74
76
  /**
@@ -79,6 +81,11 @@ export interface HeadersFileOptions {
79
81
  * root-relative rules that match nothing, which is the bug this closes.
80
82
  */
81
83
  base: string;
84
+ /**
85
+ * Content-hashed directories, from `BuildArtifacts.immutableDirs`. Each
86
+ * gets an immutable `Cache-Control` wildcard rule.
87
+ */
88
+ immutableDirs: readonly string[];
82
89
  /** Unhashed static files (route-space paths) needing per-file cache rules. */
83
90
  unhashedPaths?: string[];
84
91
  /** Route-space path → Content-Type, for extensionless API route outputs. */
@@ -154,6 +161,7 @@ function patternsOverlap(a: string, b: string): boolean {
154
161
 
155
162
  export function generateHeadersFile({
156
163
  base,
164
+ immutableDirs,
157
165
  unhashedPaths,
158
166
  contentTypes,
159
167
  userRules,
@@ -208,24 +216,25 @@ export function generateHeadersFile({
208
216
  let content = `# Auto-generated by @timber-js/app — static asset cache headers.
209
217
  # See design/25-production-deployments.md §"CDN / Edge Cache"
210
218
  `;
211
- for (const path of ['/assets/*', '/_timber/fonts/*', '/_rsc/*']) {
212
- content += emit(rulePath(path), 'Cache-Control', IMMUTABLE_CACHE);
219
+ for (const dir of immutableDirs) {
220
+ content += emit(rulePath(`/${dir}/*`), 'Cache-Control', IMMUTABLE_CACHE);
213
221
  }
222
+ const maxPerFileRules = MAX_RULES - immutableDirs.length;
214
223
 
215
224
  // Content-Type rules are higher priority than cache headers for
216
225
  // extensionless files — without them the file is unreadable.
217
226
  const allCtEntries = contentTypes
218
227
  ? Object.entries(contentTypes).sort(([a], [b]) => a.localeCompare(b))
219
228
  : [];
220
- const ctEntries = allCtEntries.slice(0, MAX_PER_FILE_RULES);
221
- if (allCtEntries.length > MAX_PER_FILE_RULES) {
229
+ const ctEntries = allCtEntries.slice(0, maxPerFileRules);
230
+ if (allCtEntries.length > maxPerFileRules) {
222
231
  console.warn(
223
232
  `[timber] _headers: ${allCtEntries.length} content-type rules exceed ` +
224
- `Cloudflare's 100-rule limit. Only the first ${MAX_PER_FILE_RULES} ` +
233
+ `Cloudflare's 100-rule limit. Only the first ${maxPerFileRules} ` +
225
234
  `extensionless API routes will get Content-Type headers.`
226
235
  );
227
236
  }
228
- const remainingBudget = MAX_PER_FILE_RULES - ctEntries.length;
237
+ const remainingBudget = maxPerFileRules - ctEntries.length;
229
238
 
230
239
  if (unhashedPaths && unhashedPaths.length > 0) {
231
240
  const capped = unhashedPaths.slice(0, Math.max(0, remainingBudget));
@@ -260,10 +269,10 @@ export function generateHeadersFile({
260
269
  content += `\n# User-authored rules from public/_headers\n\n${userRules.trim()}\n`;
261
270
 
262
271
  const total = countHeaderRules(content);
263
- if (total > MAX_PER_FILE_RULES + 3) {
272
+ if (total > MAX_RULES) {
264
273
  console.warn(
265
274
  `[timber] _headers: ${total} rules after merging public/_headers, over ` +
266
- `Cloudflare's ${MAX_PER_FILE_RULES + 3}-rule limit. Rules past the ` +
275
+ `Cloudflare's ${MAX_RULES}-rule limit. Rules past the ` +
267
276
  `limit are dropped by the platform — remove some, or move static ` +
268
277
  `assets under a directory the wildcard rules already cover.`
269
278
  );
@@ -7,6 +7,12 @@
7
7
  /**
8
8
  * Configuration passed to adapter lifecycle methods.
9
9
  * A subset of the resolved timber.config.ts relevant to adapters.
10
+ *
11
+ * Configuration only: nothing here is produced by a build phase. What the
12
+ * build produced — directories, the manifest initialization module, the
13
+ * static site — arrives separately as {@link BuildArtifacts}, and the output
14
+ * mode is the discriminant of that union rather than a field here, so an
15
+ * adapter cannot be handed a static mode with no static site (TIM-1524).
10
16
  */
11
17
  export interface TimberConfig {
12
18
  /** Absolute path to the project root (Vite root). */
@@ -19,40 +25,120 @@ export interface TimberConfig {
19
25
  * host matches against the *request* path, so those rules live in deployed-
20
26
  * URL space rather than route space and need this prefix (TIM-1274).
21
27
  *
22
- * Populated by `plugins/adapter-build.ts` from `ctx.base`, the single copy
28
+ * Populated by `plugins/post-build.ts` from `ctx.base`, the single copy
23
29
  * lifted in TIM-1261. Adapters must not re-derive it from `config.base`.
24
30
  */
25
31
  base?: string;
26
- output: 'server' | 'static';
27
32
  clientJavascriptDisabled?: boolean;
33
+ }
34
+
35
+ /** A directory a build phase wrote. */
36
+ export interface DirectoryArtifact {
37
+ /** Absolute path. Adapters never join it against `outputDir` or `root`. */
38
+ readonly path: string;
39
+ }
40
+
41
+ interface BuildArtifactsBase {
28
42
  /**
29
- * JS module source that sets globalThis.__TIMBER_BUILD_MANIFEST__.
30
- * Written by adapters as _timber-manifest-init.js, imported before the RSC handler.
31
- * Undefined when no build manifest was produced (e.g., dev mode or no client assets).
43
+ * The build output directory (`.timber/dist` by default) — where adapters
44
+ * write their own platform directory (`cloudflare/`, `nitro/`). Not the
45
+ * project root; that is `TimberConfig.root`.
32
46
  */
33
- manifestInit?: string;
47
+ readonly outputDir: string;
34
48
  /**
35
- * Absolute path to the directory containing pre-rendered static HTML,
36
- * RSC flight files, and API route outputs. Present only when
37
- * output: 'static' and the static generation pass completed.
38
- * Layout: path/index.html, _rsc/path/index.rsc, api-route-path
49
+ * The browser bundle: client JS, CSS, fonts, and everything Vite copied
50
+ * out of `public/`. Always produced — with client JavaScript disabled it
51
+ * still carries the stylesheets and `public/`; adapters drop the `.js`.
39
52
  */
40
- staticPagesDir?: string;
53
+ readonly client: DirectoryArtifact;
41
54
  /**
42
- * Content-Type mappings for extensionless API route outputs.
43
- * Map from URL path (e.g. "/api/data") to Content-Type value.
44
- * Written during static generation, consumed by adapters when
45
- * writing _headers. See TIM-1241.
55
+ * Directories of the served tree whose every file name carries a content
56
+ * hash — `'assets'`, `'_timber/fonts'`, and in a static build whose RSC
57
+ * payloads were hashed, `'_rsc'`. Relative to the site root, `/`-separated,
58
+ * no leading or trailing slash, and in route space: an adapter writing
59
+ * platform rules adds the deployment `base` itself.
60
+ *
61
+ * Each entry is recorded by the phase that hashed the files — the client
62
+ * environment from its `build.assetsDir`, the font plugin when it emitted a
63
+ * binary, static generation when it hashed payloads — so adapters mark
64
+ * these immutable without knowing which plugin names or hashes what.
46
65
  */
47
- staticContentTypes?: Record<string, string>;
66
+ readonly immutableDirs: readonly string[];
67
+ }
68
+
69
+ /** Build products of an `output: 'server'` build. */
70
+ export interface ServerBuildArtifacts extends BuildArtifactsBase {
71
+ readonly output: 'server';
72
+ /** The RSC server bundle. Its `index.js` is the request handler. */
73
+ readonly rsc: DirectoryArtifact;
74
+ /**
75
+ * The SSR bundle. The RSC bundle imports it by a path the RSC plugin
76
+ * computed between the two build directories — siblings named `rsc/` and
77
+ * `ssr/` — so adapters deploy them as siblings under those names.
78
+ */
79
+ readonly ssr: DirectoryArtifact;
80
+ /**
81
+ * `cache.component` flight payloads captured at build time (design/44).
82
+ * Present only when the capture pass wrote at least one payload.
83
+ */
84
+ readonly prebuilt?: DirectoryArtifact;
85
+ /**
86
+ * Generated JS module source that sets `globalThis.__TIMBER_BUILD_MANIFEST__`.
87
+ * Must evaluate before the RSC handler; adapters
88
+ * write it as `_timber-manifest-init.js` or prepend it to the entry.
89
+ * Absent when no build manifest was produced.
90
+ */
91
+ readonly manifestInit?: string;
92
+ }
93
+
94
+ /** Build products of an `output: 'static'` build. */
95
+ export interface StaticBuildArtifacts extends BuildArtifactsBase {
96
+ readonly output: 'static';
97
+ /**
98
+ * The pre-rendered site: `path/index.html`, RSC payloads under `_rsc/`
99
+ * (content-hashed unless client JavaScript is disabled), API route
100
+ * outputs, `404.html`, and a generated `_redirects` when any redirect was
101
+ * captured.
102
+ */
103
+ readonly pages: DirectoryArtifact;
104
+ /**
105
+ * Content-Type for each extensionless API route output, keyed by URL path
106
+ * (e.g. `/api/data` → `application/json`). Adapters write these as
107
+ * `_headers` rules; a static host cannot infer them from a file name.
108
+ * See TIM-1241.
109
+ */
110
+ readonly contentTypes: Readonly<Record<string, string>>;
111
+ }
112
+
113
+ /**
114
+ * Everything a `timber build` produced, as the adapter consumes it.
115
+ *
116
+ * Each field is recorded by the phase that wrote it. The two optional fields
117
+ * are the two products a build can legitimately lack — `prebuilt` (nothing
118
+ * captured) and `manifestInit` (no build manifest) — and adapters branch on
119
+ * their presence (`if (artifacts.prebuilt)`) rather than probing the
120
+ * filesystem.
121
+ */
122
+ export type BuildArtifacts = ServerBuildArtifacts | StaticBuildArtifacts;
123
+
124
+ /**
125
+ * What `timber preview` asks an adapter to serve. Preview runs in a later
126
+ * process with no build in memory, so it gets the output directory and the
127
+ * configured mode rather than {@link BuildArtifacts}; the mode is what tells
128
+ * an adapter whether a server entry exists to run at all.
129
+ */
130
+ export interface PreviewTarget {
131
+ readonly output: 'server' | 'static';
132
+ /** The build output directory `buildOutput` wrote its platform directory into. */
133
+ readonly outputDir: string;
48
134
  }
49
135
 
50
136
  /**
51
137
  * The formal adapter interface. An adapter transforms the build output
52
138
  * into a deployable artifact for a specific platform.
53
139
  *
54
- * Adapters are small: they receive the build output directory and
55
- * transform or copy it into whatever shape the platform expects.
140
+ * Adapters are small: they receive a description of what the build
141
+ * produced and transform or copy it into whatever shape the platform expects.
56
142
  */
57
143
  export interface TimberPlatformAdapter {
58
144
  /** Unique adapter name (e.g. 'cloudflare', 'node', 'bun'). */
@@ -62,13 +148,16 @@ export interface TimberPlatformAdapter {
62
148
  * Transform the build output for the target platform.
63
149
  * Called at the end of `timber build`.
64
150
  */
65
- buildOutput(config: TimberConfig, buildDir: string): Promise<void>;
151
+ buildOutput(config: TimberConfig, artifacts: BuildArtifacts): Promise<void>;
66
152
 
67
153
  /**
68
154
  * Start a local preview server for the built output.
69
- * Falls back to the built-in Node.js preview server if not provided.
155
+ * Falls back to Vite's preview server if not provided.
156
+ *
157
+ * Runs in a later process than the build (`timber preview`); see
158
+ * {@link PreviewTarget}.
70
159
  */
71
- preview?(config: TimberConfig, buildDir: string): Promise<void>;
160
+ preview?(config: TimberConfig, target: PreviewTarget): Promise<void>;
72
161
 
73
162
  /**
74
163
  * Send 103 Early Hints to the client before the final response.
@@ -22,10 +22,11 @@
22
22
 
23
23
  import { createHash } from 'node:crypto';
24
24
  import { createRequire } from 'node:module';
25
- import { mkdir, readFile, rename, stat, writeFile } from 'node:fs/promises';
25
+ import { mkdir, readFile, stat } from 'node:fs/promises';
26
26
  import { dirname, isAbsolute, join } from 'node:path';
27
27
  import { buildSourceExtensions, scanProjectSourceFiles } from './scan.ts';
28
28
  import type { CrawlReport } from './crawl.ts';
29
+ import { writeFileAtomic } from '../utils/write-file-atomic.ts';
29
30
 
30
31
  /**
31
32
  * JSON contract version (design/47 §9) — one constant for every
@@ -326,7 +327,5 @@ export async function readGraphCache(root: string): Promise<GraphCacheFile | nul
326
327
  export async function writeGraphCache(root: string, cache: GraphCacheFile): Promise<void> {
327
328
  const target = join(root, CACHE_RELATIVE_PATH);
328
329
  await mkdir(dirname(target), { recursive: true });
329
- const temp = `${target}.${process.pid}.tmp`;
330
- await writeFile(temp, JSON.stringify(cache));
331
- await rename(temp, target);
330
+ await writeFileAtomic(target, JSON.stringify(cache));
332
331
  }
@@ -1,3 +1,5 @@
1
+ import { logLossyCacheValue } from '../server/logger.ts';
2
+
1
3
  const LOSSY_TYPES = ['Date', 'Map', 'Set', 'BigInt'] as const;
2
4
 
3
5
  let hasWarned = false;
@@ -17,15 +19,7 @@ export function warnLossyJsonValue(value: unknown, cacheKey: string): void {
17
19
  if (lossy.size === 0) return;
18
20
 
19
21
  hasWarned = true;
20
- const types = [...lossy].join(', ');
21
- console.warn(
22
- `[timber] cache value for key "${cacheKey}" contains ${types} — ` +
23
- 'these types lose fidelity through JSON serialization in Redis/KV cache handlers. ' +
24
- 'Date becomes an ISO string, Map/Set become {}, BigInt throws. ' +
25
- 'The MemoryCacheHandler preserves them. Consider transforming values ' +
26
- 'to JSON-safe types before caching, or use MemoryCacheHandler for ' +
27
- 'values that require type preservation.'
28
- );
22
+ logLossyCacheValue({ cacheKey, types: [...lossy].join(', ') });
29
23
  }
30
24
 
31
25
  function findLossyTypes(value: unknown, seen: Set<unknown>, depth: number): Set<string> {
@@ -52,8 +52,11 @@ export function createSingleflight(opts?: SingleflightOptions): Singleflight {
52
52
  // side effects (e.g. cache writes). See TIM-1092.
53
53
  promise = new Promise<T>((resolve, reject) => {
54
54
  const timer = setTimeout(() => {
55
- ac.abort();
56
- reject(new SingleflightTimeoutError(key, timeoutMs));
55
+ // The timeout error is also the signal's reason, so the body
56
+ // can tell why it was aborted (runBackgroundFlight reports it).
57
+ const timeout = new SingleflightTimeoutError(key, timeoutMs);
58
+ ac.abort(timeout);
59
+ reject(timeout);
57
60
  }, timeoutMs);
58
61
  try {
59
62
  fn(ac.signal).then(
@@ -13,6 +13,8 @@
13
13
  * to cache and undercount than to reject the entry.
14
14
  */
15
15
 
16
+ import { swallow } from '../server/logger.ts';
17
+
16
18
  /**
17
19
  * Estimate the byte size of a value.
18
20
  *
@@ -27,7 +29,7 @@ export function estimateByteSize(value: unknown): number {
27
29
  return json.length * 2;
28
30
  } catch (e) {
29
31
  // Circular reference or non-serializable value
30
- console.debug('[timber] sizeof estimation failed:', e instanceof Error ? e.message : e);
32
+ swallow(e, 'sizeof estimation failed', { level: 'debug' });
31
33
  return 0;
32
34
  }
33
35
  }