@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
@@ -0,0 +1,327 @@
1
+ /**
2
+ * timber-post-build — the post-build phase, as one ordered handler.
3
+ *
4
+ * Everything timber does after Vite has built the three environments runs
5
+ * here, in this order, each step handed what the previous one returned:
6
+ *
7
+ * 1. finalize the build manifest — font entries, the RSC assets manifest
8
+ * merged in once, JavaScript stripped once when client JS is disabled
9
+ * 2. prebuilt capture (cache.component prerender payloads, design/44)
10
+ * 3. static generation (output: 'static', design/11)
11
+ * 4. the build report
12
+ * 5. assemble `BuildArtifacts` and call the adapter's `buildOutput`
13
+ *
14
+ * One `buildApp` hook with `order: 'post'` — so Vite runs the RSC plugin's
15
+ * buildApp, which orchestrates every environment build and writes the
16
+ * assets manifests, first. The order above is this function's, not the
17
+ * plugin array's, and no step reads another's result off the shared
18
+ * context: sibling plugins contribute through the typed steps they expose
19
+ * (`FontsBuildStep`, `PrebuiltBuildStep`, `BuildReportStep`), which
20
+ * `timber()` hands to this plugin directly.
21
+ *
22
+ * Design docs: 18-build-system.md §"Post-Build Phase", 11-platform.md
23
+ * §"Build Artifacts", 49-explicit-subsystem-boundaries.md §B
24
+ */
25
+
26
+ import type { Plugin, Rollup } from 'vite';
27
+ import { readdir } from 'node:fs/promises';
28
+ import { join, relative, resolve } from 'node:path';
29
+ import { adapterConfig, contextAdapter, type PluginContext } from '../plugin-context.ts';
30
+ import type { BuildArtifacts, DirectoryArtifact } from '../adapters/types.ts';
31
+ import type { BuildManifest } from '../server/build-manifest.ts';
32
+ import type { FontsBuildStep } from './fonts.ts';
33
+ import type { PrebuiltBuildStep } from './prebuilt.ts';
34
+ import type { BuildReportStep } from './build-report.ts';
35
+ import { runStaticGeneration, type StaticSite } from './static-build.ts';
36
+ import { mergeRscAssetsManifest, stripJsFromRscAssetsManifests } from './rsc-assets-manifest.ts';
37
+
38
+ /** The Vite environments whose output adapters consume. */
39
+ const ARTIFACT_ENVIRONMENTS = ['client', 'rsc', 'ssr'] as const;
40
+ type ArtifactEnvironment = (typeof ARTIFACT_ENVIRONMENTS)[number];
41
+
42
+ function isArtifactEnvironment(name: string): name is ArtifactEnvironment {
43
+ return (ARTIFACT_ENVIRONMENTS as readonly string[]).includes(name);
44
+ }
45
+
46
+ /** Each environment's output directory, as its own `writeBundle` recorded it. */
47
+ export type EnvironmentOutputs = Partial<Record<ArtifactEnvironment, DirectoryArtifact>>;
48
+
49
+ /** The steps sibling plugins own. */
50
+ export interface PostBuildSteps {
51
+ fonts: FontsBuildStep;
52
+ prebuilt: PrebuiltBuildStep;
53
+ report: BuildReportStep;
54
+ }
55
+
56
+ export function timberPostBuild(ctx: PluginContext, steps: PostBuildSteps): Plugin {
57
+ const environments: EnvironmentOutputs = {};
58
+ /** What the client environment's bundle wrote, from its `writeBundle`. */
59
+ let clientOutput: ClientOutput = { assetsDir: '', emitted: new Set() };
60
+
61
+ return {
62
+ name: 'timber-post-build',
63
+
64
+ // Record each environment's output directory as it is written, so the
65
+ // phase learns what exists from the build rather than by probing for
66
+ // it. The RSC plugin's scan builds run with `write: false` and never
67
+ // reach this hook; only the real bundles do.
68
+ writeBundle(options, bundle) {
69
+ if (ctx.dev) return;
70
+ const env = this.environment;
71
+ if (!isArtifactEnvironment(env.name)) return;
72
+ environments[env.name] = { path: resolve(env.config.root, env.config.build.outDir) };
73
+ if (env.name === 'client') {
74
+ clientOutput = {
75
+ assetsDir: hashedAssetsDir(env.config.build.assetsDir, options),
76
+ emitted: new Set(Object.keys(bundle)),
77
+ };
78
+ }
79
+ },
80
+
81
+ buildApp: {
82
+ order: 'post' as const,
83
+ async handler() {
84
+ if (ctx.dev) return;
85
+ await runPostBuild(ctx, steps, environments, clientOutput);
86
+ },
87
+ },
88
+ };
89
+ }
90
+
91
+ /**
92
+ * The client bundle's assets directory, in the artifacts' form (no leading
93
+ * or trailing slash) — or `''` when its files are not all content-hashed.
94
+ *
95
+ * `assetsDir` names where Vite writes; it is the naming patterns that decide
96
+ * whether a file name carries a hash. Vite's defaults do
97
+ * (`<assetsDir>/[name]-[hash].js`), but an app can set
98
+ * `assetFileNames: 'static/[name][extname]'`, and marking that directory
99
+ * immutable would pin a changed image under an unchanged URL for a year. A
100
+ * pattern given as a function cannot be inspected, so it counts as unhashed:
101
+ * those files fall back to the revalidating per-file rule.
102
+ *
103
+ * @internal Exported for testing.
104
+ */
105
+ export function hashedAssetsDir(
106
+ assetsDir: string,
107
+ output: Pick<
108
+ Rollup.NormalizedOutputOptions,
109
+ 'entryFileNames' | 'chunkFileNames' | 'assetFileNames'
110
+ >
111
+ ): string {
112
+ const dir = assetsDir.replace(/^\/+|\/+$/g, '');
113
+ const patterns = [output.entryFileNames, output.chunkFileNames, output.assetFileNames];
114
+ const hashed = patterns.every((p) => typeof p === 'string' && p.includes('[hash'));
115
+ return hashed ? dir : '';
116
+ }
117
+
118
+ /** The client bundle as its own `writeBundle` saw it. */
119
+ interface ClientOutput {
120
+ /** From `hashedAssetsDir` — `''` when the naming patterns are not all hashed. */
121
+ assetsDir: string;
122
+ /** Every file name the bundle emitted, relative to the client output directory. */
123
+ emitted: ReadonlySet<string>;
124
+ }
125
+
126
+ /**
127
+ * Keep only the directories whose every file the client bundle emitted.
128
+ *
129
+ * A producer knows it hashes what *it* writes, not what else lands beside it:
130
+ * Vite copies `public/` into the client output verbatim, so `public/assets/logo.png`
131
+ * sits in `assets/` under a stable name, and `public/_rsc/…` would sit among
132
+ * the hashed payloads. A directory holding any file the bundle did not emit
133
+ * is not content-hashed as a whole, and marking it immutable would pin that
134
+ * file for a year — so it is dropped, and its files take the per-file rule.
135
+ *
136
+ * @internal Exported for testing.
137
+ */
138
+ export async function onlyEmittedDirs(
139
+ clientDir: string,
140
+ dirs: readonly string[],
141
+ emitted: ReadonlySet<string>
142
+ ): Promise<string[]> {
143
+ const kept: string[] = [];
144
+ for (const dir of dirs) {
145
+ const root = join(clientDir, dir);
146
+ const entries = await readdir(root, { recursive: true, withFileTypes: true }).catch(() => []);
147
+ const foreign = entries.some(
148
+ (entry) =>
149
+ entry.isFile() &&
150
+ !emitted.has(relative(clientDir, join(entry.parentPath, entry.name)).replace(/\\/g, '/'))
151
+ );
152
+ if (!foreign) kept.push(dir);
153
+ }
154
+ return kept;
155
+ }
156
+
157
+ async function runPostBuild(
158
+ ctx: PluginContext,
159
+ steps: PostBuildSteps,
160
+ environments: EnvironmentOutputs,
161
+ clientOutput: ClientOutput
162
+ ): Promise<void> {
163
+ const output = ctx.config.output ?? 'server';
164
+ const rsc = requireEnvironment(environments, 'rsc');
165
+ const ssr = requireEnvironment(environments, 'ssr');
166
+
167
+ // 1. The manifest is complete before anything renders with it. Published
168
+ // for the steps that import the built bundle in this process — the same
169
+ // value `manifestInit` carries to production. Assigned, never `??=`: a
170
+ // second build in one process must not render with the first one's.
171
+ const manifest = await finalizeBuildManifest(ctx, steps.fonts, rsc, ssr);
172
+ if (manifest) Reflect.set(globalThis, '__TIMBER_BUILD_MANIFEST__', manifest);
173
+
174
+ // 2–3. Each writes its own output and returns what it wrote.
175
+ const prebuilt = await steps.prebuilt.capture(rsc.path);
176
+ const site = output === 'static' ? await runStaticGeneration(ctx, rsc.path) : undefined;
177
+
178
+ // 4.
179
+ steps.report.print(prebuilt);
180
+
181
+ // 5.
182
+ const adapter = contextAdapter(ctx);
183
+ if (!adapter || typeof adapter.buildOutput !== 'function') return;
184
+
185
+ await adapter.buildOutput(
186
+ adapterConfig(ctx),
187
+ assembleBuildArtifacts({
188
+ output,
189
+ outputDir: ctx.buildDir,
190
+ environments,
191
+ immutableDirs: await onlyEmittedDirs(
192
+ requireEnvironment(environments, 'client').path,
193
+ [
194
+ ...(clientOutput.assetsDir ? [clientOutput.assetsDir] : []),
195
+ ...steps.fonts.immutableDirs(),
196
+ ...(site?.immutableDirs ?? []),
197
+ ],
198
+ clientOutput.emitted
199
+ ),
200
+ prebuilt: prebuilt?.artifact,
201
+ site,
202
+ manifestInit: manifest ? serializeManifestInit(manifest) : undefined,
203
+ })
204
+ );
205
+ }
206
+
207
+ function requireEnvironment(
208
+ environments: EnvironmentOutputs,
209
+ name: ArtifactEnvironment
210
+ ): DirectoryArtifact {
211
+ const artifact = environments[name];
212
+ if (!artifact) {
213
+ throw new Error(`[timber] Build output: the ${name} environment wrote no bundle`);
214
+ }
215
+ return artifact;
216
+ }
217
+
218
+ /**
219
+ * Step 1: bring the build manifest to its final shape, once.
220
+ *
221
+ * `timber-build-manifest` creates it from the client bundle; this adds what
222
+ * only exists once every environment is built — the font entries and the
223
+ * per-route CSS and modulepreloads in the RSC plugin's assets manifest —
224
+ * and then, when client JavaScript is disabled, removes every JavaScript
225
+ * reference, from the manifest and from the assets manifests on disk. The
226
+ * manifest's `js` / `modulepreload` are cleared after the merge has written
227
+ * into them, so nothing the merge adds survives.
228
+ *
229
+ * Returns null only when no client bundle produced a manifest.
230
+ *
231
+ * @internal Exported for testing.
232
+ */
233
+ export async function finalizeBuildManifest(
234
+ ctx: PluginContext,
235
+ fonts: FontsBuildStep,
236
+ rsc: DirectoryArtifact,
237
+ ssr: DirectoryArtifact
238
+ ): Promise<BuildManifest | null> {
239
+ const manifest = ctx.buildManifest;
240
+ if (manifest) {
241
+ fonts.contributeManifest(manifest);
242
+ // Per-route CSS and client reference JS, for <link rel="stylesheet">
243
+ // and <link rel="modulepreload"> on server component routes (TIM-1014).
244
+ await mergeRscAssetsManifest(rsc.path, ctx.root, manifest, ctx.routeClientRefKeys);
245
+ }
246
+ if (ctx.clientJavascript.disabled) {
247
+ // Those files are not served, so hints for them are useless.
248
+ if (manifest) {
249
+ manifest.js = {};
250
+ manifest.modulepreload = {};
251
+ }
252
+ await stripJsFromRscAssetsManifests([rsc.path, ssr.path]);
253
+ }
254
+ return manifest;
255
+ }
256
+
257
+ /**
258
+ * The build manifest as a JS module that sets the global. Adapters write
259
+ * it as `_timber-manifest-init.js` (or prepend it to the entry) and
260
+ * evaluate it before the RSC handler, so `virtual:timber-build-manifest`
261
+ * finds it.
262
+ */
263
+ function serializeManifestInit(manifest: BuildManifest): string {
264
+ return `globalThis.__TIMBER_BUILD_MANIFEST__ = ${JSON.stringify(manifest)};\n`;
265
+ }
266
+
267
+ /**
268
+ * Dedupe the producers' directories and drop any that sits inside another.
269
+ *
270
+ * Two producers can name overlapping directories — a custom `assetsDir` of
271
+ * `_timber` beside the fonts' `_timber/fonts`. Cloudflare and Netlify apply
272
+ * every matching `_headers` rule, so emitting both would send two
273
+ * `Cache-Control` values for one file; the outer directory already covers
274
+ * the inner one.
275
+ */
276
+ function canonicalImmutableDirs(dirs: readonly string[]): string[] {
277
+ const unique = [...new Set(dirs)];
278
+ return unique.filter(
279
+ (dir) => !unique.some((other) => other !== dir && dir.startsWith(`${other}/`))
280
+ );
281
+ }
282
+
283
+ /**
284
+ * Assemble the adapter's view of the build from what each step returned.
285
+ *
286
+ * Not a validator: every field is copied from the phase that produced it.
287
+ * The throws are the states the union cannot represent — a Vite environment
288
+ * that wrote no bundle, a static build with no site. Each means an earlier
289
+ * phase failed without failing the build, and a deploy missing its SSR
290
+ * bundle fails on the first request rather than here.
291
+ *
292
+ * @internal Exported for testing.
293
+ */
294
+ export function assembleBuildArtifacts(input: {
295
+ output: 'server' | 'static';
296
+ outputDir: string;
297
+ environments: EnvironmentOutputs;
298
+ immutableDirs: readonly string[];
299
+ prebuilt?: DirectoryArtifact;
300
+ site?: StaticSite;
301
+ manifestInit?: string;
302
+ }): BuildArtifacts {
303
+ const { output, outputDir, environments } = input;
304
+ const client = requireEnvironment(environments, 'client');
305
+ const immutableDirs = canonicalImmutableDirs(input.immutableDirs);
306
+
307
+ if (output === 'static') {
308
+ if (!input.site) {
309
+ throw new Error(
310
+ "[timber] Build output: output is 'static' but static generation recorded no site"
311
+ );
312
+ }
313
+ const { pages, contentTypes } = input.site;
314
+ return { output, outputDir, client, immutableDirs, pages, contentTypes };
315
+ }
316
+
317
+ return {
318
+ output,
319
+ outputDir,
320
+ client,
321
+ immutableDirs,
322
+ rsc: requireEnvironment(environments, 'rsc'),
323
+ ssr: requireEnvironment(environments, 'ssr'),
324
+ prebuilt: input.prebuilt,
325
+ manifestInit: input.manifestInit,
326
+ };
327
+ }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Post-build prebuilt capture — Node-side orchestration (TIM-1119).
3
3
  *
