@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
package/dist/index.js CHANGED
@@ -1,15 +1,17 @@
1
- import { a as formatMissingPeers, i as formatConfigErrors, n as timberDevServer, o as validateConfig, r as checkPeerDependencies } from "./_chunks/dev-server-BzBxgYAV.js";
1
+ import { a as formatMissingPeers, i as formatConfigErrors, n as timberDevServer, o as validateConfig, r as checkPeerDependencies } from "./_chunks/dev-server-C4WZdB7L.js";
2
+ import { i as resolveRenderTimeoutMs } from "./_chunks/render-timeout-DOf_BBcO.js";
3
+ import { t as writeFileAtomic } from "./_chunks/write-file-atomic-D1qWqHb4.js";
2
4
  import { a as isDynamicMetadataExtension } from "./_chunks/metadata-routes-DSDjM_hJ.js";
3
- import { n as scanRoutes, r as collectInterceptionRewrites } from "./_chunks/scanner-BQ5sPIJ7.js";
4
- import { h as swallow } from "./_chunks/logger-k2DQ4EUf.js";
5
- import { c as writeRouteCodegen, i as getPrerenderExport, l as buildDirToRouteMap, n as formatConventionWarnings, r as lintConventions, s as flushCodegenWrites, t as checkAppDirExists } from "./_chunks/convention-lint-5KzoMg_A.js";
6
- import { c as resolveClientJavascript, i as mergeFileConfig, l as createNoopTimer, o as resolveAppDir, r as loadTimberConfigFile, s as resolveBuildDir, t as createPluginContext } from "./_chunks/plugin-context-8idfR3UZ.js";
7
- import { r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "./_chunks/walkers-CN2N_bA-.js";
8
- import { i as poisonPillSource, r as markerFor, t as EXPLICIT_MARKERS } from "./_chunks/poison-rules-DoEhbqaY.js";
5
+ import { n as scanRoutes, r as collectInterceptionRewrites } from "./_chunks/scanner-Bw0oq1HB.js";
6
+ import { _ as swallow } from "./_chunks/logger-DiDt5ppH.js";
7
+ import { c as writeRouteCodegen, i as getPrerenderExport, l as buildDirToRouteMap, n as formatConventionWarnings, r as lintConventions, s as flushCodegenWrites, t as checkAppDirExists } from "./_chunks/convention-lint-jKTwKwPe.js";
8
+ import { a as loadTimberConfigFile, c as resolveAppDir, d as createNoopTimer, l as resolveBuildDir, n as contextAdapter, o as mergeFileConfig, r as createPluginContext, t as adapterConfig, u as resolveClientJavascript } from "./_chunks/plugin-context-BPBPc3lL.js";
9
9
  import { i as withBasePath, n as normalizeBasePath, t as isRelativeBase } from "./_chunks/base-path-DaQrzbez.js";
10
- import { t as EMPTY_BUILD_MANIFEST } from "./_chunks/build-manifest-DTmSGLRz.js";
11
- import { t as rscPayloadPath } from "./_chunks/rsc-payload-path-B_LBodc2.js";
12
- import { a as REDIRECTS_FILE, n as detectFsIdentity, o as RESERVED_OUTPUT_PATHS, r as fsKey, t as EXACT_FS_IDENTITY } from "./_chunks/fs-identity-D7vb6GdI.js";
10
+ import { r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "./_chunks/walkers-BXExhzzk.js";
11
+ import { i as poisonPillSource, r as markerFor, t as EXPLICIT_MARKERS } from "./_chunks/poison-rules-DoEhbqaY.js";
12
+ import { n as rscPayloadPath, t as RSC_PAYLOAD_DIR } from "./_chunks/rsc-payload-path-dffcs4jp.js";
13
+ import { a as REDIRECTS_FILE, n as detectFsIdentity, o as RESERVED_OUTPUT_PATHS, r as fsKey, t as EXACT_FS_IDENTITY } from "./_chunks/fs-identity-BRKuL215.js";
14
+ import { t as EMPTY_BUILD_MANIFEST } from "./_chunks/build-manifest-DWppEdLB.js";
13
15
  import { t as fnv1aHash } from "./_chunks/fast-hash-C-tVYrLb.js";
14
16
  import { t as formatSize } from "./_chunks/format-BKclgVbk.js";
15
17
  import { createLogger, parseAst } from "vite";
@@ -202,7 +204,7 @@ function generateConfigModule(ctx) {
202
204
  topLoader: ctx.config.topLoader,
203
205
  debug: ctx.config.debug ?? false,
204
206
  serverTiming: ctx.config.serverTiming,
205
- renderTimeoutMs: ctx.config.renderTimeoutMs ?? 3e4,
207
+ renderTimeoutMs: resolveRenderTimeoutMs(ctx.config.renderTimeoutMs),
206
208
  sitemap: ctx.config.sitemap,
207
209
  forms: serializeFormsConfig(ctx.config.forms),
208
210
  deploymentId: ctx.deploymentId ?? null,
@@ -962,7 +964,8 @@ var SUBPATH_SRC_MAP = {
962
964
  "adapters/cloudflare": "adapters/cloudflare.ts",
963
965
  "adapters/cloudflare/cache": "adapters/cloudflare-kv-cache.ts",
964
966
  "adapters/cloudflare/dev": "adapters/cloudflare-dev.ts",
965
- "adapters/nitro": "adapters/nitro.ts"
967
+ "adapters/nitro": "adapters/nitro.ts",
968
+ "adapters/types": "adapters/types.ts"
966
969
  };
967
970
  /**
968
971
  * Runtime value exports of @timber-js/app/server, stubbed in the client
@@ -4543,8 +4546,14 @@ function writeFontManifest(pipeline, buildManifest, base = "/") {
4543
4546
  */
4544
4547
  function timberFonts(ctx) {
4545
4548
  const pipeline = new FontPipeline({ hashOnRegister: !ctx.dev });
4549
+ /** Whether the client environment emitted a binary this build. */
4550
+ let emittedToClient = false;
4546
4551
  return {
4547
4552
  name: "timber-fonts",
4553
+ api: {
4554
+ contributeManifest: (manifest) => writeFontManifest(pipeline, manifest, ctx.base),
4555
+ immutableDirs: () => emittedToClient ? [FONT_OUTPUT_DIR] : []
4556
+ },
4548
4557
  /**
4549
4558
  * Push Vite's resolved `base` into the pipeline so every font URL it
4550
4559
  * emits (@font-face src, manifest hrefs, dev middleware matching)
@@ -4724,213 +4733,24 @@ function timberFonts(ctx) {
4724
4733
  }
4725
4734
  },
4726
4735
  /**
4727
- * Emit font binaries and build-manifest entries.
4736
+ * Emit font binaries.
4728
4737
  *
4729
4738
  * All font binaries (Google and local) use content-hashed filenames
4730
4739
  * for immutable caching. Font CSS is handled by Vite's CSS pipeline
4731
- * via virtual modules — we only emit binaries here.
4740
+ * via virtual modules — we only emit binaries here. Manifest entries are
4741
+ * written by the post-build phase through `api.contributeManifest`.
4732
4742
  */
4733
4743
  generateBundle() {
4734
- emitFontAssets(pipeline, (asset) => this.emitFile(asset), (msg) => this.warn(msg));
4735
- if (!ctx.buildManifest) return;
4736
- writeFontManifest(pipeline, ctx.buildManifest, ctx.base);
4744
+ let emitted = 0;
4745
+ emitFontAssets(pipeline, (asset) => {
4746
+ emitted++;
4747
+ return this.emitFile(asset);
4748
+ }, (msg) => this.warn(msg));
4749
+ if (this.environment?.name === "client") emittedToClient = emitted > 0;
4737
4750
  }
4738
4751
  };
4739
4752
  }
4740
4753
  //#endregion
4741
- //#region src/plugins/adapter-build.ts
4742
- function timberAdapterBuild(ctx) {
4743
- return {
4744
- name: "timber-adapter-build",
4745
- buildApp: {
4746
- order: "post",
4747
- async handler() {
4748
- if (ctx.dev) return;
4749
- const adapter = ctx.config.adapter;
4750
- if (!adapter || typeof adapter.buildOutput !== "function") return;
4751
- const buildDir = ctx.buildDir;
4752
- if (ctx.buildManifest) await mergeRscAssetsManifest(buildDir, ctx.root, ctx.buildManifest, ctx.routeClientRefKeys);
4753
- let manifestInit;
4754
- if (ctx.buildManifest) {
4755
- const manifest = ctx.clientJavascript.disabled ? {
4756
- ...ctx.buildManifest,
4757
- js: {},
4758
- modulepreload: {}
4759
- } : ctx.buildManifest;
4760
- manifestInit = `globalThis.__TIMBER_BUILD_MANIFEST__ = ${JSON.stringify(manifest)};\n`;
4761
- if (ctx.deploymentId) manifestInit += `globalThis.__TIMBER_DEPLOYMENT_ID__ = ${JSON.stringify(ctx.deploymentId)};\n`;
4762
- }
4763
- if (ctx.clientJavascript.disabled) await stripJsFromRscAssetsManifests(buildDir);
4764
- const adapterConfig = {
4765
- root: ctx.root,
4766
- base: normalizeBasePath(ctx.base),
4767
- output: ctx.config.output ?? "server",
4768
- clientJavascriptDisabled: ctx.clientJavascript.disabled,
4769
- manifestInit,
4770
- staticPagesDir: (ctx.config.output ?? "server") === "static" ? join(buildDir, "static-pages") : void 0,
4771
- staticContentTypes: ctx.staticContentTypes
4772
- };
4773
- await adapter.buildOutput(adapterConfig, buildDir);
4774
- }
4775
- }
4776
- };
4777
- }
4778
- /**
4779
- * Parse the RSC assets manifest at `manifestPath`. Tries JSON.parse first
4780
- * (fast path for plain-string manifests); falls back to a dynamic import()
4781
- * for manifests that contain runtime expressions from renderBuiltUrl.
4782
- * Returns null if both paths fail.
4783
- */
4784
- async function parseRscManifest(manifestPath, content) {
4785
- const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
4786
- try {
4787
- return JSON.parse(jsonStr);
4788
- } catch {}
4789
- try {
4790
- return (await import(`${pathToFileURL(manifestPath).href}?t=${Date.now()}`)).default ?? null;
4791
- } catch (err) {
4792
- swallow(err, `failed to evaluate RSC assets manifest: ${manifestPath}`, { level: "warn" });
4793
- return null;
4794
- }
4795
- }
4796
- /**
4797
- * Replace all `"js": [...]` array contents with `"js": []` using balanced
4798
- * bracket matching. Handles nested brackets from runtime expressions like
4799
- * `__rbu("path/to/[slug]/file.js")`.
4800
- */
4801
- function clearJsArrays(src) {
4802
- const pattern = /"js"\s*:\s*\[/g;
4803
- let result = "";
4804
- let lastEnd = 0;
4805
- let match;
4806
- while ((match = pattern.exec(src)) !== null) {
4807
- const arrayStart = match.index + match[0].length;
4808
- let depth = 1;
4809
- let i = arrayStart;
4810
- while (i < src.length && depth > 0) {
4811
- if (src[i] === "[") depth++;
4812
- else if (src[i] === "]") depth--;
4813
- i++;
4814
- }
4815
- result += src.slice(lastEnd, match.index) + "\"js\": []";
4816
- lastEnd = i;
4817
- }
4818
- result += src.slice(lastEnd);
4819
- return result;
4820
- }
4821
- /**
4822
- * Replace `"bootstrapScriptContent": <value>` with an empty string. The
4823
- * value may be a JS expression (e.g., concatenation with runtime helpers),
4824
- * not a simple string literal. Scans forward from the colon, tracking
4825
- * balanced parens and brackets, and stops at the next unbalanced `,` or `}`.
4826
- */
4827
- function clearBootstrapScriptContent(src) {
4828
- const idx = src.indexOf("\"bootstrapScriptContent\"");
4829
- if (idx === -1) return src;
4830
- const colonIdx = src.indexOf(":", idx + 24);
4831
- if (colonIdx === -1) return src;
4832
- let valStart = colonIdx + 1;
4833
- while (valStart < src.length && /\s/.test(src[valStart])) valStart++;
4834
- let i = valStart;
4835
- let depth = 0;
4836
- let inString = false;
4837
- let stringChar = "";
4838
- while (i < src.length) {
4839
- const ch = src[i];
4840
- if (inString) {
4841
- if (ch === "\\") {
4842
- i += 2;
4843
- continue;
4844
- }
4845
- if (ch === stringChar) inString = false;
4846
- } else if (ch === "\"" || ch === "'") {
4847
- inString = true;
4848
- stringChar = ch;
4849
- } else if (ch === "(" || ch === "[") depth++;
4850
- else if (ch === ")" || ch === "]") depth--;
4851
- else if (depth === 0 && (ch === "," || ch === "}" || ch === "\n")) break;
4852
- i++;
4853
- }
4854
- return src.slice(0, idx) + "\"bootstrapScriptContent\": \"\"" + src.slice(i);
4855
- }
4856
- /**
4857
- * Strip JS references from the RSC plugin's assets manifest files.
4858
- *
4859
- * The RSC plugin writes `__vite_rsc_assets_manifest.js` to rsc/ and ssr/
4860
- * as standalone files (not Rollup chunks), so generateBundle can't
4861
- * intercept them. This rewrites the files on disk after all builds
4862
- * complete but before the adapter copies them to the output directory.
4863
- */
4864
- /**
4865
- * Read the RSC plugin's assets manifest and merge per-route CSS and
4866
- * per-route JS modulepreloads into the build manifest.
4867
- *
4868
- * CSS: `serverResources` maps server component paths to CSS URLs.
4869
- * JS: `clientReferenceDeps` maps reference hashes to JS dep URLs.
4870
- * Combined with `routeClientRefKeys` (from the RSC generateBundle
4871
- * module graph walk) to produce per-route modulepreload entries.
4872
- */
4873
- async function mergeRscAssetsManifest(buildDir, root, buildManifest, routeClientRefKeys) {
4874
- const manifestPath = join(buildDir, "rsc", "__vite_rsc_assets_manifest.js");
4875
- let content;
4876
- try {
4877
- content = await readFile(manifestPath, "utf-8");
4878
- } catch {
4879
- return;
4880
- }
4881
- const manifest = await parseRscManifest(manifestPath, content);
4882
- if (!manifest) return;
4883
- const serverResources = manifest.serverResources;
4884
- if (serverResources) {
4885
- for (const [relativePath, deps] of Object.entries(serverResources)) if (deps.css && deps.css.length > 0) {
4886
- const absolutePath = join(root, relativePath);
4887
- buildManifest.css[absolutePath] = deps.css;
4888
- }
4889
- }
4890
- if (routeClientRefKeys && routeClientRefKeys.size > 0) {
4891
- const clientReferenceDeps = manifest.clientReferenceDeps;
4892
- if (clientReferenceDeps) for (const [filePath, refKeys] of routeClientRefKeys) {
4893
- const jsUrls = /* @__PURE__ */ new Set();
4894
- for (const key of refKeys) {
4895
- const deps = clientReferenceDeps[key];
4896
- if (deps?.js) for (const url of deps.js) jsUrls.add(url);
4897
- }
4898
- if (jsUrls.size > 0) buildManifest.modulepreload[filePath] = Array.from(jsUrls);
4899
- }
4900
- }
4901
- }
4902
- async function stripJsFromRscAssetsManifests(buildDir) {
4903
- const manifestName = "__vite_rsc_assets_manifest.js";
4904
- const paths = [join(buildDir, "rsc", manifestName), join(buildDir, "ssr", manifestName)];
4905
- for (const path of paths) {
4906
- let content;
4907
- try {
4908
- content = await readFile(path, "utf-8");
4909
- } catch {
4910
- continue;
4911
- }
4912
- const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
4913
- let isStrictJson = true;
4914
- let manifest = null;
4915
- try {
4916
- manifest = JSON.parse(jsonStr);
4917
- } catch {
4918
- isStrictJson = false;
4919
- }
4920
- if (!isStrictJson) {
4921
- let rewritten = content;
4922
- rewritten = clearJsArrays(rewritten);
4923
- rewritten = clearBootstrapScriptContent(rewritten);
4924
- await writeFile(path, rewritten);
4925
- continue;
4926
- }
4927
- const deps = manifest?.clientReferenceDeps;
4928
- if (deps) for (const entry of Object.values(deps)) entry.js = [];
4929
- if (manifest) manifest.bootstrapScriptContent = "";
4930
- await writeFile(path, `export default ${JSON.stringify(manifest, null, 2)};\n`);
4931
- }
4932
- }
4933
- //#endregion
4934
4754
  //#region src/server/flight-scripts.ts
4935
4755
  /**
4936
4756
  * Escape a JSON string for safe embedding inside an HTML `<script>` tag.
@@ -5012,12 +4832,6 @@ function generateRedirectsFile(redirects, base) {
5012
4832
  const target = (to) => to.startsWith("/") && !to.startsWith("//") ? withBasePath(base, to) : to;
5013
4833
  return redirects.map((r) => `${withBasePath(base, r.from)} ${target(r.to)} ${r.status}`).join("\n") + "\n";
5014
4834
  }
5015
- /** Write a file atomically: temp sibling + rename. */
5016
- async function writeFileAtomic$1(path, data) {
5017
- const tmp = `${path}.tmp`;
5018
- await writeFile(tmp, data);
5019
- await rename(tmp, path);
5020
- }
5021
4835
  /**
5022
4836
  * Determine the output file path for a static page entry.
5023
4837
  *
@@ -5056,7 +4870,7 @@ function staticOutputPath(entry) {
5056
4870
  * API route, `about/index.html` from a page). The filesystem does refuse that
5057
4871
  * one — `EISDIR` on the rename, `ENOTDIR` on the mkdir, depending on which
5058
4872
  * lands second — but an errno names a path, and in the rename case the path
5059
- * it names is `about.tmp`. Reported here instead, so the message says which
4873
+ * it names is the write's temp file. Reported here instead, so the message says which
5060
4874
  * two routes.
5061
4875
  *
5062
4876
  * Collisions are **collected, not thrown**. `onEntry` runs inside the
@@ -5145,7 +4959,7 @@ var StaticSiteWriter = class {
5145
4959
  if (rel.split(/[\\/]/)[0] === ".." || isAbsolute(rel) || resolve(this.staticDir, rel) !== fullPath) throw new Error(`[timber] Static generation: output path "${relPath}" escapes the static output directory — check generateStaticSegmentParams for path traversal characters in ${entry.urlPath}`);
5146
4960
  if (!this.paths.claim(rel.replace(/\\/g, "/"), entry)) return;
5147
4961
  await mkdir(dirname(fullPath), { recursive: true });
5148
- await writeFileAtomic$1(fullPath, entry.body);
4962
+ await writeFileAtomic(fullPath, entry.body);
5149
4963
  if (entry.kind === "api" && !extname(relPath) && entry.contentType) this.contentTypes[entry.urlPath] = entry.contentType;
5150
4964
  }
5151
4965
  /** Throw if any two entries could not both be written. */
@@ -5173,7 +4987,7 @@ var StaticSiteWriter = class {
5173
4987
  * @internal Exported for testing.
5174
4988
  */
5175
4989
  async function cleanConditionalArtifacts(staticDir) {
5176
- await rm(join(staticDir, "_rsc"), {
4990
+ await rm(join(staticDir, RSC_PAYLOAD_DIR), {
5177
4991
  recursive: true,
5178
4992
  force: true
5179
4993
  }).catch(() => {});
@@ -5219,19 +5033,21 @@ async function withSchedulerPortsReleased(fn) {
5219
5033
  }
5220
5034
  }
5221
5035
  /**
5222
- * Load the built RSC entry and run the static generation pass.
5036
+ * Load the built RSC entry and run the static generation pass — the static
5037
+ * generation step of the post-build phase (plugins/post-build.ts).
5223
5038
  *
5224
- * Unlike prebuilt capture, this needs the FULL pipeline handler, so
5039
+ * The build manifest it renders with is already final: the phase merged the
5040
+ * RSC assets manifest into it and published it before this step. Unlike
5041
+ * prebuilt capture, this needs the FULL pipeline handler, so
5225
5042
  * __TIMBER_CAPTURE_MODE__ must be false.
5043
+ *
5044
+ * Returns the site only once it is complete, so an adapter is never handed a
5045
+ * directory a failed pass left half-written — a failure throws instead.
5226
5046
  */
5227
- async function runStaticGeneration(ctx) {
5228
- const entryPath = join(ctx.buildDir, "rsc", "index.js");
5229
- if (!existsSync(entryPath)) throw new Error(`[timber] Static generation: built RSC entry not found at ${entryPath} — the build output is missing`);
5230
- const g = globalThis;
5231
- if (ctx.buildManifest) g.__TIMBER_BUILD_MANIFEST__ ??= ctx.buildManifest;
5232
- if (ctx.deploymentId) g.__TIMBER_DEPLOYMENT_ID__ ??= ctx.deploymentId;
5233
- g.__TIMBER_CAPTURE_MODE__ = false;
5234
- if (ctx.buildManifest) await mergeRscAssetsManifest(ctx.buildDir, ctx.root, ctx.buildManifest, ctx.routeClientRefKeys);
5047
+ async function runStaticGeneration(ctx, rscDir) {
5048
+ const entryPath = join(rscDir, "index.js");
5049
+ warnUnusableBase(ctx);
5050
+ globalThis.__TIMBER_CAPTURE_MODE__ = false;
5235
5051
  console.log("[timber] Static generation: building site…");
5236
5052
  const staticDir = join(ctx.buildDir, "static-pages");
5237
5053
  await cleanConditionalArtifacts(staticDir);
@@ -5265,12 +5081,12 @@ async function runStaticGeneration(ctx) {
5265
5081
  throw new Error(`[timber] Static generation failed:\n${details}`);
5266
5082
  }
5267
5083
  writer.assertNoCollisions();
5268
- if (Object.keys(writer.contentTypes).length > 0) ctx.staticContentTypes = writer.contentTypes;
5084
+ const immutableDirs = [];
5269
5085
  if (!ctx.clientJavascript.disabled) {
5270
5086
  const rscManifest = await hashRscPayloads(staticDir);
5271
5087
  if (Object.keys(rscManifest).length > 0) {
5088
+ immutableDirs.push(RSC_PAYLOAD_DIR);
5272
5089
  await injectRscManifestIntoHtml(staticDir, rscManifest);
5273
- ctx.rscManifest = rscManifest;
5274
5090
  console.log(`[timber] Static generation: hashed ${Object.keys(rscManifest).length} RSC flight payloads`);
5275
5091
  }
5276
5092
  }
@@ -5279,14 +5095,18 @@ async function runStaticGeneration(ctx) {
5279
5095
  const redirectsPath = join(staticDir, REDIRECTS_FILE);
5280
5096
  const userRedirects = await readUserRedirects(ctx.root);
5281
5097
  if (userRedirects !== null) {
5282
- await writeFileAtomic$1(redirectsPath, generated + "\n" + userRedirects);
5098
+ await writeFileAtomic(redirectsPath, generated + "\n" + userRedirects);
5283
5099
  console.log(`[timber] Static generation: wrote _redirects with ${summary.redirects.length} generated rule(s), merged with user-authored _redirects`);
5284
5100
  } else {
5285
- await writeFileAtomic$1(redirectsPath, generated);
5101
+ await writeFileAtomic(redirectsPath, generated);
5286
5102
  console.log(`[timber] Static generation: wrote _redirects with ${summary.redirects.length} rule(s)`);
5287
5103
  }
5288
5104
  }
5289
- return summary;
5105
+ return {
5106
+ pages: { path: staticDir },
5107
+ contentTypes: writer.contentTypes,
5108
+ immutableDirs
5109
+ };
5290
5110
  }
5291
5111
  /**
5292
5112
  * Warn when Vite's `base` is document-relative (`'./'`) in static mode.
@@ -5359,7 +5179,7 @@ async function walkDir(dir) {
5359
5179
  * @internal Exported for testing.
5360
5180
  */
5361
5181
  async function hashRscPayloads(staticDir) {
5362
- const files = await walkDir(join(staticDir, "_rsc"));
5182
+ const files = await walkDir(join(staticDir, RSC_PAYLOAD_DIR));
5363
5183
  const manifest = {};
5364
5184
  for (const filePath of files) {
5365
5185
  if (!filePath.endsWith(".rsc")) continue;
@@ -5407,11 +5227,9 @@ async function readUserRedirects(root) {
5407
5227
  /**
5408
5228
  * Create the timber-static-build Vite plugin.
5409
5229
  *
5410
- * Only active when output: 'static' is configured.
5411
- *
5412
- * Hooks:
5413
- * - transform: Validates source files for static mode violations
5414
- * - buildApp (post): Renders all routes to static HTML after the build
5230
+ * Only active when output: 'static' is configured. Validates source files
5231
+ * for static mode violations; rendering the site is `runStaticGeneration`,
5232
+ * which the post-build phase calls.
5415
5233
  */
5416
5234
  function timberStaticBuild(ctx) {
5417
5235
  return {
@@ -5433,22 +5251,6 @@ function timberStaticBuild(ctx) {
5433
5251
  this.error(messages.join("\n\n"));
5434
5252
  }
5435
5253
  return null;
5436
- },
5437
- /**
5438
- * After all environments are built, render every route to static HTML.
5439
- *
5440
- * Runs with order: 'post' so the RSC plugin's buildApp completes first,
5441
- * producing the built entry we import. Must run BEFORE the adapter
5442
- * build copies output to its platform-specific directory.
5443
- */
5444
- buildApp: {
5445
- order: "post",
5446
- async handler() {
5447
- if (ctx.dev) return;
5448
- if (!(ctx.config.output === "static")) return;
5449
- warnUnusableBase(ctx);
5450
- await runStaticGeneration(ctx);
5451
- }
5452
5254
  }
5453
5255
  };
5454
5256
  }
@@ -5658,8 +5460,6 @@ function timberBuildManifest(ctx) {
5658
5460
  if (ctx.requestDepMap === void 0) throw new Error("[timber] Build manifest: the request-dependency map was never computed. The RSC environment's buildEnd hook did not run before the client build, so no segment or slot could be skipped on client navigation. This is a plugin pipeline bug — timber-request-dep must run in the rsc environment.");
5659
5461
  ctx.buildManifest.requestDep = ctx.requestDepMap;
5660
5462
  if (ctx.clientJavascript.disabled) {
5661
- ctx.buildManifest.js = {};
5662
- ctx.buildManifest.modulepreload = {};
5663
5463
  for (const [fileName, item] of Object.entries(bundle)) if (item.type === "chunk") delete bundle[fileName];
5664
5464
  }
5665
5465
  }
@@ -7841,8 +7641,8 @@ function mayPrerender(call) {
7841
7641
  /**
7842
7642
  * Post-build prebuilt capture — Node-side orchestration (TIM-1119).
7843
7643
  *
7844
- * Runs from timber-prebuilt's `buildApp` post hook, after Vite's 5-step
7845
- * build sequence. Imports the BUILT `rsc/index.js` (the bundle carries
7644
+ * Runs as the capture step of the post-build phase (plugins/post-build.ts),
7645
+ * after Vite's 5-step build sequence and the manifest finalization step. Imports the BUILT `rsc/index.js` (the bundle carries
7846
7646
  * the react-server condition resolved at build time, so a plain dynamic
7847
7647
  * import works) and calls its `__timber_capturePrebuilt` export — the
7848
7648
  * capture itself must run inside the bundle's module graph, where the
@@ -7871,12 +7671,6 @@ function mayPrerender(call) {
7871
7671
  */
7872
7672
  var COMPONENT_ID_RE = /^[a-z0-9]+_[0-9a-f]{16}$/;
7873
7673
  var CACHE_KEY_RE = /^[0-9a-f]{16}$/;
7874
- /** Write a file atomically: temp sibling + rename. */
7875
- async function writeFileAtomic(path, data) {
7876
- const tmp = `${path}.tmp`;
7877
- await writeFile(tmp, data);
7878
- await rename(tmp, path);
7879
- }
7880
7674
  /**
7881
7675
  * Create the writer for `.timber/dist/prebuilt/`. Storage layout per
7882
7676
  * design/44 §Storage: one directory per component ID, one `.flight` file
@@ -7918,7 +7712,7 @@ function createPrebuiltArtifactWriter(prebuiltDir) {
7918
7712
  * make adapters ship payloads from an OLD build — reviving them serves
7919
7713
  * outdated content with that build's chunk references instead of the
7920
7714
  * intended miss → live render. Runs unconditionally at the start of the
7921
- * post-build hook, BEFORE the capture decision: a build whose app no
7715
+ * capture step, BEFORE the capture decision: a build whose app no
7922
7716
  * longer declares any prebuilt components must also shed the artifacts
7923
7717
  * (codex P2 on PR #836).
7924
7718
  */
@@ -7935,19 +7729,16 @@ async function cleanPrebuiltDir(buildDir) {
7935
7729
  * component). Per-entry data errors skip-and-report per design/44
7936
7730
  * §Build-Phase Error Handling.
7937
7731
  */
7938
- async function runPrebuiltCapture(ctx) {
7732
+ async function runPrebuiltCapture(ctx, rscDir) {
7939
7733
  const routeComponents = ctx.routePrebuiltComponents;
7940
- if (!routeComponents || routeComponents.size === 0) return {
7734
+ if (!routeComponents || routeComponents.size === 0) return { summary: {
7941
7735
  captured: 0,
7942
7736
  skipped: [],
7943
7737
  hardErrors: [],
7944
7738
  nestingWarnings: 0
7945
- };
7946
- const entryPath = join(ctx.buildDir, "rsc", "index.js");
7947
- if (!existsSync(entryPath)) throw new Error(`[timber] prebuilt capture: built RSC entry not found at ${entryPath} — the app declares cache.component({ prerender: true }) call sites but the RSC build output is missing`);
7739
+ } };
7740
+ const entryPath = join(rscDir, "index.js");
7948
7741
  const g = globalThis;
7949
- if (ctx.buildManifest) g.__TIMBER_BUILD_MANIFEST__ ??= ctx.buildManifest;
7950
- if (ctx.deploymentId) g.__TIMBER_DEPLOYMENT_ID__ ??= ctx.deploymentId;
7951
7742
  console.log("[timber] cache.component: capturing prebuilt flight payloads…");
7952
7743
  g.__TIMBER_CAPTURE_MODE__ = true;
7953
7744
  let mod;
@@ -7961,7 +7752,8 @@ async function runPrebuiltCapture(ctx) {
7961
7752
  }
7962
7753
  const capture = mod.__timber_capturePrebuilt;
7963
7754
  if (typeof capture !== "function") throw new Error("[timber] prebuilt capture: built RSC entry does not export __timber_capturePrebuilt — the build output predates this framework version; rebuild from a clean .timber/dist");
7964
- const writer = createPrebuiltArtifactWriter(join(ctx.buildDir, "prebuilt"));
7755
+ const prebuiltDir = join(ctx.buildDir, "prebuilt");
7756
+ const writer = createPrebuiltArtifactWriter(prebuiltDir);
7965
7757
  const summary = await capture({
7966
7758
  fileComponentMap: Object.fromEntries(routeComponents),
7967
7759
  callSiteProps: ctx.prebuiltCallSiteProps ? Object.fromEntries(ctx.prebuiltCallSiteProps) : void 0,
@@ -7972,10 +7764,13 @@ async function runPrebuiltCapture(ctx) {
7972
7764
  const details = summary.hardErrors.map((issue) => ` - ${issue.message}`).join("\n");
7973
7765
  throw new Error(`[timber] prebuilt capture failed: ${summary.hardErrors.length} component(s) read per-request context at build time:\n${details}`);
7974
7766
  }
7975
- await writer.finalize();
7767
+ const written = await writer.finalize();
7976
7768
  const total = summary.captured + summary.skipped.length;
7977
7769
  console.log(`[timber] Prebuilt ${summary.captured}/${total} entries.` + (summary.skipped.length > 0 ? ` ${summary.skipped.length} skipped due to errors.` : ""));
7978
- return summary;
7770
+ return written > 0 ? {
7771
+ summary,
7772
+ artifact: { path: prebuiltDir }
7773
+ } : { summary };
7979
7774
  }
7980
7775
  //#endregion
7981
7776
  //#region src/plugins/prebuilt.ts
@@ -8149,8 +7944,7 @@ function collectPageAndLayoutFiles(root) {
8149
7944
  return files;
8150
7945
  }
8151
7946
  var DEFAULT_SENTINEL = "\0default";
8152
- async function collectCrossModuleProps(ctx, moduleId, getInfo, resolve) {
8153
- const bindingNames = ctx.prebuiltBindingNames;
7947
+ async function collectCrossModuleProps(ctx, bindingNames, moduleId, getInfo, resolve) {
8154
7948
  const info = getInfo(moduleId);
8155
7949
  if (!info) return;
8156
7950
  const declaringImports = info.importedIds.filter((id) => bindingNames.has(id) && id !== moduleId);
@@ -8218,10 +8012,34 @@ async function collectCrossModuleProps(ctx, moduleId, getInfo, resolve) {
8218
8012
  }
8219
8013
  }
8220
8014
  function timberPrebuilt(ctx) {
8015
+ /**
8016
+ * Module ID → prerender-capable component IDs declared in it. Recorded by
8017
+ * the RSC transform, read by the RSC `generateBundle` module-graph walk
8018
+ * that computes `ctx.routePrebuiltComponents`. Build only.
8019
+ */
8020
+ const moduleComponents = /* @__PURE__ */ new Map();
8021
+ /**
8022
+ * Module ID → variable name → component ID, for the prebuilt components
8023
+ * that module declares. Read at `generateBundle` time to trace imports in
8024
+ * other modules back to component IDs (cross-module call-site props).
8025
+ */
8026
+ const bindingNames = /* @__PURE__ */ new Map();
8221
8027
  return {
8222
8028
  name: "timber-prebuilt",
8029
+ api: { async capture(rscDir) {
8030
+ await cleanPrebuiltDir(ctx.buildDir);
8031
+ if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return null;
8032
+ if (ctx.config.output === "static") {
8033
+ console.log(`[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`);
8034
+ return null;
8035
+ }
8036
+ return runPrebuiltCapture(ctx, rscDir);
8037
+ } },
8223
8038
  transform(code, id) {
8224
- if (!ctx.dev && this?.environment?.name === "rsc") ctx.prebuiltModuleComponents?.delete(id);
8039
+ if (!ctx.dev && this?.environment?.name === "rsc") {
8040
+ moduleComponents.delete(id);
8041
+ bindingNames.delete(id);
8042
+ }
8225
8043
  if (!code.includes("@timber-js/app/cache") && !code.includes("timber/cache")) return;
8226
8044
  if (id.includes("node_modules")) return;
8227
8045
  if (this?.environment?.name === "client") return;
@@ -8253,8 +8071,7 @@ function timberPrebuilt(ctx) {
8253
8071
  s.appendLeft(call.arguments[0].start, `${JSON.stringify(firstArg)}, `);
8254
8072
  }
8255
8073
  if (!ctx.dev && componentIds.length > 0 && this?.environment?.name === "rsc") {
8256
- ctx.prebuiltModuleComponents ??= /* @__PURE__ */ new Map();
8257
- ctx.prebuiltModuleComponents.set(id, componentIds);
8074
+ moduleComponents.set(id, componentIds);
8258
8075
  const bindingMap = /* @__PURE__ */ new Map();
8259
8076
  let componentIdIdx = 0;
8260
8077
  for (const { call, stmt, displayName } of callSites) if (!ctx.dev && mayPrerender(call)) {
@@ -8274,10 +8091,7 @@ function timberPrebuilt(ctx) {
8274
8091
  }
8275
8092
  }
8276
8093
  }
8277
- if (bindingMap.size > 0) {
8278
- ctx.prebuiltBindingNames ??= /* @__PURE__ */ new Map();
8279
- ctx.prebuiltBindingNames.set(id, bindingMap);
8280
- }
8094
+ if (bindingMap.size > 0) bindingNames.set(id, bindingMap);
8281
8095
  const declaredBindings = new Set([...bindingMap.keys()].filter((k) => k !== DEFAULT_SENTINEL));
8282
8096
  if (declaredBindings.size > 0) {
8283
8097
  const usages = collectJsxUsages(program, declaredBindings);
@@ -8308,8 +8122,8 @@ function timberPrebuilt(ctx) {
8308
8122
  if (ctx.dev) return;
8309
8123
  if (this?.environment?.name !== "rsc") return;
8310
8124
  ctx.routePrebuiltComponents = void 0;
8311
- const moduleComponents = ctx.prebuiltModuleComponents;
8312
- if (!moduleComponents || moduleComponents.size === 0 || !ctx.routeTree) return;
8125
+ ctx.prebuiltLazyChunks = void 0;
8126
+ if (moduleComponents.size === 0 || !ctx.routeTree) return;
8313
8127
  const self = this;
8314
8128
  const getInfo = (id) => self.getModuleInfo?.(id) ?? null;
8315
8129
  const resolveFn = async (source, importer) => {
@@ -8337,7 +8151,7 @@ function timberPrebuilt(ctx) {
8337
8151
  }
8338
8152
  if (lazyChunks.size > 0) ctx.prebuiltLazyChunks = lazyChunks;
8339
8153
  }
8340
- if (ctx.prebuiltBindingNames && ctx.prebuiltBindingNames.size > 0) {
8154
+ if (bindingNames.size > 0) {
8341
8155
  const scannedModules = /* @__PURE__ */ new Set();
8342
8156
  for (const filePath of routeComponents.keys()) {
8343
8157
  const visited = /* @__PURE__ */ new Set();
@@ -8348,7 +8162,7 @@ function timberPrebuilt(ctx) {
8348
8162
  visited.add(modId);
8349
8163
  if (!scannedModules.has(modId)) {
8350
8164
  scannedModules.add(modId);
8351
- await collectCrossModuleProps(ctx, modId, getInfo, resolveFn);
8165
+ await collectCrossModuleProps(ctx, bindingNames, modId, getInfo, resolveFn);
8352
8166
  }
8353
8167
  const modInfo = getInfo(modId);
8354
8168
  if (!modInfo) continue;
@@ -8358,26 +8172,6 @@ function timberPrebuilt(ctx) {
8358
8172
  }
8359
8173
  }
8360
8174
  } else console.warn(`[timber] cache.component: ${moduleComponents.size} module(s) declare prebuilt components, but none are reachable from any page or layout — no payloads will be prerendered`);
8361
- },
8362
- /**
8363
- * Post-build capture (design/44 §Build Phase). `order: 'post'` runs
8364
- * after the RSC plugin's buildApp — all five build steps are complete —
8365
- * and BEFORE timber-adapter-build's post hook (plugin array order), so
8366
- * `prebuilt/` exists when the adapter assembles its output (TIM-1122).
8367
- */
8368
- buildApp: {
8369
- order: "post",
8370
- async handler() {
8371
- if (ctx.dev) return;
8372
- ctx.captureSummary = void 0;
8373
- await cleanPrebuiltDir(ctx.buildDir);
8374
- if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return;
8375
- if (ctx.config.output === "static") {
8376
- console.log(`[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`);
8377
- return;
8378
- }
8379
- ctx.captureSummary = await runPrebuiltCapture(ctx);
8380
- }
8381
8175
  }
8382
8176
  };
8383
8177
  }
@@ -8530,8 +8324,6 @@ function timberPrerenderSugar(ctx) {
8530
8324
  if (defaultExport.kind === "expression" && defaultExport.node.declaration) {
8531
8325
  if (code.slice(defaultExport.node.declaration.start, defaultExport.node.declaration.end).includes(".component(")) return;
8532
8326
  }
8533
- ctx.prerenderSugarPages ??= /* @__PURE__ */ new Set();
8534
- ctx.prerenderSugarPages.add(id);
8535
8327
  const s = new MagicString(code);
8536
8328
  const optionsSource = buildOptionsSource(value);
8537
8329
  const importAlias = "__timber_prerender_cache__";
@@ -8668,6 +8460,378 @@ function timberCloudflareWasm(ctx) {
8668
8460
  }];
8669
8461
  }
8670
8462
  //#endregion
8463
+ //#region src/plugins/rsc-assets-manifest.ts
8464
+ /**
8465
+ * The RSC plugin's assets manifest (`__vite_rsc_assets_manifest.js`) — read
8466
+ * into the build manifest, and stripped of JavaScript when client JS is off.
8467
+ *
8468
+ * The RSC plugin writes the file to rsc/ and ssr/ as a standalone file, not
8469
+ * a Rollup chunk, so no `generateBundle` can intercept it; both operations
8470
+ * work on the written files. Both run once, from the post-build phase's
8471
+ * manifest finalization step (plugins/post-build.ts), before anything
8472
+ * imports the built bundle.
8473
+ *
8474
+ * Design doc: 18-build-system.md §"Post-Build Phase"
8475
+ */
8476
+ /**
8477
+ * Parse the RSC assets manifest at `manifestPath`. Tries JSON.parse first
8478
+ * (fast path for plain-string manifests); falls back to a dynamic import()
8479
+ * for manifests that contain runtime expressions from renderBuiltUrl.
8480
+ * Returns null if both paths fail.
8481
+ */
8482
+ async function parseRscManifest(manifestPath, content) {
8483
+ const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
8484
+ try {
8485
+ return JSON.parse(jsonStr);
8486
+ } catch {}
8487
+ try {
8488
+ return (await import(`${pathToFileURL(manifestPath).href}?t=${Date.now()}`)).default ?? null;
8489
+ } catch (err) {
8490
+ swallow(err, `failed to evaluate RSC assets manifest: ${manifestPath}`, { level: "warn" });
8491
+ return null;
8492
+ }
8493
+ }
8494
+ /**
8495
+ * Replace all `"js": [...]` array contents with `"js": []` using balanced
8496
+ * bracket matching. Handles nested brackets from runtime expressions like
8497
+ * `__rbu("path/to/[slug]/file.js")`.
8498
+ */
8499
+ function clearJsArrays(src) {
8500
+ const pattern = /"js"\s*:\s*\[/g;
8501
+ let result = "";
8502
+ let lastEnd = 0;
8503
+ let match;
8504
+ while ((match = pattern.exec(src)) !== null) {
8505
+ const arrayStart = match.index + match[0].length;
8506
+ let depth = 1;
8507
+ let i = arrayStart;
8508
+ while (i < src.length && depth > 0) {
8509
+ if (src[i] === "[") depth++;
8510
+ else if (src[i] === "]") depth--;
8511
+ i++;
8512
+ }
8513
+ result += src.slice(lastEnd, match.index) + "\"js\": []";
8514
+ lastEnd = i;
8515
+ }
8516
+ result += src.slice(lastEnd);
8517
+ return result;
8518
+ }
8519
+ /**
8520
+ * Replace `"bootstrapScriptContent": <value>` with an empty string. The
8521
+ * value may be a JS expression (e.g., concatenation with runtime helpers),
8522
+ * not a simple string literal. Scans forward from the colon, tracking
8523
+ * balanced parens and brackets, and stops at the next unbalanced `,` or `}`.
8524
+ */
8525
+ function clearBootstrapScriptContent(src) {
8526
+ const idx = src.indexOf("\"bootstrapScriptContent\"");
8527
+ if (idx === -1) return src;
8528
+ const colonIdx = src.indexOf(":", idx + 24);
8529
+ if (colonIdx === -1) return src;
8530
+ let valStart = colonIdx + 1;
8531
+ while (valStart < src.length && /\s/.test(src[valStart])) valStart++;
8532
+ let i = valStart;
8533
+ let depth = 0;
8534
+ let inString = false;
8535
+ let stringChar = "";
8536
+ while (i < src.length) {
8537
+ const ch = src[i];
8538
+ if (inString) {
8539
+ if (ch === "\\") {
8540
+ i += 2;
8541
+ continue;
8542
+ }
8543
+ if (ch === stringChar) inString = false;
8544
+ } else if (ch === "\"" || ch === "'") {
8545
+ inString = true;
8546
+ stringChar = ch;
8547
+ } else if (ch === "(" || ch === "[") depth++;
8548
+ else if (ch === ")" || ch === "]") depth--;
8549
+ else if (depth === 0 && (ch === "," || ch === "}" || ch === "\n")) break;
8550
+ i++;
8551
+ }
8552
+ return src.slice(0, idx) + "\"bootstrapScriptContent\": \"\"" + src.slice(i);
8553
+ }
8554
+ /**
8555
+ * Read the RSC plugin's assets manifest and merge per-route CSS and
8556
+ * per-route JS modulepreloads into the build manifest.
8557
+ *
8558
+ * CSS: `serverResources` maps server component paths to CSS URLs.
8559
+ * JS: `clientReferenceDeps` maps reference hashes to JS dep URLs.
8560
+ * Combined with `routeClientRefKeys` (from the RSC generateBundle
8561
+ * module graph walk) to produce per-route modulepreload entries.
8562
+ */
8563
+ async function mergeRscAssetsManifest(rscDir, root, buildManifest, routeClientRefKeys) {
8564
+ const manifestPath = join(rscDir, "__vite_rsc_assets_manifest.js");
8565
+ let content;
8566
+ try {
8567
+ content = await readFile(manifestPath, "utf-8");
8568
+ } catch {
8569
+ return;
8570
+ }
8571
+ const manifest = await parseRscManifest(manifestPath, content);
8572
+ if (!manifest) return;
8573
+ const serverResources = manifest.serverResources;
8574
+ if (serverResources) {
8575
+ for (const [relativePath, deps] of Object.entries(serverResources)) if (deps.css && deps.css.length > 0) {
8576
+ const absolutePath = join(root, relativePath);
8577
+ buildManifest.css[absolutePath] = deps.css;
8578
+ }
8579
+ }
8580
+ if (routeClientRefKeys && routeClientRefKeys.size > 0) {
8581
+ const clientReferenceDeps = manifest.clientReferenceDeps;
8582
+ if (clientReferenceDeps) for (const [filePath, refKeys] of routeClientRefKeys) {
8583
+ const jsUrls = /* @__PURE__ */ new Set();
8584
+ for (const key of refKeys) {
8585
+ const deps = clientReferenceDeps[key];
8586
+ if (deps?.js) for (const url of deps.js) jsUrls.add(url);
8587
+ }
8588
+ if (jsUrls.size > 0) buildManifest.modulepreload[filePath] = Array.from(jsUrls);
8589
+ }
8590
+ }
8591
+ }
8592
+ /**
8593
+ * Strip JS references from the RSC plugin's assets manifest files.
8594
+ *
8595
+ * The RSC plugin writes `__vite_rsc_assets_manifest.js` to rsc/ and ssr/
8596
+ * as standalone files (not Rollup chunks), so generateBundle can't
8597
+ * intercept them. This rewrites the files on disk after all builds
8598
+ * complete but before the adapter copies them to the output directory.
8599
+ */
8600
+ async function stripJsFromRscAssetsManifests(serverDirs) {
8601
+ const paths = serverDirs.map((dir) => join(dir, "__vite_rsc_assets_manifest.js"));
8602
+ for (const path of paths) {
8603
+ let content;
8604
+ try {
8605
+ content = await readFile(path, "utf-8");
8606
+ } catch {
8607
+ continue;
8608
+ }
8609
+ const jsonStr = content.replace(/^export default\s*/, "").replace(/;?\s*$/, "");
8610
+ let isStrictJson = true;
8611
+ let manifest = null;
8612
+ try {
8613
+ manifest = JSON.parse(jsonStr);
8614
+ } catch {
8615
+ isStrictJson = false;
8616
+ }
8617
+ if (!isStrictJson) {
8618
+ let rewritten = content;
8619
+ rewritten = clearJsArrays(rewritten);
8620
+ rewritten = clearBootstrapScriptContent(rewritten);
8621
+ await writeFile(path, rewritten);
8622
+ continue;
8623
+ }
8624
+ const deps = manifest?.clientReferenceDeps;
8625
+ if (deps) for (const entry of Object.values(deps)) entry.js = [];
8626
+ if (manifest) manifest.bootstrapScriptContent = "";
8627
+ await writeFile(path, `export default ${JSON.stringify(manifest, null, 2)};\n`);
8628
+ }
8629
+ }
8630
+ //#endregion
8631
+ //#region src/plugins/post-build.ts
8632
+ /** The Vite environments whose output adapters consume. */
8633
+ var ARTIFACT_ENVIRONMENTS = [
8634
+ "client",
8635
+ "rsc",
8636
+ "ssr"
8637
+ ];
8638
+ function isArtifactEnvironment(name) {
8639
+ return ARTIFACT_ENVIRONMENTS.includes(name);
8640
+ }
8641
+ function timberPostBuild(ctx, steps) {
8642
+ const environments = {};
8643
+ /** What the client environment's bundle wrote, from its `writeBundle`. */
8644
+ let clientOutput = {
8645
+ assetsDir: "",
8646
+ emitted: /* @__PURE__ */ new Set()
8647
+ };
8648
+ return {
8649
+ name: "timber-post-build",
8650
+ writeBundle(options, bundle) {
8651
+ if (ctx.dev) return;
8652
+ const env = this.environment;
8653
+ if (!isArtifactEnvironment(env.name)) return;
8654
+ environments[env.name] = { path: resolve(env.config.root, env.config.build.outDir) };
8655
+ if (env.name === "client") clientOutput = {
8656
+ assetsDir: hashedAssetsDir(env.config.build.assetsDir, options),
8657
+ emitted: new Set(Object.keys(bundle))
8658
+ };
8659
+ },
8660
+ buildApp: {
8661
+ order: "post",
8662
+ async handler() {
8663
+ if (ctx.dev) return;
8664
+ await runPostBuild(ctx, steps, environments, clientOutput);
8665
+ }
8666
+ }
8667
+ };
8668
+ }
8669
+ /**
8670
+ * The client bundle's assets directory, in the artifacts' form (no leading
8671
+ * or trailing slash) — or `''` when its files are not all content-hashed.
8672
+ *
8673
+ * `assetsDir` names where Vite writes; it is the naming patterns that decide
8674
+ * whether a file name carries a hash. Vite's defaults do
8675
+ * (`<assetsDir>/[name]-[hash].js`), but an app can set
8676
+ * `assetFileNames: 'static/[name][extname]'`, and marking that directory
8677
+ * immutable would pin a changed image under an unchanged URL for a year. A
8678
+ * pattern given as a function cannot be inspected, so it counts as unhashed:
8679
+ * those files fall back to the revalidating per-file rule.
8680
+ *
8681
+ * @internal Exported for testing.
8682
+ */
8683
+ function hashedAssetsDir(assetsDir, output) {
8684
+ const dir = assetsDir.replace(/^\/+|\/+$/g, "");
8685
+ return [
8686
+ output.entryFileNames,
8687
+ output.chunkFileNames,
8688
+ output.assetFileNames
8689
+ ].every((p) => typeof p === "string" && p.includes("[hash")) ? dir : "";
8690
+ }
8691
+ /**
8692
+ * Keep only the directories whose every file the client bundle emitted.
8693
+ *
8694
+ * A producer knows it hashes what *it* writes, not what else lands beside it:
8695
+ * Vite copies `public/` into the client output verbatim, so `public/assets/logo.png`
8696
+ * sits in `assets/` under a stable name, and `public/_rsc/…` would sit among
8697
+ * the hashed payloads. A directory holding any file the bundle did not emit
8698
+ * is not content-hashed as a whole, and marking it immutable would pin that
8699
+ * file for a year — so it is dropped, and its files take the per-file rule.
8700
+ *
8701
+ * @internal Exported for testing.
8702
+ */
8703
+ async function onlyEmittedDirs(clientDir, dirs, emitted) {
8704
+ const kept = [];
8705
+ for (const dir of dirs) {
8706
+ const root = join(clientDir, dir);
8707
+ if (!(await readdir(root, {
8708
+ recursive: true,
8709
+ withFileTypes: true
8710
+ }).catch(() => [])).some((entry) => entry.isFile() && !emitted.has(relative(clientDir, join(entry.parentPath, entry.name)).replace(/\\/g, "/")))) kept.push(dir);
8711
+ }
8712
+ return kept;
8713
+ }
8714
+ async function runPostBuild(ctx, steps, environments, clientOutput) {
8715
+ const output = ctx.config.output ?? "server";
8716
+ const rsc = requireEnvironment(environments, "rsc");
8717
+ const ssr = requireEnvironment(environments, "ssr");
8718
+ const manifest = await finalizeBuildManifest(ctx, steps.fonts, rsc, ssr);
8719
+ if (manifest) Reflect.set(globalThis, "__TIMBER_BUILD_MANIFEST__", manifest);
8720
+ const prebuilt = await steps.prebuilt.capture(rsc.path);
8721
+ const site = output === "static" ? await runStaticGeneration(ctx, rsc.path) : void 0;
8722
+ steps.report.print(prebuilt);
8723
+ const adapter = contextAdapter(ctx);
8724
+ if (!adapter || typeof adapter.buildOutput !== "function") return;
8725
+ await adapter.buildOutput(adapterConfig(ctx), assembleBuildArtifacts({
8726
+ output,
8727
+ outputDir: ctx.buildDir,
8728
+ environments,
8729
+ immutableDirs: await onlyEmittedDirs(requireEnvironment(environments, "client").path, [
8730
+ ...clientOutput.assetsDir ? [clientOutput.assetsDir] : [],
8731
+ ...steps.fonts.immutableDirs(),
8732
+ ...site?.immutableDirs ?? []
8733
+ ], clientOutput.emitted),
8734
+ prebuilt: prebuilt?.artifact,
8735
+ site,
8736
+ manifestInit: manifest ? serializeManifestInit(manifest) : void 0
8737
+ }));
8738
+ }
8739
+ function requireEnvironment(environments, name) {
8740
+ const artifact = environments[name];
8741
+ if (!artifact) throw new Error(`[timber] Build output: the ${name} environment wrote no bundle`);
8742
+ return artifact;
8743
+ }
8744
+ /**
8745
+ * Step 1: bring the build manifest to its final shape, once.
8746
+ *
8747
+ * `timber-build-manifest` creates it from the client bundle; this adds what
8748
+ * only exists once every environment is built — the font entries and the
8749
+ * per-route CSS and modulepreloads in the RSC plugin's assets manifest —
8750
+ * and then, when client JavaScript is disabled, removes every JavaScript
8751
+ * reference, from the manifest and from the assets manifests on disk. The
8752
+ * manifest's `js` / `modulepreload` are cleared after the merge has written
8753
+ * into them, so nothing the merge adds survives.
8754
+ *
8755
+ * Returns null only when no client bundle produced a manifest.
8756
+ *
8757
+ * @internal Exported for testing.
8758
+ */
8759
+ async function finalizeBuildManifest(ctx, fonts, rsc, ssr) {
8760
+ const manifest = ctx.buildManifest;
8761
+ if (manifest) {
8762
+ fonts.contributeManifest(manifest);
8763
+ await mergeRscAssetsManifest(rsc.path, ctx.root, manifest, ctx.routeClientRefKeys);
8764
+ }
8765
+ if (ctx.clientJavascript.disabled) {
8766
+ if (manifest) {
8767
+ manifest.js = {};
8768
+ manifest.modulepreload = {};
8769
+ }
8770
+ await stripJsFromRscAssetsManifests([rsc.path, ssr.path]);
8771
+ }
8772
+ return manifest;
8773
+ }
8774
+ /**
8775
+ * The build manifest as a JS module that sets the global. Adapters write
8776
+ * it as `_timber-manifest-init.js` (or prepend it to the entry) and
8777
+ * evaluate it before the RSC handler, so `virtual:timber-build-manifest`
8778
+ * finds it.
8779
+ */
8780
+ function serializeManifestInit(manifest) {
8781
+ return `globalThis.__TIMBER_BUILD_MANIFEST__ = ${JSON.stringify(manifest)};\n`;
8782
+ }
8783
+ /**
8784
+ * Dedupe the producers' directories and drop any that sits inside another.
8785
+ *
8786
+ * Two producers can name overlapping directories — a custom `assetsDir` of
8787
+ * `_timber` beside the fonts' `_timber/fonts`. Cloudflare and Netlify apply
8788
+ * every matching `_headers` rule, so emitting both would send two
8789
+ * `Cache-Control` values for one file; the outer directory already covers
8790
+ * the inner one.
8791
+ */
8792
+ function canonicalImmutableDirs(dirs) {
8793
+ const unique = [...new Set(dirs)];
8794
+ return unique.filter((dir) => !unique.some((other) => other !== dir && dir.startsWith(`${other}/`)));
8795
+ }
8796
+ /**
8797
+ * Assemble the adapter's view of the build from what each step returned.
8798
+ *
8799
+ * Not a validator: every field is copied from the phase that produced it.
8800
+ * The throws are the states the union cannot represent — a Vite environment
8801
+ * that wrote no bundle, a static build with no site. Each means an earlier
8802
+ * phase failed without failing the build, and a deploy missing its SSR
8803
+ * bundle fails on the first request rather than here.
8804
+ *
8805
+ * @internal Exported for testing.
8806
+ */
8807
+ function assembleBuildArtifacts(input) {
8808
+ const { output, outputDir, environments } = input;
8809
+ const client = requireEnvironment(environments, "client");
8810
+ const immutableDirs = canonicalImmutableDirs(input.immutableDirs);
8811
+ if (output === "static") {
8812
+ if (!input.site) throw new Error("[timber] Build output: output is 'static' but static generation recorded no site");
8813
+ const { pages, contentTypes } = input.site;
8814
+ return {
8815
+ output,
8816
+ outputDir,
8817
+ client,
8818
+ immutableDirs,
8819
+ pages,
8820
+ contentTypes
8821
+ };
8822
+ }
8823
+ return {
8824
+ output,
8825
+ outputDir,
8826
+ client,
8827
+ immutableDirs,
8828
+ rsc: requireEnvironment(environments, "rsc"),
8829
+ ssr: requireEnvironment(environments, "ssr"),
8830
+ prebuilt: input.prebuilt,
8831
+ manifestInit: input.manifestInit
8832
+ };
8833
+ }
8834
+ //#endregion
8671
8835
  //#region src/plugins/build-report.ts
8672
8836
  /**
8673
8837
  * timber-build-report — Post-build route summary table.
@@ -8771,13 +8935,10 @@ function pad(str, width, align = "right") {
8771
8935
  function stripAnsi(str) {
8772
8936
  return str.replace(/\u001b\[\d+m/g, "");
8773
8937
  }
8774
- function loadPrebuiltManifest(buildDir) {
8775
- try {
8776
- const raw = readFileSync(join(buildDir, "prebuilt", "manifest.json"), "utf-8");
8777
- return JSON.parse(raw);
8778
- } catch {
8779
- return null;
8780
- }
8938
+ /** Read the manifest of the prebuilt artifact this build recorded, if any. */
8939
+ function loadPrebuiltManifest(prebuiltDir) {
8940
+ if (!prebuiltDir) return null;
8941
+ return JSON.parse(readFileSync(join(prebuiltDir, "manifest.json"), "utf-8"));
8781
8942
  }
8782
8943
  function buildPrebuiltReportData(manifest, summary) {
8783
8944
  const hasCaptures = summary && (summary.captured > 0 || summary.skipped.length > 0);
@@ -8981,11 +9142,47 @@ function timberBuildReport(ctx) {
8981
9142
  let logger = null;
8982
9143
  let chunkSizes = null;
8983
9144
  let clientBundle = null;
8984
- let reported = false;
8985
- let deferReport = false;
8986
9145
  const buildStart = performance.now();
9146
+ function printRouteTable() {
9147
+ if (!ctx.routeTree || !chunkSizes || !clientBundle || !logger) return;
9148
+ const outputMode = ctx.config.output ?? "server";
9149
+ const { entries, sharedGzip } = ctx.clientJavascript.disabled ? {
9150
+ entries: collectRoutes(ctx.routeTree).map((info) => ({
9151
+ path: info.path,
9152
+ type: classifyRoute(info.segments, outputMode),
9153
+ size: 0,
9154
+ firstLoadSize: 0
9155
+ })),
9156
+ sharedGzip: 0
9157
+ } : buildEntries(ctx.routeTree, chunkSizes, clientBundle, outputMode, ctx.appDir, ctx.root);
9158
+ const elapsed = ((performance.now() - buildStart) / 1e3).toFixed(2);
9159
+ const lines = buildRouteReport(entries, sharedGzip);
9160
+ logger.info("");
9161
+ for (const line of lines) logger.info(line);
9162
+ const warnings = buildWarnings(entries, ctx.config.budget);
9163
+ if (warnings.length > 0) {
9164
+ logger.info("");
9165
+ for (const w of warnings) logger.warn(w);
9166
+ }
9167
+ logger.info("");
9168
+ logger.info(`✓ built ${entries.length} routes for all three environments (rsc, ssr, client) in ${elapsed}s`);
9169
+ logger.info("");
9170
+ }
9171
+ function printPrebuiltReport(prebuilt) {
9172
+ if (!logger || !prebuilt) return;
9173
+ const prebuiltData = buildPrebuiltReportData(loadPrebuiltManifest(prebuilt.artifact?.path), prebuilt.summary);
9174
+ if (!prebuiltData) return;
9175
+ logger.info("");
9176
+ for (const line of buildPrebuiltReport(prebuiltData)) logger.info(line);
9177
+ logger.info("");
9178
+ }
8987
9179
  return {
8988
9180
  name: "timber-build-report",
9181
+ api: { print(prebuilt) {
9182
+ if (ctx.dev) return;
9183
+ printRouteTable();
9184
+ printPrebuiltReport(prebuilt);
9185
+ } },
8989
9186
  config(_cfg, { command }) {
8990
9187
  if (command !== "build") return;
8991
9188
  return { environments: {
@@ -9002,50 +9199,6 @@ function timberBuildReport(ctx) {
9002
9199
  if (this.environment?.name && this.environment.name !== "client") return;
9003
9200
  chunkSizes = collectChunkSizes(bundle);
9004
9201
  clientBundle = { ...bundle };
9005
- deferReport = true;
9006
- },
9007
- closeBundle() {
9008
- if (ctx.dev || reported) return;
9009
- if (deferReport) {
9010
- deferReport = false;
9011
- return;
9012
- }
9013
- if (!ctx.routeTree || !chunkSizes || !clientBundle || !logger) return;
9014
- reported = true;
9015
- const outputMode = ctx.config.output ?? "server";
9016
- const { entries, sharedGzip } = ctx.clientJavascript.disabled ? {
9017
- entries: collectRoutes(ctx.routeTree).map((info) => ({
9018
- path: info.path,
9019
- type: classifyRoute(info.segments, outputMode),
9020
- size: 0,
9021
- firstLoadSize: 0
9022
- })),
9023
- sharedGzip: 0
9024
- } : buildEntries(ctx.routeTree, chunkSizes, clientBundle, outputMode, ctx.appDir, ctx.root);
9025
- const elapsed = ((performance.now() - buildStart) / 1e3).toFixed(2);
9026
- const lines = buildRouteReport(entries, sharedGzip);
9027
- logger.info("");
9028
- for (const line of lines) logger.info(line);
9029
- const warnings = buildWarnings(entries, ctx.config.budget);
9030
- if (warnings.length > 0) {
9031
- logger.info("");
9032
- for (const w of warnings) logger.warn(w);
9033
- }
9034
- logger.info("");
9035
- logger.info(`✓ built ${entries.length} routes for all three environments (rsc, ssr, client) in ${elapsed}s`);
9036
- logger.info("");
9037
- },
9038
- buildApp: {
9039
- order: "post",
9040
- async handler() {
9041
- if (ctx.dev || !logger) return;
9042
- const prebuiltData = buildPrebuiltReportData(loadPrebuiltManifest(ctx.buildDir), ctx.captureSummary);
9043
- if (!prebuiltData) return;
9044
- logger.info("");
9045
- const prebuiltLines = buildPrebuiltReport(prebuiltData);
9046
- for (const line of prebuiltLines) logger.info(line);
9047
- logger.info("");
9048
- }
9049
9202
  }
9050
9203
  };
9051
9204
  }
@@ -9387,10 +9540,8 @@ function timber(config) {
9387
9540
  }
9388
9541
  ctx.config.output ??= "server";
9389
9542
  ctx.timer.end("config-load");
9390
- const viteOutDir = userConfig.build?.outDir;
9391
- const timberBuildDir = ctx.config.buildDir;
9392
9543
  const resolvedRoot = resolve(userConfig.root ?? process.cwd());
9393
- ctx.buildDir = resolveBuildDir(resolvedRoot, timberBuildDir, viteOutDir);
9544
+ const buildDir = resolveBuildDir(resolvedRoot, ctx.config.buildDir, userConfig.build?.outDir);
9394
9545
  if (viteRoot !== process.cwd()) {
9395
9546
  const hasCompilerInReloaded = !config?.reactCompiler && ctx.config.reactCompiler;
9396
9547
  const hadCompilerInEarly = !config?.reactCompiler && earlyFileConfig?.reactCompiler;
@@ -9421,7 +9572,7 @@ function timber(config) {
9421
9572
  resolvedDevPort = start.port;
9422
9573
  resolvedDevPortExplicit = start.explicit;
9423
9574
  }
9424
- const buildOutDir = relative(resolvedRoot, ctx.buildDir);
9575
+ const buildOutDir = relative(resolvedRoot, buildDir);
9425
9576
  const envOutDirs = {};
9426
9577
  for (const envName of [
9427
9578
  "rsc",
@@ -9485,6 +9636,9 @@ function timber(config) {
9485
9636
  };
9486
9637
  const effectiveReactCompiler = config?.reactCompiler ?? earlyFileConfig?.reactCompiler ?? true;
9487
9638
  // @vitejs/plugin-rsc handles:
9639
+ const fonts = timberFonts(ctx);
9640
+ const prebuilt = timberPrebuilt(ctx);
9641
+ const buildReport = timberBuildReport(ctx);
9488
9642
  return [
9489
9643
  rootSync,
9490
9644
  timberReactResolve(),
@@ -9495,19 +9649,23 @@ function timber(config) {
9495
9649
  timberRouting(ctx),
9496
9650
  timberEntries(ctx),
9497
9651
  timberBuildManifest(ctx),
9498
- timberFonts(ctx),
9652
+ fonts,
9499
9653
  timberMdx(ctx),
9500
9654
  timberRequestDep(ctx),
9501
9655
  timberCacheTransform(ctx),
9502
9656
  timberPrerenderSugar(ctx),
9503
- timberPrebuilt(ctx),
9657
+ prebuilt,
9504
9658
  timberStaticBuild(ctx),
9505
9659
  timberContent(ctx),
9506
9660
  timberServerBundle(),
9507
9661
  timberCloudflareWasm(ctx),
9508
9662
  timberChunks(ctx),
9509
- timberBuildReport(ctx),
9510
- timberAdapterBuild(ctx),
9663
+ buildReport,
9664
+ timberPostBuild(ctx, {
9665
+ fonts: fonts.api,
9666
+ prebuilt: prebuilt.api,
9667
+ report: buildReport.api
9668
+ }),
9511
9669
  timberDevLogs(ctx),
9512
9670
  timberDevServer(ctx)
9513
9671
  ];