4
- * Runs from timber-prebuilt's `buildApp` post hook, after Vite's 5-step
5
- * build sequence. Imports the BUILT `rsc/index.js` (the bundle carries
4
+ * Runs as the capture step of the post-build phase (plugins/post-build.ts),
5
+ * after Vite's 5-step build sequence and the manifest finalization step. Imports the BUILT `rsc/index.js` (the bundle carries
6
6
  * the react-server condition resolved at build time, so a plain dynamic
7
7
  * import works) and calls its `__timber_capturePrebuilt` export — the
8
8
  * capture itself must run inside the bundle's module graph, where the
@@ -25,11 +25,12 @@
25
25
  * prebuilt components.
26
26
  */
27
27
 
28
- import { existsSync } from 'node:fs';
29
- import { mkdir, rename, rm, writeFile } from 'node:fs/promises';
28
+ import { mkdir, rm } from 'node:fs/promises';
30
29
  import { dirname, join } from 'node:path';
31
30
  import { pathToFileURL } from 'node:url';
31
+ import { writeFileAtomic } from '../utils/write-file-atomic.ts';
32
32
 
33
+ import type { DirectoryArtifact } from '../adapters/types.ts';
33
34
  import type { PluginContext } from '../plugin-context.ts';
34
35
  import type { CaptureOptions, CaptureSummary, CapturedEntry } from '../server/prebuilt-builder.ts';
35
36
  import type { PrebuiltManifest } from '../server/prebuilt/payload-source.ts';
@@ -50,13 +51,6 @@ export interface PrebuiltArtifactWriter {
50
51
  finalize(): Promise<number>;
51
52
  }
52
53
 
53
- /** Write a file atomically: temp sibling + rename. */
54
- async function writeFileAtomic(path: string, data: Uint8Array | string): Promise<void> {
55
- const tmp = `${path}.tmp`;
56
- await writeFile(tmp, data);
57
- await rename(tmp, path);
58
- }
59
-
60
54
  /**
61
55
  * Create the writer for `.timber/dist/prebuilt/`. Storage layout per
62
56
  * design/44 §Storage: one directory per component ID, one `.flight` file
@@ -105,13 +99,20 @@ export function createPrebuiltArtifactWriter(prebuiltDir: string): PrebuiltArtif
105
99
  };
106
100
  }
107
101
 
102
+ /** What a capture pass produced. */
103
+ export interface PrebuiltCaptureResult {
104
+ summary: CaptureSummary;
105
+ /** The payload directory — present only when the pass wrote a payload. */
106
+ artifact?: DirectoryArtifact;
107
+ }
108
+
108
109
  /**
109
110
  * Remove any `prebuilt/` output left by a previous build in this
110
111
  * directory (watch mode, `emptyOutDir: false`). A stale manifest would
111
112
  * make adapters ship payloads from an OLD build — reviving them serves
112
113
  * outdated content with that build's chunk references instead of the
113
114
  * intended miss → live render. Runs unconditionally at the start of the
114
- * post-build hook, BEFORE the capture decision: a build whose app no
115
+ * capture step, BEFORE the capture decision: a build whose app no
115
116
  * longer declares any prebuilt components must also shed the artifacts
116
117
  * (codex P2 on PR #836).
117
118
  */
@@ -133,28 +134,19 @@ interface CaptureModule {
133
134
  * component). Per-entry data errors skip-and-report per design/44
134
135
  * §Build-Phase Error Handling.
135
136
  */
136
- export async function runPrebuiltCapture(ctx: PluginContext): Promise<CaptureSummary> {
137
+ export async function runPrebuiltCapture(
138
+ ctx: PluginContext,
139
+ rscDir: string
140
+ ): Promise<PrebuiltCaptureResult> {
137
141
  const routeComponents = ctx.routePrebuiltComponents;
138
142
  if (!routeComponents || routeComponents.size === 0) {
139
- return { captured: 0, skipped: [], hardErrors: [], nestingWarnings: 0 };
140
- }
141
-
142
- const entryPath = join(ctx.buildDir, 'rsc', 'index.js');
143
- if (!existsSync(entryPath)) {
144
- throw new Error(
145
- `[timber] prebuilt capture: built RSC entry not found at ${entryPath} — ` +
146
- `the app declares cache.component({ prerender: true }) call sites but the ` +
147
- `RSC build output is missing`
148
- );
143
+ return { summary: { captured: 0, skipped: [], hardErrors: [], nestingWarnings: 0 } };
149
144
  }
145
+ const entryPath = join(rscDir, 'index.js');
150
146
 
151
- // The same globals the adapter entry sets before importing the handler
152
- // (adapter-build.ts). The bundle's virtual:timber-build-manifest falls
153
- // back to an empty manifest, but set the real values when available so
154
- // capture-time behavior matches production startup.
147
+ // The build manifest global the bundle reads is published by the
148
+ // post-build phase before this step runs (plugins/post-build.ts).
155
149
  const g = globalThis as Record<string, unknown>;
156
- if (ctx.buildManifest) g.__TIMBER_BUILD_MANIFEST__ ??= ctx.buildManifest;
157
- if (ctx.deploymentId) g.__TIMBER_DEPLOYMENT_ID__ ??= ctx.deploymentId;
158
150
 
159
151
  console.log('[timber] cache.component: capturing prebuilt flight payloads…');
160
152
 
@@ -173,6 +165,7 @@ export async function runPrebuiltCapture(ctx: PluginContext): Promise<CaptureSum
173
165
  const entryUrl = `${pathToFileURL(entryPath).href}?t=${Date.now()}`;
174
166
  mod = (await import(/* @vite-ignore */ entryUrl)) as CaptureModule;
175
167
  } catch (error) {
168
+ // A missing entry lands here too: the import is the existence check.
176
169
  throw new Error(
177
170
  `[timber] prebuilt capture: failed to load the built RSC entry (${entryPath}). ` +
178
171
  `The capture pass runs the production server module inside the build process — ` +
@@ -188,7 +181,8 @@ export async function runPrebuiltCapture(ctx: PluginContext): Promise<CaptureSum
188
181
  );
189
182
  }
190
183
 
191
- const writer = createPrebuiltArtifactWriter(join(ctx.buildDir, 'prebuilt'));
184
+ const prebuiltDir = join(ctx.buildDir, 'prebuilt');
185
+ const writer = createPrebuiltArtifactWriter(prebuiltDir);
192
186
  const summary = await capture({
193
187
  fileComponentMap: Object.fromEntries(routeComponents),
194
188
  callSiteProps: ctx.prebuiltCallSiteProps
@@ -206,12 +200,14 @@ export async function runPrebuiltCapture(ctx: PluginContext): Promise<CaptureSum
206
200
  );
207
201
  }
208
202
 
209
- await writer.finalize();
203
+ // The manifest is written only when a payload was, so this is the one
204
+ // point that knows whether prebuilt/ is a product of this build.
205
+ const written = await writer.finalize();
210
206
 
211
207
  const total = summary.captured + summary.skipped.length;
212
208
  console.log(
213
209
  `[timber] Prebuilt ${summary.captured}/${total} entries.` +
214
210
  (summary.skipped.length > 0 ? ` ${summary.skipped.length} skipped due to errors.` : '')
215
211
  );
216
- return summary;
212
+ return written > 0 ? { summary, artifact: { path: prebuiltDir } } : { summary };
217
213
  }
@@ -71,6 +71,7 @@ import {
71
71
  import { collectJsxUsages, recordCallSiteProps } from './callsite-jsx.ts';
72
72
  import { mayPrerender, unwrapExpression } from './prebuilt-options-analysis.ts';
73
73
  import { cleanPrebuiltDir, runPrebuiltCapture } from './prebuilt-capture.ts';
74
+ import type { PrebuiltCaptureResult } from './prebuilt-capture.ts';
74
75
  import type {
75
76
  CallExpressionNode,
76
77
  IdentifierNode,
@@ -263,12 +264,11 @@ const DEFAULT_SENTINEL = '\0default';
263
264
 
264
265
  async function collectCrossModuleProps(
265
266
  ctx: PluginContext,
267
+ bindingNames: ReadonlyMap<string, ReadonlyMap<string, string>>,
266
268
  moduleId: string,
267
269
  getInfo: (id: string) => PrebuiltModuleInfo | null,
268
270
  resolve: (source: string, importer: string) => Promise<string | null>
269
271
  ): Promise<void> {
270
- const bindingNames = ctx.prebuiltBindingNames!;
271
-
272
272
  const info = getInfo(moduleId);
273
273
  if (!info) return;
274
274
 
@@ -362,10 +362,53 @@ async function collectCrossModuleProps(
362
362
  }
363
363
  }
364
364
 
365
- export function timberPrebuilt(ctx: PluginContext): Plugin {
365
+ /**
366
+ * What the post-build phase asks of the prebuilt plugin (plugins/post-build.ts).
367
+ */
368
+ export interface PrebuiltBuildStep {
369
+ /**
370
+ * Run the capture pass against the built RSC bundle in `rscDir`. Always
371
+ * removes the previous build's `prebuilt/` first — even when this build
372
+ * captures nothing, a stale manifest must never ship. Returns null when
373
+ * there was nothing to capture: no prerender call site is reachable from a
374
+ * route, or `output: 'static'` already renders everything at build time.
375
+ */
376
+ capture(rscDir: string): Promise<PrebuiltCaptureResult | null>;
377
+ }
378
+
379
+ export function timberPrebuilt(ctx: PluginContext): Plugin & { api: PrebuiltBuildStep } {
380
+ /**
381
+ * Module ID → prerender-capable component IDs declared in it. Recorded by
382
+ * the RSC transform, read by the RSC `generateBundle` module-graph walk
383
+ * that computes `ctx.routePrebuiltComponents`. Build only.
384
+ */
385
+ const moduleComponents = new Map<string, string[]>();
386
+ /**
387
+ * Module ID → variable name → component ID, for the prebuilt components
388
+ * that module declares. Read at `generateBundle` time to trace imports in
389
+ * other modules back to component IDs (cross-module call-site props).
390
+ */
391
+ const bindingNames = new Map<string, Map<string, string>>();
392
+
366
393
  return {
367
394
  name: 'timber-prebuilt',
368
395
 
396
+ api: {
397
+ async capture(rscDir) {
398
+ await cleanPrebuiltDir(ctx.buildDir);
399
+ if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return null;
400
+ if (ctx.config.output === 'static') {
401
+ // design/44 §output: 'static' — everything already renders at
402
+ // build time there; the wrapper is a no-op, not an error.
403
+ console.log(
404
+ `[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`
405
+ );
406
+ return null;
407
+ }
408
+ return runPrebuiltCapture(ctx, rscDir);
409
+ },
410
+ },
411
+
369
412
  transform(code, id) {
370
413
  // Drop this module's stale attribution first — in a long-lived
371
414
  // `vite build --watch` process the plugin context outlives builds,
@@ -374,7 +417,8 @@ export function timberPrebuilt(ctx: PluginContext): Plugin {
374
417
  // below (codex P2 on PR #836). Re-recorded at the bottom if the
375
418
  // edited module still has prerender-capable call sites.
376
419
  if (!ctx.dev && this?.environment?.name === 'rsc') {
377
- ctx.prebuiltModuleComponents?.delete(id);
420
+ moduleComponents.delete(id);
421
+ bindingNames.delete(id);
378
422
  }
379
423
  if (!code.includes('@timber-js/app/cache') && !code.includes('timber/cache')) return;
380
424
  // Skip node_modules (don't transform third-party code)
@@ -432,8 +476,7 @@ export function timberPrebuilt(ctx: PluginContext): Plugin {
432
476
  // Record this module's component IDs for the RSC generateBundle
433
477
  // module-graph walk (route → component attribution, TIM-1119).
434
478
  if (!ctx.dev && componentIds.length > 0 && this?.environment?.name === 'rsc') {
435
- ctx.prebuiltModuleComponents ??= new Map();
436
- ctx.prebuiltModuleComponents.set(id, componentIds);
479
+ moduleComponents.set(id, componentIds);
437
480
 
438
481
  // Record binding name → component ID mapping for cross-module
439
482
  // prop detection at generateBundle time (TIM-1142).
@@ -485,8 +528,7 @@ export function timberPrebuilt(ctx: PluginContext): Plugin {
485
528
  }
486
529
 
487
530
  if (bindingMap.size > 0) {
488
- ctx.prebuiltBindingNames ??= new Map();
489
- ctx.prebuiltBindingNames.set(id, bindingMap);
531
+ bindingNames.set(id, bindingMap);
490
532
  }
491
533
 
492
534
  // Same-module JSX usages: if a prebuilt component is declared AND
@@ -542,8 +584,8 @@ export function timberPrebuilt(ctx: PluginContext): Plugin {
542
584
  if (ctx.dev) return;
543
585
  if (this?.environment?.name !== 'rsc') return;
544
586
  ctx.routePrebuiltComponents = undefined;
545
- const moduleComponents = ctx.prebuiltModuleComponents;
546
- if (!moduleComponents || moduleComponents.size === 0 || !ctx.routeTree) return;
587
+ ctx.prebuiltLazyChunks = undefined;
588
+ if (moduleComponents.size === 0 || !ctx.routeTree) return;
547
589
 
548
590
  const self = this as unknown as {
549
591
  getModuleInfo?: (id: string) => PrebuiltModuleInfo | null;
@@ -592,7 +634,7 @@ export function timberPrebuilt(ctx: PluginContext): Plugin {
592
634
  // for JSX usages of prebuilt components — not just the route files
593
635
  // themselves. A component used in a helper (page → Shell → <BlogBody>)
594
636
  // must have its props captured from wherever the JSX lives.
595
- if (ctx.prebuiltBindingNames && ctx.prebuiltBindingNames.size > 0) {
637
+ if (bindingNames.size > 0) {
596
638
  const scannedModules = new Set<string>();
597
639
  for (const filePath of routeComponents.keys()) {
598
640
  const visited = new Set<string>();
@@ -603,7 +645,7 @@ export function timberPrebuilt(ctx: PluginContext): Plugin {
603
645
  visited.add(modId);
604
646
  if (!scannedModules.has(modId)) {
605
647
  scannedModules.add(modId);
606
- await collectCrossModuleProps(ctx, modId, getInfo, resolveFn);
648
+ await collectCrossModuleProps(ctx, bindingNames, modId, getInfo, resolveFn);
607
649
  }
608
650
  const modInfo = getInfo(modId);
609
651
  if (!modInfo) continue;
@@ -624,32 +666,5 @@ export function timberPrebuilt(ctx: PluginContext): Plugin {
624
666
  );
625
667
  }
626
668
  },
627
-
628
- /**
629
- * Post-build capture (design/44 §Build Phase). `order: 'post'` runs
630
- * after the RSC plugin's buildApp — all five build steps are complete —
631
- * and BEFORE timber-adapter-build's post hook (plugin array order), so
632
- * `prebuilt/` exists when the adapter assembles its output (TIM-1122).
633
- */
634
- buildApp: {
635
- order: 'post' as const,
636
- async handler() {
637
- if (ctx.dev) return;
638
- ctx.captureSummary = undefined;
639
- // Always shed a previous build's artifacts first — even when THIS
640
- // build captures nothing, a stale manifest must never ship.
641
- await cleanPrebuiltDir(ctx.buildDir);
642
- if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return;
643
- if (ctx.config.output === 'static') {
644
- // design/44 §output: 'static' — everything already renders at
645
- // build time there; the wrapper is a no-op, not an error.
646
- console.log(
647
- `[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`
648
- );
649
- return;
650
- }
651
- ctx.captureSummary = await runPrebuiltCapture(ctx);
652
- },
653
- },
654
669
  };
655
670
  }
@@ -227,10 +227,6 @@ export function timberPrerenderSugar(ctx: PluginContext): Plugin {
227
227
  if (declText.includes('.component(')) return;
228
228
  }
229
229
 
230
- // Record this page as desugared for downstream attribution
231
- ctx.prerenderSugarPages ??= new Set();
232
- ctx.prerenderSugarPages.add(id);
233
-
234
230
  const s = new MagicString(code);
235
231
  const optionsSource = buildOptionsSource(value);
236
232