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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (526) hide show
  1. package/dist/_chunks/{primitives-DLAnvsrk.js → actions-BerlqoXA.js} +640 -410
  2. package/dist/_chunks/actions-BerlqoXA.js.map +1 -0
  3. package/dist/_chunks/{als-registry-C6kcfprT.js → als-registry-DaxkVjt5.js} +6 -2
  4. package/dist/_chunks/als-registry-DaxkVjt5.js.map +1 -0
  5. package/dist/_chunks/{build-manifest-DTmSGLRz.js → build-manifest-DWppEdLB.js} +2 -51
  6. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  7. package/dist/_chunks/{build-output-helper-9dqCv1pZ.js → build-output-helper-RV_BRcF1.js} +50 -53
  8. package/dist/_chunks/build-output-helper-RV_BRcF1.js.map +1 -0
  9. package/dist/_chunks/{cache-api-CUD9Ezaq.js → cache-api-CR23J_NC.js} +64 -32
  10. package/dist/_chunks/cache-api-CR23J_NC.js.map +1 -0
  11. package/dist/_chunks/{chains-B4bgOl2g.js → chains-CpFg56UB.js} +2 -2
  12. package/dist/_chunks/{chains-B4bgOl2g.js.map → chains-CpFg56UB.js.map} +1 -1
  13. package/dist/_chunks/{cli-check-G8o30ldg.js → cli-check-C6Ev6wBO.js} +11 -52
  14. package/dist/_chunks/cli-check-C6Ev6wBO.js.map +1 -0
  15. package/dist/_chunks/cli-context-By7k2xVo.js +70 -0
  16. package/dist/_chunks/cli-context-By7k2xVo.js.map +1 -0
  17. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js → cli-schema-sync-CbT2AUUI.js} +3 -3
  18. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js.map → cli-schema-sync-CbT2AUUI.js.map} +1 -1
  19. package/dist/_chunks/{cloudflare-BFb__LYG.js → cloudflare-Byxl8FWP.js} +96 -53
  20. package/dist/_chunks/{cloudflare-BFb__LYG.js.map → cloudflare-Byxl8FWP.js.map} +1 -1
  21. package/dist/_chunks/{convention-lint-5KzoMg_A.js → convention-lint-jKTwKwPe.js} +21 -6
  22. package/dist/_chunks/convention-lint-jKTwKwPe.js.map +1 -0
  23. package/dist/_chunks/{dev-server-BzBxgYAV.js → dev-server-C4WZdB7L.js} +15 -167
  24. package/dist/_chunks/dev-server-C4WZdB7L.js.map +1 -0
  25. package/dist/_chunks/{error-boundary-BndF-3Td.js → error-boundary-tA7kVfs4.js} +84 -104
  26. package/dist/_chunks/error-boundary-tA7kVfs4.js.map +1 -0
  27. package/dist/_chunks/{fs-identity-D7vb6GdI.js → fs-identity-BRKuL215.js} +3 -4
  28. package/dist/_chunks/fs-identity-BRKuL215.js.map +1 -0
  29. package/dist/_chunks/{graph-cache-CP4GEmf9.js → graph-cache-CYiUS2aS.js} +4 -5
  30. package/dist/_chunks/graph-cache-CYiUS2aS.js.map +1 -0
  31. package/dist/_chunks/{json-lossy-check-ClNvBM_3.js → json-lossy-check-ip0Qi0MT.js} +6 -3
  32. package/dist/_chunks/json-lossy-check-ip0Qi0MT.js.map +1 -0
  33. package/dist/_chunks/{live-graph-Bm5WTvcr.js → live-graph-Dv-JJCZw.js} +3 -3
  34. package/dist/_chunks/{live-graph-Bm5WTvcr.js.map → live-graph-Dv-JJCZw.js.map} +1 -1
  35. package/dist/_chunks/{logger-k2DQ4EUf.js → logger-DiDt5ppH.js} +192 -51
  36. package/dist/_chunks/logger-DiDt5ppH.js.map +1 -0
  37. package/dist/_chunks/{navigation-root-mHSK9psY.js → navigation-root-BQfo1-kG.js} +2 -2
  38. package/dist/_chunks/{navigation-root-mHSK9psY.js.map → navigation-root-BQfo1-kG.js.map} +1 -1
  39. package/dist/_chunks/{plugin-context-8idfR3UZ.js → plugin-context-BPBPc3lL.js} +28 -4
  40. package/dist/_chunks/plugin-context-BPBPc3lL.js.map +1 -0
  41. package/dist/_chunks/{poison-scan-DG5eI2_z.js → poison-scan-CpeT6_OJ.js} +2 -2
  42. package/dist/_chunks/{poison-scan-DG5eI2_z.js.map → poison-scan-CpeT6_OJ.js.map} +1 -1
  43. package/dist/_chunks/render-timeout-DOf_BBcO.js +46 -0
  44. package/dist/_chunks/render-timeout-DOf_BBcO.js.map +1 -0
  45. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js → rsc-payload-path-dffcs4jp.js} +9 -3
  46. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js.map → rsc-payload-path-dffcs4jp.js.map} +1 -1
  47. package/dist/_chunks/{scanner-BQ5sPIJ7.js → scanner-Bw0oq1HB.js} +2 -2
  48. package/dist/_chunks/{scanner-BQ5sPIJ7.js.map → scanner-Bw0oq1HB.js.map} +1 -1
  49. package/dist/_chunks/{navigation-context-D0TU0Jog.js → segment-context-xtPUGfdq.js} +36 -34
  50. package/dist/_chunks/segment-context-xtPUGfdq.js.map +1 -0
  51. package/dist/_chunks/{singleflight-2lUWfcAk.js → singleflight-BeVMMKi0.js} +4 -3
  52. package/dist/_chunks/{singleflight-2lUWfcAk.js.map → singleflight-BeVMMKi0.js.map} +1 -1
  53. package/dist/_chunks/{sizeof-lXffQ1Vr.js → sizeof-UwzwB1uM.js} +3 -2
  54. package/dist/_chunks/sizeof-UwzwB1uM.js.map +1 -0
  55. package/dist/_chunks/ssr-data-nA3I70_n.js +49 -0
  56. package/dist/_chunks/ssr-data-nA3I70_n.js.map +1 -0
  57. package/dist/_chunks/{state-FippDgxN.js → state-BhNGPsdi.js} +6 -8
  58. package/dist/_chunks/state-BhNGPsdi.js.map +1 -0
  59. package/dist/_chunks/{status-page-marker-DwQBrLBz.js → status-page-marker-gaihi0KZ.js} +140 -28
  60. package/dist/_chunks/status-page-marker-gaihi0KZ.js.map +1 -0
  61. package/dist/_chunks/{walkers-CN2N_bA-.js → walkers-BXExhzzk.js} +2 -2
  62. package/dist/_chunks/{walkers-CN2N_bA-.js.map → walkers-BXExhzzk.js.map} +1 -1
  63. package/dist/_chunks/write-file-atomic-D1qWqHb4.js +32 -0
  64. package/dist/_chunks/write-file-atomic-D1qWqHb4.js.map +1 -0
  65. package/dist/adapters/build-output-helper.d.ts +7 -7
  66. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  67. package/dist/adapters/canonicalize-module.d.ts +8 -0
  68. package/dist/adapters/canonicalize-module.d.ts.map +1 -0
  69. package/dist/adapters/cloudflare-dev.js +1 -1
  70. package/dist/adapters/cloudflare-kv-cache.js +2 -2
  71. package/dist/adapters/cloudflare.d.ts +30 -8
  72. package/dist/adapters/cloudflare.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare.js +2 -2
  74. package/dist/adapters/compress-module.d.ts +8 -0
  75. package/dist/adapters/compress-module.d.ts.map +1 -1
  76. package/dist/adapters/fs-identity.d.ts +2 -3
  77. package/dist/adapters/fs-identity.d.ts.map +1 -1
  78. package/dist/adapters/nitro-presets.d.ts +0 -6
  79. package/dist/adapters/nitro-presets.d.ts.map +1 -1
  80. package/dist/adapters/nitro-preview.d.ts +43 -11
  81. package/dist/adapters/nitro-preview.d.ts.map +1 -1
  82. package/dist/adapters/nitro.d.ts +1 -13
  83. package/dist/adapters/nitro.d.ts.map +1 -1
  84. package/dist/adapters/nitro.js +291 -176
  85. package/dist/adapters/nitro.js.map +1 -1
  86. package/dist/adapters/shared.d.ts +7 -2
  87. package/dist/adapters/shared.d.ts.map +1 -1
  88. package/dist/adapters/types.d.ts +105 -21
  89. package/dist/adapters/types.d.ts.map +1 -1
  90. package/dist/adapters/types.js +0 -0
  91. package/dist/analyze/crawl-entry.js +3 -3
  92. package/dist/analyze/graph-cache.d.ts.map +1 -1
  93. package/dist/analyze/graph-command.js +4 -4
  94. package/dist/cache/index.js +2 -2
  95. package/dist/cache/json-lossy-check.d.ts.map +1 -1
  96. package/dist/cache/singleflight.d.ts.map +1 -1
  97. package/dist/cache/sizeof.d.ts.map +1 -1
  98. package/dist/cache/stores/memory.js +1 -1
  99. package/dist/cache/tag-aware-handler.d.ts.map +1 -1
  100. package/dist/cdn/workers-cache-purge.js +1 -1
  101. package/dist/cli-check.d.ts +7 -37
  102. package/dist/cli-check.d.ts.map +1 -1
  103. package/dist/cli-context.d.ts +54 -0
  104. package/dist/cli-context.d.ts.map +1 -0
  105. package/dist/cli.d.ts +9 -9
  106. package/dist/cli.d.ts.map +1 -1
  107. package/dist/cli.js +20 -24
  108. package/dist/cli.js.map +1 -1
  109. package/dist/client/browser-dev.d.ts +1 -1
  110. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  111. package/dist/client/browser-entry/hydrate.d.ts +19 -29
  112. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  113. package/dist/client/browser-entry/index.d.ts +7 -7
  114. package/dist/client/browser-entry/post-hydration.d.ts +6 -9
  115. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  116. package/dist/client/browser-entry/router-init.d.ts +6 -11
  117. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  118. package/dist/client/error-boundary.d.ts +4 -3
  119. package/dist/client/error-boundary.d.ts.map +1 -1
  120. package/dist/client/error-boundary.js +1 -1
  121. package/dist/client/error-reconstituter.d.ts +3 -9
  122. package/dist/client/error-reconstituter.d.ts.map +1 -1
  123. package/dist/client/history.d.ts +20 -11
  124. package/dist/client/history.d.ts.map +1 -1
  125. package/dist/client/index.d.ts +0 -1
  126. package/dist/client/index.d.ts.map +1 -1
  127. package/dist/client/index.js +5 -6
  128. package/dist/client/index.js.map +1 -1
  129. package/dist/client/internal.d.ts +3 -3
  130. package/dist/client/internal.d.ts.map +1 -1
  131. package/dist/client/internal.js +95 -108
  132. package/dist/client/internal.js.map +1 -1
  133. package/dist/client/navigation-commit.d.ts +20 -7
  134. package/dist/client/navigation-commit.d.ts.map +1 -1
  135. package/dist/client/navigation-context.d.ts +3 -5
  136. package/dist/client/navigation-context.d.ts.map +1 -1
  137. package/dist/client/react-root.d.ts +3 -2
  138. package/dist/client/react-root.d.ts.map +1 -1
  139. package/dist/client/router-pipeline.d.ts +3 -8
  140. package/dist/client/router-pipeline.d.ts.map +1 -1
  141. package/dist/client/router-types.d.ts +45 -39
  142. package/dist/client/router-types.d.ts.map +1 -1
  143. package/dist/client/router-url.d.ts +24 -0
  144. package/dist/client/router-url.d.ts.map +1 -0
  145. package/dist/client/router.d.ts.map +1 -1
  146. package/dist/client/rsc-fetch.d.ts +8 -4
  147. package/dist/client/rsc-fetch.d.ts.map +1 -1
  148. package/dist/client/segment-cache.d.ts +44 -4
  149. package/dist/client/segment-cache.d.ts.map +1 -1
  150. package/dist/client/ssr-data.d.ts +18 -64
  151. package/dist/client/ssr-data.d.ts.map +1 -1
  152. package/dist/client/state.d.ts +2 -5
  153. package/dist/client/state.d.ts.map +1 -1
  154. package/dist/client/use-pathname.d.ts +1 -1
  155. package/dist/config-types.d.ts +2 -1
  156. package/dist/config-types.d.ts.map +1 -1
  157. package/dist/config-validation.d.ts.map +1 -1
  158. package/dist/cookies/index.js +1 -1
  159. package/dist/dev-tools/dev-page-shell.d.ts +17 -0
  160. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
  161. package/dist/dev-tools/index.d.ts +1 -1
  162. package/dist/dev-tools/index.d.ts.map +1 -1
  163. package/dist/dev-tools/instrumentation.d.ts +17 -2
  164. package/dist/dev-tools/instrumentation.d.ts.map +1 -1
  165. package/dist/dev-tools/overlay.d.ts +6 -27
  166. package/dist/dev-tools/overlay.d.ts.map +1 -1
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +632 -373
  169. package/dist/index.js.map +1 -1
  170. package/dist/plugin-context.d.ts +26 -40
  171. package/dist/plugin-context.d.ts.map +1 -1
  172. package/dist/plugins/build-manifest.d.ts.map +1 -1
  173. package/dist/plugins/build-report.d.ts +15 -2
  174. package/dist/plugins/build-report.d.ts.map +1 -1
  175. package/dist/plugins/dev-server.d.ts.map +1 -1
  176. package/dist/plugins/entries.d.ts.map +1 -1
  177. package/dist/plugins/fonts.d.ts +19 -1
  178. package/dist/plugins/fonts.d.ts.map +1 -1
  179. package/dist/plugins/post-build.d.ts +110 -0
  180. package/dist/plugins/post-build.d.ts.map +1 -0
  181. package/dist/plugins/prebuilt-capture.d.ts +11 -4
  182. package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
  183. package/dist/plugins/prebuilt.d.ts +17 -1
  184. package/dist/plugins/prebuilt.d.ts.map +1 -1
  185. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  186. package/dist/plugins/react-resolve.d.ts +49 -0
  187. package/dist/plugins/react-resolve.d.ts.map +1 -0
  188. package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
  189. package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
  190. package/dist/plugins/shims.d.ts.map +1 -1
  191. package/dist/plugins/static-build.d.ts +32 -9
  192. package/dist/plugins/static-build.d.ts.map +1 -1
  193. package/dist/routing/codegen-write.d.ts +0 -9
  194. package/dist/routing/codegen-write.d.ts.map +1 -1
  195. package/dist/routing/index.js +2 -2
  196. package/dist/routing/segment-codegen.d.ts.map +1 -1
  197. package/dist/server/access-gate.d.ts.map +1 -1
  198. package/dist/server/action-handler.d.ts +5 -4
  199. package/dist/server/action-handler.d.ts.map +1 -1
  200. package/dist/server/actions.d.ts +46 -7
  201. package/dist/server/actions.d.ts.map +1 -1
  202. package/dist/server/als-registry.d.ts +58 -5
  203. package/dist/server/als-registry.d.ts.map +1 -1
  204. package/dist/server/children-interception.d.ts.map +1 -1
  205. package/dist/server/cookie-context.d.ts +2 -23
  206. package/dist/server/cookie-context.d.ts.map +1 -1
  207. package/dist/server/csp-nonce.d.ts +0 -9
  208. package/dist/server/csp-nonce.d.ts.map +1 -1
  209. package/dist/server/csrf.d.ts +27 -4
  210. package/dist/server/csrf.d.ts.map +1 -1
  211. package/dist/server/debug.d.ts +0 -1
  212. package/dist/server/debug.d.ts.map +1 -1
  213. package/dist/server/default-logger.d.ts +2 -1
  214. package/dist/server/default-logger.d.ts.map +1 -1
  215. package/dist/server/deny-boundary.d.ts +12 -6
  216. package/dist/server/deny-boundary.d.ts.map +1 -1
  217. package/dist/server/deny-renderer.d.ts +2 -2
  218. package/dist/server/deny-renderer.d.ts.map +1 -1
  219. package/dist/server/error-boundary-wrapper.d.ts +7 -3
  220. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  221. package/dist/server/fallback-error.d.ts +9 -2
  222. package/dist/server/fallback-error.d.ts.map +1 -1
  223. package/dist/server/head-response.d.ts +4 -4
  224. package/dist/server/html-injectors.d.ts.map +1 -1
  225. package/dist/server/index.d.ts +0 -1
  226. package/dist/server/index.d.ts.map +1 -1
  227. package/dist/server/index.js +3 -4
  228. package/dist/server/index.js.map +1 -1
  229. package/dist/server/instrumentation.d.ts +10 -3
  230. package/dist/server/instrumentation.d.ts.map +1 -1
  231. package/dist/server/internal.d.ts +1 -4
  232. package/dist/server/internal.d.ts.map +1 -1
  233. package/dist/server/internal.js +961 -581
  234. package/dist/server/internal.js.map +1 -1
  235. package/dist/server/json-status-response.d.ts +34 -0
  236. package/dist/server/json-status-response.d.ts.map +1 -0
  237. package/dist/server/logger.d.ts +26 -0
  238. package/dist/server/logger.d.ts.map +1 -1
  239. package/dist/server/param-coercion.d.ts +11 -6
  240. package/dist/server/param-coercion.d.ts.map +1 -1
  241. package/dist/server/pipeline-helpers.d.ts +95 -7
  242. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  243. package/dist/server/pipeline-interception.d.ts +11 -0
  244. package/dist/server/pipeline-interception.d.ts.map +1 -1
  245. package/dist/server/pipeline-outcome.d.ts +11 -1
  246. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  247. package/dist/server/pipeline-phases.d.ts +2 -2
  248. package/dist/server/pipeline-phases.d.ts.map +1 -1
  249. package/dist/server/pipeline.d.ts +23 -35
  250. package/dist/server/pipeline.d.ts.map +1 -1
  251. package/dist/server/prebuilt/capture-render.d.ts +25 -0
  252. package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
  253. package/dist/server/prebuilt/capture-routes.d.ts +37 -0
  254. package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
  255. package/dist/server/prebuilt/capture-state.d.ts +79 -35
  256. package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
  257. package/dist/server/prebuilt/lifetime.d.ts +38 -0
  258. package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
  259. package/dist/server/prebuilt/slots.d.ts +7 -0
  260. package/dist/server/prebuilt/slots.d.ts.map +1 -1
  261. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
  262. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  263. package/dist/server/prebuilt-runtime.d.ts.map +1 -1
  264. package/dist/server/primitives.d.ts +6 -81
  265. package/dist/server/primitives.d.ts.map +1 -1
  266. package/dist/server/react-cache-bridge.d.ts +59 -0
  267. package/dist/server/react-cache-bridge.d.ts.map +1 -0
  268. package/dist/server/react-cache-scope.d.ts +49 -0
  269. package/dist/server/react-cache-scope.d.ts.map +1 -0
  270. package/dist/server/render-timeout.d.ts +15 -0
  271. package/dist/server/render-timeout.d.ts.map +1 -1
  272. package/dist/server/render-utils.d.ts +9 -0
  273. package/dist/server/render-utils.d.ts.map +1 -1
  274. package/dist/server/request-context.d.ts +26 -5
  275. package/dist/server/request-context.d.ts.map +1 -1
  276. package/dist/server/route-element-builder.d.ts.map +1 -1
  277. package/dist/server/route-handler.d.ts.map +1 -1
  278. package/dist/server/route-matcher.d.ts +7 -0
  279. package/dist/server/route-matcher.d.ts.map +1 -1
  280. package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
  281. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
  282. package/dist/server/rsc-entry/api-handler.d.ts +7 -0
  283. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  284. package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
  285. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  286. package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
  287. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  288. package/dist/server/rsc-entry/helpers.d.ts +0 -1
  289. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  290. package/dist/server/rsc-entry/index.d.ts +5 -15
  291. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  292. package/dist/server/rsc-entry/render-route.d.ts +5 -6
  293. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  294. package/dist/server/rsc-entry/render-signals.d.ts +65 -0
  295. package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
  296. package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
  297. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  298. package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
  299. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  300. package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
  301. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  302. package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
  303. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  304. package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
  305. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  306. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
  307. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
  308. package/dist/server/signal-identity.d.ts +43 -0
  309. package/dist/server/signal-identity.d.ts.map +1 -0
  310. package/dist/server/slot-resolver.d.ts +4 -3
  311. package/dist/server/slot-resolver.d.ts.map +1 -1
  312. package/dist/server/slot-subtree-contain.d.ts.map +1 -1
  313. package/dist/server/ssr-bridge-types.d.ts +91 -53
  314. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  315. package/dist/server/ssr-entry.d.ts +8 -5
  316. package/dist/server/ssr-entry.d.ts.map +1 -1
  317. package/dist/server/ssr-render.d.ts +26 -40
  318. package/dist/server/ssr-render.d.ts.map +1 -1
  319. package/dist/server/ssr-wrappers.d.ts +1 -1
  320. package/dist/server/static-generator.d.ts.map +1 -1
  321. package/dist/server/stream-utils.d.ts +12 -0
  322. package/dist/server/stream-utils.d.ts.map +1 -1
  323. package/dist/server/tracing.d.ts +12 -16
  324. package/dist/server/tracing.d.ts.map +1 -1
  325. package/dist/server/types.d.ts +1 -1
  326. package/dist/server/version-skew.d.ts +3 -3
  327. package/dist/shared/csrf-reject.d.ts +16 -0
  328. package/dist/shared/csrf-reject.d.ts.map +1 -0
  329. package/dist/shared/error-digest.d.ts +28 -0
  330. package/dist/shared/error-digest.d.ts.map +1 -0
  331. package/dist/shared/payload-root.d.ts +11 -10
  332. package/dist/shared/payload-root.d.ts.map +1 -1
  333. package/dist/shared/rsc-payload-path.d.ts +6 -0
  334. package/dist/shared/rsc-payload-path.d.ts.map +1 -1
  335. package/dist/utils/write-file-atomic.d.ts +17 -0
  336. package/dist/utils/write-file-atomic.d.ts.map +1 -0
  337. package/docs/api/30-api-server.mdx +17 -14
  338. package/docs/api/32-api-cache.mdx +51 -23
  339. package/docs/api/34-api-config.mdx +34 -6
  340. package/docs/api/36-cli.mdx +11 -1
  341. package/docs/learn/03-fetching-data.mdx +17 -1
  342. package/docs/learn/04-access-control.mdx +1 -1
  343. package/docs/learn/10-caching.mdx +29 -11
  344. package/docs/learn/11-middleware.mdx +8 -2
  345. package/docs/learn/12-error-handling.mdx +6 -1
  346. package/package.json +7 -3
  347. package/src/adapters/build-output-helper.ts +55 -53
  348. package/src/adapters/canonicalize-module.ts +29 -0
  349. package/src/adapters/cloudflare.ts +105 -63
  350. package/src/adapters/compress-module.ts +16 -5
  351. package/src/adapters/fs-identity.ts +2 -3
  352. package/src/adapters/nitro-presets.ts +0 -15
  353. package/src/adapters/nitro-preview.ts +272 -136
  354. package/src/adapters/nitro.ts +119 -82
  355. package/src/adapters/shared.ts +23 -14
  356. package/src/adapters/types.ts +110 -21
  357. package/src/analyze/graph-cache.ts +3 -4
  358. package/src/cache/json-lossy-check.ts +3 -9
  359. package/src/cache/singleflight.ts +5 -2
  360. package/src/cache/sizeof.ts +3 -1
  361. package/src/cache/tag-aware-handler.ts +43 -26
  362. package/src/cli-check.ts +8 -98
  363. package/src/cli-context.ts +119 -0
  364. package/src/cli.ts +19 -28
  365. package/src/client/browser-dev.ts +1 -1
  366. package/src/client/browser-entry/action-dispatch.ts +26 -4
  367. package/src/client/browser-entry/hydrate.ts +53 -58
  368. package/src/client/browser-entry/index.ts +16 -27
  369. package/src/client/browser-entry/post-hydration.ts +6 -40
  370. package/src/client/browser-entry/router-init.ts +66 -84
  371. package/src/client/error-boundary.tsx +9 -41
  372. package/src/client/error-reconstituter.tsx +10 -5
  373. package/src/client/history.ts +35 -21
  374. package/src/client/index.ts +0 -1
  375. package/src/client/internal.ts +2 -7
  376. package/src/client/navigation-commit.ts +41 -18
  377. package/src/client/navigation-context.ts +3 -39
  378. package/src/client/react-root.ts +3 -2
  379. package/src/client/router-pipeline.ts +96 -132
  380. package/src/client/router-types.ts +46 -44
  381. package/src/client/router-url.ts +32 -0
  382. package/src/client/router.ts +62 -21
  383. package/src/client/rsc-fetch.ts +117 -155
  384. package/src/client/segment-cache.ts +110 -11
  385. package/src/client/ssr-data.ts +19 -80
  386. package/src/client/state.ts +2 -9
  387. package/src/client/use-pathname.ts +1 -1
  388. package/src/config-types.ts +2 -1
  389. package/src/config-validation.ts +2 -1
  390. package/src/dev-tools/dev-page-shell.ts +18 -0
  391. package/src/dev-tools/index.ts +0 -2
  392. package/src/dev-tools/instrumentation.ts +50 -2
  393. package/src/dev-tools/overlay.ts +8 -238
  394. package/src/index.ts +26 -14
  395. package/src/plugin-context.ts +39 -40
  396. package/src/plugins/build-manifest.ts +4 -11
  397. package/src/plugins/build-report.ts +70 -70
  398. package/src/plugins/dev-server.ts +24 -44
  399. package/src/plugins/entries.ts +2 -1
  400. package/src/plugins/fonts.ts +35 -7
  401. package/src/plugins/post-build.ts +327 -0
  402. package/src/plugins/prebuilt-capture.ts +28 -32
  403. package/src/plugins/prebuilt.ts +54 -39
  404. package/src/plugins/prerender-sugar.ts +0 -4
  405. package/src/plugins/react-resolve.ts +149 -0
  406. package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
  407. package/src/plugins/shims.ts +1 -0
  408. package/src/plugins/static-build.ts +42 -74
  409. package/src/routing/codegen-write.ts +25 -3
  410. package/src/routing/segment-codegen.ts +3 -2
  411. package/src/rsc-runtime/vendor-types.d.ts +8 -0
  412. package/src/server/access-gate.tsx +2 -1
  413. package/src/server/action-client.ts +1 -1
  414. package/src/server/action-handler.ts +253 -110
  415. package/src/server/actions.ts +73 -25
  416. package/src/server/als-registry.ts +73 -5
  417. package/src/server/chain-url-parts.ts +1 -1
  418. package/src/server/children-interception.ts +2 -1
  419. package/src/server/cookie-context.ts +18 -48
  420. package/src/server/csp-nonce.ts +0 -12
  421. package/src/server/csrf.ts +140 -8
  422. package/src/server/debug.ts +0 -1
  423. package/src/server/default-logger.ts +2 -1
  424. package/src/server/deny-boundary.ts +25 -13
  425. package/src/server/deny-renderer.ts +30 -97
  426. package/src/server/error-boundary-wrapper.ts +7 -3
  427. package/src/server/fallback-error.ts +26 -11
  428. package/src/server/flight-scripts.ts +1 -1
  429. package/src/server/head-response.ts +4 -4
  430. package/src/server/html-injector-core.ts +2 -2
  431. package/src/server/html-injectors.ts +2 -4
  432. package/src/server/index.ts +0 -4
  433. package/src/server/instrumentation.ts +10 -3
  434. package/src/server/internal.ts +1 -6
  435. package/src/server/json-status-response.ts +105 -0
  436. package/src/server/logger.ts +39 -3
  437. package/src/server/param-coercion.ts +15 -12
  438. package/src/server/pipeline-helpers.ts +257 -12
  439. package/src/server/pipeline-interception.ts +133 -0
  440. package/src/server/pipeline-outcome.ts +103 -31
  441. package/src/server/pipeline-phases.ts +127 -237
  442. package/src/server/pipeline.ts +204 -207
  443. package/src/server/prebuilt/capture-render.ts +118 -0
  444. package/src/server/prebuilt/capture-routes.ts +104 -0
  445. package/src/server/prebuilt/capture-state.ts +155 -48
  446. package/src/server/prebuilt/lifetime.ts +151 -0
  447. package/src/server/prebuilt/slots.ts +14 -2
  448. package/src/server/prebuilt/synthetic-store.ts +3 -0
  449. package/src/server/prebuilt-builder.ts +30 -320
  450. package/src/server/prebuilt-runtime.ts +125 -129
  451. package/src/server/primitives.ts +8 -168
  452. package/src/server/react-cache-bridge.ts +124 -0
  453. package/src/server/react-cache-scope.ts +104 -0
  454. package/src/server/render-timeout.ts +20 -0
  455. package/src/server/render-utils.ts +11 -1
  456. package/src/server/request-context.ts +36 -9
  457. package/src/server/route-element-builder.ts +11 -6
  458. package/src/server/route-handler.ts +36 -23
  459. package/src/server/route-matcher.ts +15 -1
  460. package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
  461. package/src/server/rsc-entry/api-handler.ts +27 -103
  462. package/src/server/rsc-entry/deny-fallback.ts +93 -26
  463. package/src/server/rsc-entry/error-renderer.ts +39 -91
  464. package/src/server/rsc-entry/helpers.ts +2 -4
  465. package/src/server/rsc-entry/index.ts +64 -58
  466. package/src/server/rsc-entry/render-route.ts +15 -80
  467. package/src/server/rsc-entry/render-signals.ts +108 -0
  468. package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
  469. package/src/server/rsc-entry/rsc-payload.ts +28 -61
  470. package/src/server/rsc-entry/rsc-stream.ts +113 -213
  471. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  472. package/src/server/rsc-entry/ssr-renderer.ts +182 -263
  473. package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
  474. package/src/server/signal-identity.ts +112 -0
  475. package/src/server/slot-resolver.ts +18 -18
  476. package/src/server/slot-subtree-contain.ts +2 -1
  477. package/src/server/ssr-bridge-types.ts +92 -56
  478. package/src/server/ssr-entry.ts +87 -111
  479. package/src/server/ssr-render.ts +55 -64
  480. package/src/server/ssr-wrappers.tsx +2 -2
  481. package/src/server/static-generator.ts +7 -42
  482. package/src/server/static-not-found.ts +3 -3
  483. package/src/server/stream-utils.ts +51 -0
  484. package/src/server/tracing.ts +58 -75
  485. package/src/server/types.ts +1 -1
  486. package/src/server/version-skew.ts +5 -5
  487. package/src/shared/csrf-reject.ts +15 -0
  488. package/src/shared/error-digest.ts +46 -0
  489. package/src/shared/payload-root.ts +11 -10
  490. package/src/shared/rsc-payload-path.ts +8 -1
  491. package/src/utils/write-file-atomic.ts +32 -0
  492. package/dist/_chunks/actions-jNrXdzgs.js +0 -346
  493. package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
  494. package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
  495. package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
  496. package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
  497. package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
  498. package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
  499. package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
  500. package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
  501. package/dist/_chunks/error-boundary-BndF-3Td.js.map +0 -1
  502. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
  503. package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
  504. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
  505. package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
  506. package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
  507. package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
  508. package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
  509. package/dist/_chunks/segment-context-D9_89u34.js +0 -34
  510. package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
  511. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
  512. package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
  513. package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
  514. package/dist/_chunks/state-FippDgxN.js.map +0 -1
  515. package/dist/_chunks/status-page-marker-DwQBrLBz.js.map +0 -1
  516. package/dist/client/types.d.ts +0 -14
  517. package/dist/client/types.d.ts.map +0 -1
  518. package/dist/plugins/adapter-build.d.ts +0 -38
  519. package/dist/plugins/adapter-build.d.ts.map +0 -1
  520. package/dist/server/asset-headers.d.ts +0 -32
  521. package/dist/server/asset-headers.d.ts.map +0 -1
  522. package/dist/server/dev-source-map.d.ts +0 -22
  523. package/dist/server/dev-source-map.d.ts.map +0 -1
  524. package/src/client/types.ts +0 -21
  525. package/src/server/asset-headers.ts +0 -59
  526. package/src/server/dev-source-map.ts +0 -31
@@ -1,5 +1,5 @@
1
1
  import { i as withBasePath } from "./base-path-DaQrzbez.js";
2
- import { c as USER_PLATFORM_DIR, i as HEADERS_FILE, n as detectFsIdentity, r as fsKey, s as USER_MERGED_PLATFORM_FILES } from "./fs-identity-D7vb6GdI.js";
2
+ import { c as USER_PLATFORM_DIR, i as HEADERS_FILE, n as detectFsIdentity, r as fsKey, s as USER_MERGED_PLATFORM_FILES } from "./fs-identity-BRKuL215.js";
3
3
  import { basename, join, relative } from "node:path";
4
4
  import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
5
5
  //#region src/adapters/shared.ts
@@ -10,7 +10,7 @@ import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
10
10
  * by callers that predate it (a hand-written adapter, a test harness). Falling
11
11
  * back to `'/'` reproduces the pre-TIM-1274 output exactly, which is correct
12
12
  * for the only deployments those callers can have: a build under a non-root
13
- * base always goes through `plugins/adapter-build.ts`, which populates it.
13
+ * base always goes through `plugins/post-build.ts`, which populates it.
14
14
  *
15
15
  * Typed structurally rather than as `TimberConfig` so this module keeps no
16
16
  * import of `./types.js` at runtime.
@@ -29,7 +29,9 @@ var STATIC_CACHE = "public, max-age=3600, must-revalidate";
29
29
  * Static Assets, Cloudflare Pages, and Netlify. It maps URL patterns to
30
30
  * HTTP response headers.
31
31
  *
32
- * Only hashed (immutable) asset paths are listed here by default. When
32
+ * The build's content-hashed directories (`immutableDirs`, recorded on
33
+ * `BuildArtifacts` by the phases that hashed them) get one wildcard rule
34
+ * each. When
33
35
  * `unhashedPaths` is provided, per-file rules are appended for unhashed
34
36
  * static assets (favicon.ico, robots.txt, etc.) so they get Cache-Control
35
37
  * on platforms like Cloudflare Workers Static Assets where the server
@@ -48,11 +50,11 @@ var STATIC_CACHE = "public, max-age=3600, must-revalidate";
48
50
  * Cloudflare Workers Static Assets without one.
49
51
  *
50
52
  * The prefix is applied at exactly one point, `rulePath()`, which every rule
51
- * in this function goes through. Prefixing the three wildcards and
53
+ * in this function goes through. Prefixing the wildcards and
52
54
  * hand-checking that the per-file rules agree is how the next rule gets
53
55
  * missed.
54
56
  */
55
- var MAX_PER_FILE_RULES = 97;
57
+ var MAX_RULES = 100;
56
58
  /**
57
59
  * Count the rules in a `_headers` file — a rule is a path line, which is any
58
60
  * line that is neither blank, a comment, nor an indented header.
@@ -105,7 +107,7 @@ function patternsOverlap(a, b) {
105
107
  if (pb !== null && (a.startsWith(pb) || pb === "")) return true;
106
108
  return false;
107
109
  }
108
- function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
110
+ function generateHeadersFile({ base, immutableDirs, unhashedPaths, contentTypes, userRules }) {
109
111
  /** Route-space rule path → deployed-URL rule path. */
110
112
  const rulePath = (path) => withBasePath(base, path);
111
113
  const userRuleList = userRules ? parseHeaderRules(userRules) : [];
@@ -130,15 +132,12 @@ function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
130
132
  let content = `# Auto-generated by @timber-js/app — static asset cache headers.
131
133
  # See design/25-production-deployments.md §"CDN / Edge Cache"
132
134
  `;
133
- for (const path of [
134
- "/assets/*",
135
- "/_timber/fonts/*",
136
- "/_rsc/*"
137
- ]) content += emit(rulePath(path), "Cache-Control", IMMUTABLE_CACHE);
135
+ for (const dir of immutableDirs) content += emit(rulePath(`/${dir}/*`), "Cache-Control", IMMUTABLE_CACHE);
136
+ const maxPerFileRules = MAX_RULES - immutableDirs.length;
138
137
  const allCtEntries = contentTypes ? Object.entries(contentTypes).sort(([a], [b]) => a.localeCompare(b)) : [];
139
- const ctEntries = allCtEntries.slice(0, MAX_PER_FILE_RULES);
140
- if (allCtEntries.length > MAX_PER_FILE_RULES) console.warn(`[timber] _headers: ${allCtEntries.length} content-type rules exceed Cloudflare's 100-rule limit. Only the first ${MAX_PER_FILE_RULES} extensionless API routes will get Content-Type headers.`);
141
- const remainingBudget = MAX_PER_FILE_RULES - ctEntries.length;
138
+ const ctEntries = allCtEntries.slice(0, maxPerFileRules);
139
+ if (allCtEntries.length > maxPerFileRules) console.warn(`[timber] _headers: ${allCtEntries.length} content-type rules exceed Cloudflare's 100-rule limit. Only the first ${maxPerFileRules} extensionless API routes will get Content-Type headers.`);
140
+ const remainingBudget = maxPerFileRules - ctEntries.length;
142
141
  if (unhashedPaths && unhashedPaths.length > 0) {
143
142
  const capped = unhashedPaths.slice(0, Math.max(0, remainingBudget));
144
143
  if (unhashedPaths.length > remainingBudget) console.warn(`[timber] _headers: ${unhashedPaths.length} unhashed static files + ${ctEntries.length} content-type rules found, but Cloudflare limits _headers to 100 rules. Only the first ${capped.length} unhashed files will get Cache-Control headers.`);
@@ -150,7 +149,7 @@ function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
150
149
  if (userRules && userRules.trim() !== "") {
151
150
  content += `\n# User-authored rules from public/_headers\n\n${userRules.trim()}\n`;
152
151
  const total = countHeaderRules(content);
153
- if (total > 100) console.warn(`[timber] _headers: ${total} rules after merging public/_headers, over Cloudflare's 100-rule limit. Rules past the limit are dropped by the platform — remove some, or move static assets under a directory the wildcard rules already cover.`);
152
+ if (total > MAX_RULES) console.warn(`[timber] _headers: ${total} rules after merging public/_headers, over Cloudflare's ${MAX_RULES}-rule limit. Rules past the limit are dropped by the platform — remove some, or move static assets under a directory the wildcard rules already cover.`);
154
153
  }
155
154
  return content;
156
155
  }
@@ -168,11 +167,11 @@ function generateHeadersFile({ base, unhashedPaths, contentTypes, userRules }) {
168
167
  * Returns the resolved public directory path for further adapter-specific use.
169
168
  */
170
169
  async function runSharedBuildSteps(opts) {
171
- const { config, buildDir, outDir, publicDirName } = opts;
170
+ const { config, artifacts, outDir, publicDirName } = opts;
172
171
  await mkdir(outDir, { recursive: true });
173
- const clientDir = join(buildDir, "client");
174
172
  const publicDir = join(outDir, publicDirName);
175
173
  await mkdir(publicDir, { recursive: true });
174
+ const clientDir = artifacts.client.path;
176
175
  const referencedWasm = await findReferencedWasm(clientDir);
177
176
  await cp(clientDir, publicDir, {
178
177
  recursive: true,
@@ -181,18 +180,12 @@ async function runSharedBuildSteps(opts) {
181
180
  if (config.clientJavascriptDisabled && src.endsWith(".js")) return false;
182
181
  return true;
183
182
  }
184
- }).catch((e) => {
185
- if (e.code !== "ENOENT") throw e;
186
183
  });
187
- await writeHeadersFile(publicDir, config, await findUnhashedStaticFiles(publicDir));
188
- await cp(join(buildDir, "rsc"), join(outDir, "rsc"), { recursive: true });
189
- await cp(join(buildDir, "ssr"), join(outDir, "ssr"), { recursive: true }).catch((e) => {
190
- if (e.code !== "ENOENT") throw e;
191
- });
192
- await cp(join(buildDir, "prebuilt"), join(outDir, "prebuilt"), { recursive: true }).catch((e) => {
193
- if (e.code !== "ENOENT") throw e;
194
- });
195
- if (config.manifestInit) await writeFile(join(outDir, "_timber-manifest-init.js"), config.manifestInit);
184
+ await writeHeadersFile(publicDir, config, artifacts);
185
+ await cp(artifacts.rsc.path, join(outDir, "rsc"), { recursive: true });
186
+ await cp(artifacts.ssr.path, join(outDir, "ssr"), { recursive: true });
187
+ if (artifacts.prebuilt) await cp(artifacts.prebuilt.path, join(outDir, "prebuilt"), { recursive: true });
188
+ if (artifacts.manifestInit) await writeFile(join(outDir, "_timber-manifest-init.js"), artifacts.manifestInit);
196
189
  return publicDir;
197
190
  }
198
191
  /**
@@ -200,9 +193,16 @@ async function runSharedBuildSteps(opts) {
200
193
  * Cache-Control rules in the `_headers` file.
201
194
  *
202
195
  * Excludes:
203
- * - Files under `assets/` and `_timber/` (covered by wildcard rules)
196
+ * - Files under the build's `immutableDirs` (covered by wildcard rules)
197
+ * - Files under `rsc/` and `ssr/` (server bundles, never served)
204
198
  * - Underscore-prefixed files (`_headers`, `_worker.js`, etc.)
205
199
  *
200
+ * Ordered for the rule cap: well-known metadata files, then everything
201
+ * else, then files under an underscore-prefixed directory — the
202
+ * framework's own output (unhashed RSC payloads in a static build with
203
+ * client JavaScript disabled, which nothing fetches). Those can number one
204
+ * per route, and must not take the budget from the app's real files.
205
+ *
206
206
  * @internal Exported for testing.
207
207
  */
208
208
  var PRIORITY_FILES = /* @__PURE__ */ new Set([
@@ -213,7 +213,7 @@ var PRIORITY_FILES = /* @__PURE__ */ new Set([
213
213
  "/manifest.webmanifest",
214
214
  "/apple-touch-icon.png"
215
215
  ]);
216
- async function findUnhashedStaticFiles(publicDir) {
216
+ async function findUnhashedStaticFiles(publicDir, immutableDirs) {
217
217
  let files;
218
218
  try {
219
219
  files = await collectFiles(publicDir);
@@ -222,16 +222,22 @@ async function findUnhashedStaticFiles(publicDir) {
222
222
  }
223
223
  const priority = [];
224
224
  const rest = [];
225
+ const framework = [];
225
226
  for (const file of files) {
226
227
  const rel = relative(publicDir, file).replace(/\\/g, "/");
227
- if (rel.startsWith("assets/") || rel.startsWith("_timber/")) continue;
228
- if (rel.startsWith("rsc/") || rel.startsWith("ssr/") || rel.startsWith("_rsc/")) continue;
228
+ if (immutableDirs.some((dir) => rel.startsWith(`${dir}/`))) continue;
229
+ if (rel.startsWith("rsc/") || rel.startsWith("ssr/")) continue;
229
230
  if (basename(rel).startsWith("_")) continue;
230
231
  const urlPath = "/" + rel;
231
232
  if (PRIORITY_FILES.has(urlPath)) priority.push(urlPath);
233
+ else if (rel.startsWith("_")) framework.push(urlPath);
232
234
  else rest.push(urlPath);
233
235
  }
234
- return [...priority.sort(), ...rest.sort()];
236
+ return [
237
+ ...priority.sort(),
238
+ ...rest.sort(),
239
+ ...framework.sort()
240
+ ];
235
241
  }
236
242
  /**
237
243
  * Scan client JS files for references to .wasm filenames.
@@ -240,12 +246,7 @@ async function findUnhashedStaticFiles(publicDir) {
240
246
  */
241
247
  async function findReferencedWasm(clientDir) {
242
248
  const referenced = /* @__PURE__ */ new Set();
243
- let files;
244
- try {
245
- files = await collectFiles(clientDir);
246
- } catch {
247
- return referenced;
248
- }
249
+ const files = await collectFiles(clientDir);
249
250
  const jsFiles = files.filter((f) => f.endsWith(".js"));
250
251
  const wasmFiles = files.filter((f) => f.endsWith(".wasm")).map((f) => basename(f));
251
252
  if (wasmFiles.length === 0) return referenced;
@@ -260,7 +261,7 @@ async function findReferencedWasm(clientDir) {
260
261
  * assets and pre-rendered HTML/RSC/API files into `outDir/publicDirName`.
261
262
  * Used by both Cloudflare and Nitro adapters in `output: 'static'` mode.
262
263
  */
263
- async function buildStaticDirectoryOutput(config, buildDir, outDir, publicDirName) {
264
+ async function buildStaticDirectoryOutput(config, artifacts, outDir, publicDirName) {
264
265
  await rm(outDir, {
265
266
  recursive: true,
266
267
  force: true
@@ -268,20 +269,15 @@ async function buildStaticDirectoryOutput(config, buildDir, outDir, publicDirNam
268
269
  await mkdir(outDir, { recursive: true });
269
270
  const publicDir = join(outDir, publicDirName);
270
271
  await mkdir(publicDir, { recursive: true });
271
- const clientDir = join(buildDir, "client");
272
- await cp(clientDir, publicDir, {
272
+ await cp(artifacts.client.path, publicDir, {
273
273
  recursive: true,
274
274
  filter: (src) => {
275
275
  if (config.clientJavascriptDisabled && src.endsWith(".js")) return false;
276
276
  return true;
277
277
  }
278
- }).catch((e) => {
279
- if (e.code !== "ENOENT") throw e;
280
278
  });
281
- if (config.staticPagesDir) {
282
- await assertNoTreeCollision(config.staticPagesDir, publicDir);
283
- await cp(config.staticPagesDir, publicDir, { recursive: true });
284
- }
279
+ await assertNoTreeCollision(artifacts.pages.path, publicDir);
280
+ await cp(artifacts.pages.path, publicDir, { recursive: true });
285
281
  }
286
282
  /**
287
283
  * Write the `_headers` file, folding in the user's `public/_headers`.
@@ -308,12 +304,13 @@ async function buildStaticDirectoryOutput(config, buildDir, outDir, publicDirNam
308
304
  *
309
305
  * @internal Exported for testing.
310
306
  */
311
- async function writeHeadersFile(dir, config, unhashedPaths) {
307
+ async function writeHeadersFile(dir, config, artifacts) {
312
308
  const userRules = await readUserPlatformFile(config.root, HEADERS_FILE);
313
309
  await writeFile(join(dir, HEADERS_FILE), generateHeadersFile({
314
310
  base: adapterBase(config),
315
- unhashedPaths,
316
- contentTypes: config.staticContentTypes,
311
+ immutableDirs: artifacts.immutableDirs,
312
+ unhashedPaths: await findUnhashedStaticFiles(dir, artifacts.immutableDirs),
313
+ contentTypes: artifacts.output === "static" ? artifacts.contentTypes : void 0,
317
314
  userRules: userRules ?? void 0
318
315
  }));
319
316
  }
@@ -365,6 +362,6 @@ async function collectFiles(dir) {
365
362
  return result;
366
363
  }
367
364
  //#endregion
368
- export { IMMUTABLE_CACHE as a, writeHeadersFile as i, findUnhashedStaticFiles as n, runSharedBuildSteps as r, buildStaticDirectoryOutput as t };
365
+ export { STATIC_CACHE as a, IMMUTABLE_CACHE as i, runSharedBuildSteps as n, adapterBase as o, writeHeadersFile as r, buildStaticDirectoryOutput as t };
369
366
 
370
- //# sourceMappingURL=build-output-helper-9dqCv1pZ.js.map
367
+ //# sourceMappingURL=build-output-helper-RV_BRcF1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-output-helper-RV_BRcF1.js","names":[],"sources":["../../src/adapters/shared.ts","../../src/adapters/build-output-helper.ts"],"sourcesContent":["// Shared adapter utilities — leaf module with zero deps on server/, client/,\n// or any Vite-dependent code.\n//\n// Adapters are loaded by Node at Vite startup time, before Vite's module\n// resolver is available. This module uses only Node built-ins and can be\n// imported by both adapters via a relative path.\n//\n// IMPORTANT: Do NOT add imports from ../server/, ../client/, ../plugins/,\n// or any module that transitively depends on Vite. A test in\n// tests/adapters/shared-no-forbidden-imports.test.ts enforces this.\n// ../shared/ is exempt: it is dependency-free by the same rule.\n\nimport { withBasePath } from '../shared/base-path.ts';\n\n/**\n * The deployment base an adapter should write platform rules against.\n *\n * `config.base` is optional on `TimberConfig` because adapters can be invoked\n * by callers that predate it (a hand-written adapter, a test harness). Falling\n * back to `'/'` reproduces the pre-TIM-1274 output exactly, which is correct\n * for the only deployments those callers can have: a build under a non-root\n * base always goes through `plugins/post-build.ts`, which populates it.\n *\n * Typed structurally rather than as `TimberConfig` so this module keeps no\n * import of `./types.js` at runtime.\n */\nexport function adapterBase(config: { base?: string }): string {\n return config.base ?? '/';\n}\n\n// ─── Static asset cache headers ──────────────────────────────────────────\n\n/** Cache-Control value for hashed (immutable) assets. */\nexport const IMMUTABLE_CACHE = 'public, max-age=31536000, immutable';\n\n/** Cache-Control value for unhashed static assets. */\nexport const STATIC_CACHE = 'public, max-age=3600, must-revalidate';\n\n/**\n * Generate a `_headers` file for static asset cache control.\n *\n * The `_headers` file is a platform convention supported by Cloudflare Workers\n * Static Assets, Cloudflare Pages, and Netlify. It maps URL patterns to\n * HTTP response headers.\n *\n * The build's content-hashed directories (`immutableDirs`, recorded on\n * `BuildArtifacts` by the phases that hashed them) get one wildcard rule\n * each. When\n * `unhashedPaths` is provided, per-file rules are appended for unhashed\n * static assets (favicon.ico, robots.txt, etc.) so they get Cache-Control\n * on platforms like Cloudflare Workers Static Assets where the server\n * handler never sees static file requests.\n *\n * A `/*` catch-all is NOT used — it would be additive on Cloudflare,\n * producing duplicate Cache-Control directives on hashed assets\n * (invalid per RFC 9111).\n *\n * **Every rule path is written in deployed-URL space** (TIM-1274). The\n * platform matches these patterns against the request path, which under a\n * non-root `base` sits below the prefix: with `base: '/repo/'` the assets are\n * at `/repo/assets/*`, so a rule saying `/assets/*` matches nothing. Silent\n * for the cache rules (slower, still correct) and not silent for the\n * Content-Type rules — an extensionless API route output is unreadable on\n * Cloudflare Workers Static Assets without one.\n *\n * The prefix is applied at exactly one point, `rulePath()`, which every rule\n * in this function goes through. Prefixing the wildcards and\n * hand-checking that the per-file rules agree is how the next rule gets\n * missed.\n */\n// Cloudflare Workers Static Assets caps _headers at 100 rules. The wildcard\n// rules for the immutable directories come out of the same budget.\nconst MAX_RULES = 100;\n\nexport interface HeadersFileOptions {\n /**\n * The deployment base, already normalized by `normalizeBasePath()` —\n * leading and trailing slash, `'/'` at the domain root.\n *\n * Required rather than defaulted: a caller that forgets it would emit\n * root-relative rules that match nothing, which is the bug this closes.\n */\n base: string;\n /**\n * Content-hashed directories, from `BuildArtifacts.immutableDirs`. Each\n * gets an immutable `Cache-Control` wildcard rule.\n */\n immutableDirs: readonly string[];\n /** Unhashed static files (route-space paths) needing per-file cache rules. */\n unhashedPaths?: string[];\n /** Route-space path → Content-Type, for extensionless API route outputs. */\n contentTypes?: Record<string, string>;\n /**\n * Verbatim contents of the user's `public/_headers`, appended after the\n * generated rules. See `mergeUserHeaders` for why it goes last.\n */\n userRules?: string;\n}\n\n/**\n * Count the rules in a `_headers` file — a rule is a path line, which is any\n * line that is neither blank, a comment, nor an indented header.\n *\n * @internal Exported for testing.\n */\nexport function countHeaderRules(content: string): number {\n return content\n .split('\\n')\n .filter((line) => line.trim() !== '' && !line.startsWith('#') && !/^\\s/.test(line)).length;\n}\n\n/** One `_headers` block: a path pattern and the headers it sets. */\nexport interface HeaderRule {\n pattern: string;\n headers: Array<{ name: string; value: string }>;\n}\n\n/**\n * Parse a `_headers` file. A non-indented, non-comment line opens a rule; the\n * indented `Name: value` lines beneath it belong to that rule.\n *\n * @internal Exported for testing.\n */\nexport function parseHeaderRules(content: string): HeaderRule[] {\n const rules: HeaderRule[] = [];\n for (const raw of content.split('\\n')) {\n const line = raw.replace(/\\r$/, '');\n if (line.trim() === '' || line.trimStart().startsWith('#')) continue;\n if (/^\\s/.test(line)) {\n const current = rules[rules.length - 1];\n if (!current) continue; // header with no rule above it — not ours to fix\n const colon = line.indexOf(':');\n if (colon === -1) continue;\n current.headers.push({\n name: line.slice(0, colon).trim(),\n value: line.slice(colon + 1).trim(),\n });\n } else {\n rules.push({ pattern: line.trim(), headers: [] });\n }\n }\n return rules;\n}\n\n/**\n * Whether a user pattern can match paths a generated pattern also matches.\n *\n * Deliberately narrow: equality, or a prefix-glob (`/x/*`, `/*`) whose literal\n * prefix contains the other's. Anything cleverer risks claiming an overlap\n * that is not there, and the only thing this drives is a warning — a false\n * positive is noise a developer cannot act on.\n */\nfunction patternsOverlap(a: string, b: string): boolean {\n if (a === b) return true;\n const prefixOf = (p: string) => (p.endsWith('*') ? p.slice(0, -1) : null);\n const [pa, pb] = [prefixOf(a), prefixOf(b)];\n if (pa !== null && (b.startsWith(pa) || pa === '')) return true;\n if (pb !== null && (a.startsWith(pb) || pb === '')) return true;\n return false;\n}\n\nexport function generateHeadersFile({\n base,\n immutableDirs,\n unhashedPaths,\n contentTypes,\n userRules,\n}: HeadersFileOptions): string {\n /** Route-space rule path → deployed-URL rule path. */\n const rulePath = (path: string) => withBasePath(base, path);\n\n // Cloudflare and Netlify apply *every* matching rule, so emitting a header\n // the user also sets on the same path yields two definitions of it — a\n // comma-joined `Cache-Control` that is invalid per RFC 9111, and neither\n // side's intent. This module already refuses to emit a `/*` catch-all for\n // that reason; appending the user's file verbatim reintroduced it through\n // the back door (TIM-1326).\n //\n // An explicit app rule beats a framework default, so where the user names\n // the same pattern and the same header, ours is dropped. Only exact pattern\n // matches are resolved this way: silently dropping asset immutability\n // because a `/*` rule *might* subsume it would be a worse surprise than the\n // duplicate, so overlapping-but-different patterns warn instead.\n const userRuleList = userRules ? parseHeaderRules(userRules) : [];\n const overriddenExactly = new Set(\n userRuleList.flatMap((rule) =>\n rule.headers.map((h) => `${rule.pattern}\\0${h.name.toLowerCase()}`)\n )\n );\n const overridden = (pattern: string, header: string) =>\n overriddenExactly.has(`${pattern}\\0${header.toLowerCase()}`);\n\n const warnedOverlaps = new Set<string>();\n const emit = (pattern: string, header: string, value: string): string => {\n if (overridden(pattern, header)) return '';\n for (const rule of userRuleList) {\n if (rule.pattern === pattern) continue;\n if (!patternsOverlap(rule.pattern, pattern)) continue;\n for (const h of rule.headers) {\n if (h.name.toLowerCase() !== header.toLowerCase()) continue;\n const key = `${rule.pattern}\\0${pattern}\\0${header.toLowerCase()}`;\n if (warnedOverlaps.has(key)) continue;\n warnedOverlaps.add(key);\n console.warn(\n `[timber] _headers: your rule \"${rule.pattern}\" sets ${header}, which ` +\n `timber also sets on \"${pattern}\". Cloudflare and Netlify apply both, ` +\n `so the response gets two ${header} values. Use the exact pattern ` +\n `\"${pattern}\" to replace timber's rule, or narrow yours so they do ` +\n `not overlap.`\n );\n }\n }\n return `\\n${pattern}\\n ${header}: ${value}\\n`;\n };\n\n let content = `# Auto-generated by @timber-js/app — static asset cache headers.\n# See design/25-production-deployments.md §\"CDN / Edge Cache\"\n`;\n for (const dir of immutableDirs) {\n content += emit(rulePath(`/${dir}/*`), 'Cache-Control', IMMUTABLE_CACHE);\n }\n const maxPerFileRules = MAX_RULES - immutableDirs.length;\n\n // Content-Type rules are higher priority than cache headers for\n // extensionless files — without them the file is unreadable.\n const allCtEntries = contentTypes\n ? Object.entries(contentTypes).sort(([a], [b]) => a.localeCompare(b))\n : [];\n const ctEntries = allCtEntries.slice(0, maxPerFileRules);\n if (allCtEntries.length > maxPerFileRules) {\n console.warn(\n `[timber] _headers: ${allCtEntries.length} content-type rules exceed ` +\n `Cloudflare's 100-rule limit. Only the first ${maxPerFileRules} ` +\n `extensionless API routes will get Content-Type headers.`\n );\n }\n const remainingBudget = maxPerFileRules - ctEntries.length;\n\n if (unhashedPaths && unhashedPaths.length > 0) {\n const capped = unhashedPaths.slice(0, Math.max(0, remainingBudget));\n if (unhashedPaths.length > remainingBudget) {\n console.warn(\n `[timber] _headers: ${unhashedPaths.length} unhashed static files + ` +\n `${ctEntries.length} content-type rules found, but Cloudflare limits ` +\n `_headers to 100 rules. Only the first ${capped.length} unhashed ` +\n `files will get Cache-Control headers.`\n );\n }\n // Section bodies are built before their comment header so a section the\n // user has overridden entirely does not leave a heading over nothing.\n const body = capped.map((p) => emit(rulePath(p), 'Cache-Control', STATIC_CACHE)).join('');\n if (body !== '') {\n content += `\\n# Unhashed static assets — short-lived cache with revalidation\\n${body}`;\n }\n }\n\n const ctBody = ctEntries\n .map(([urlPath, ct]) => emit(rulePath(urlPath), 'Content-Type', ct))\n .join('');\n if (ctBody !== '') {\n content += `\\n# Content-Type for extensionless API routes\\n${ctBody}`;\n }\n\n // User rules last, matching the `_redirects` merge. Their paths are left\n // verbatim: `_redirects` prefixes the rules it generates because it wrote\n // them in route space, but these are the user's own text, already authored\n // against the URLs the site is deployed at.\n if (userRules && userRules.trim() !== '') {\n content += `\\n# User-authored rules from public/_headers\\n\\n${userRules.trim()}\\n`;\n\n const total = countHeaderRules(content);\n if (total > MAX_RULES) {\n console.warn(\n `[timber] _headers: ${total} rules after merging public/_headers, over ` +\n `Cloudflare's ${MAX_RULES}-rule limit. Rules past the ` +\n `limit are dropped by the platform — remove some, or move static ` +\n `assets under a directory the wildcard rules already cover.`\n );\n }\n }\n\n return content;\n}\n","// Shared build-output helper for adapter buildOutput() methods.\n//\n// Steps 1–5 of every adapter's buildOutput are platform-agnostic:\n// 1. Copy client assets to the public/static directory\n// 2. Write _headers file for static asset cache control\n// 3. Copy RSC + SSR server bundles\n// 4. Write manifest-init module (if present)\n//\n// Only the final steps (entry codegen, platform config) vary per adapter.\n//\n// IMPORTANT: This module must remain a leaf — no imports from ../server/,\n// ../client/, or Vite-dependent code. See adapters/shared.ts header.\n\nimport { writeFile, mkdir, cp, rm, readdir, readFile } from 'node:fs/promises';\nimport { join, basename, relative } from 'node:path';\nimport { adapterBase, generateHeadersFile } from './shared.ts';\n// Isomorphic, zero-import module — safe to load from an adapter, which Node's\n// native ESM loader evaluates before Vite's resolver exists. Same precedent as\n// `adapters/shared.ts` importing `../shared/base-path.js`.\nimport {\n HEADERS_FILE,\n USER_MERGED_PLATFORM_FILES,\n USER_PLATFORM_DIR,\n} from '../shared/static-platform-files.ts';\nimport { detectFsIdentity, fsKey } from './fs-identity.ts';\nimport type {\n BuildArtifacts,\n ServerBuildArtifacts,\n StaticBuildArtifacts,\n TimberConfig,\n} from './types.ts';\n\n/** Options for the shared build output steps. */\nexport interface BuildOutputBaseOptions {\n /** Resolved timber config. */\n config: TimberConfig;\n /** What the build produced. */\n artifacts: ServerBuildArtifacts;\n /** Adapter-specific output directory (e.g. `.timber/dist/nitro`). */\n outDir: string;\n /**\n * Name of the public/static directory within outDir.\n * Nitro uses 'public', Cloudflare uses 'static'.\n */\n publicDirName: string;\n}\n\n/**\n * Run the platform-agnostic build output steps shared by all adapters:\n *\n * 1. Create the output directory\n * 2. Copy client assets to the public/static directory\n * 3. Write the `_headers` file for static asset cache control\n * 4. Copy RSC and SSR server bundles into the output directory\n * 5. Write the manifest-init module if present\n *\n * Returns the resolved public directory path for further adapter-specific use.\n */\nexport async function runSharedBuildSteps(opts: BuildOutputBaseOptions): Promise<string> {\n const { config, artifacts, outDir, publicDirName } = opts;\n\n // 1. Create the output directory.\n await mkdir(outDir, { recursive: true });\n\n // 2. Copy client assets to public/static directory.\n // When client JavaScript is disabled, skip .js files — only CSS,\n // fonts, images, and other static assets are needed.\n const publicDir = join(outDir, publicDirName);\n await mkdir(publicDir, { recursive: true });\n const clientDir = artifacts.client.path;\n // Find WASM files that are referenced by client JS (legitimate client WASM)\n // vs orphaned server-only WASM (e.g. @takumi-rs for OG image generation).\n // Only strip orphaned WASM to avoid breaking client-side WASM usage.\n const referencedWasm = await findReferencedWasm(clientDir);\n\n await cp(clientDir, publicDir, {\n recursive: true,\n filter: (src: string) => {\n if (src.endsWith('.wasm') && !referencedWasm.has(basename(src))) {\n return false;\n }\n if (config.clientJavascriptDisabled && src.endsWith('.js')) return false;\n return true;\n },\n });\n\n // 3. Write _headers file for static asset cache control.\n // Scan for unhashed files so they get per-file Cache-Control rules in the\n // _headers file. On platforms like Cloudflare Workers Static Assets, the\n // worker never sees static file requests — _headers is the only mechanism.\n await writeHeadersFile(publicDir, config, artifacts);\n\n // 4. Copy RSC + SSR server bundles into the output directory. The RSC\n // bundle imports the SSR one by a path the RSC plugin computed between the\n // two *build* directories, which the build names `rsc/` and `ssr/` as\n // siblings (index.ts); deploying them under the same names keeps it valid.\n await cp(artifacts.rsc.path, join(outDir, 'rsc'), { recursive: true });\n await cp(artifacts.ssr.path, join(outDir, 'ssr'), { recursive: true });\n\n // 4b. Copy prebuilt/ flight payloads (cache.component artifacts). These\n // are produced by the post-build capture pass (design/44) and read at\n // request time via the adapter's PrebuiltPayloadSource.\n if (artifacts.prebuilt) {\n await cp(artifacts.prebuilt.path, join(outDir, 'prebuilt'), { recursive: true });\n }\n\n // 5. Write manifest-init module if present.\n if (artifacts.manifestInit) {\n await writeFile(join(outDir, '_timber-manifest-init.js'), artifacts.manifestInit);\n }\n\n return publicDir;\n}\n\n/**\n * Find unhashed static files in the public directory that need per-file\n * Cache-Control rules in the `_headers` file.\n *\n * Excludes:\n * - Files under the build's `immutableDirs` (covered by wildcard rules)\n * - Files under `rsc/` and `ssr/` (server bundles, never served)\n * - Underscore-prefixed files (`_headers`, `_worker.js`, etc.)\n *\n * Ordered for the rule cap: well-known metadata files, then everything\n * else, then files under an underscore-prefixed directory — the\n * framework's own output (unhashed RSC payloads in a static build with\n * client JavaScript disabled, which nothing fetches). Those can number one\n * per route, and must not take the budget from the app's real files.\n *\n * @internal Exported for testing.\n */\n// Well-known metadata files that should be prioritized when capping\n// _headers rules, so they're never dropped in favor of less important files.\nconst PRIORITY_FILES = new Set([\n '/favicon.ico',\n '/robots.txt',\n '/sitemap.xml',\n '/manifest.json',\n '/manifest.webmanifest',\n '/apple-touch-icon.png',\n]);\n\nexport async function findUnhashedStaticFiles(\n publicDir: string,\n immutableDirs: readonly string[]\n): Promise<string[]> {\n let files: string[];\n try {\n files = await collectFiles(publicDir);\n } catch {\n return [];\n }\n\n const priority: string[] = [];\n const rest: string[] = [];\n const framework: string[] = [];\n for (const file of files) {\n const rel = relative(publicDir, file).replace(/\\\\/g, '/');\n if (immutableDirs.some((dir) => rel.startsWith(`${dir}/`))) continue;\n if (rel.startsWith('rsc/') || rel.startsWith('ssr/')) continue;\n if (basename(rel).startsWith('_')) continue;\n const urlPath = '/' + rel;\n if (PRIORITY_FILES.has(urlPath)) {\n priority.push(urlPath);\n } else if (rel.startsWith('_')) {\n framework.push(urlPath);\n } else {\n rest.push(urlPath);\n }\n }\n\n return [...priority.sort(), ...rest.sort(), ...framework.sort()];\n}\n\n/**\n * Scan client JS files for references to .wasm filenames.\n * Returns the set of WASM basenames that are actually imported/referenced\n * by client code and must be preserved in the static output.\n */\nasync function findReferencedWasm(clientDir: string): Promise<Set<string>> {\n const referenced = new Set<string>();\n const files = await collectFiles(clientDir);\n\n const jsFiles = files.filter((f) => f.endsWith('.js'));\n const wasmFiles = files.filter((f) => f.endsWith('.wasm')).map((f) => basename(f));\n if (wasmFiles.length === 0) return referenced;\n\n for (const jsFile of jsFiles) {\n const content = await readFile(jsFile, 'utf-8');\n for (const wasmName of wasmFiles) {\n if (content.includes(wasmName)) {\n referenced.add(wasmName);\n }\n }\n }\n\n return referenced;\n}\n\n/**\n * Build a static-only output directory (no server entry). Copies client\n * assets and pre-rendered HTML/RSC/API files into `outDir/publicDirName`.\n * Used by both Cloudflare and Nitro adapters in `output: 'static'` mode.\n */\nexport async function buildStaticDirectoryOutput(\n config: TimberConfig,\n artifacts: StaticBuildArtifacts,\n outDir: string,\n publicDirName: string\n): Promise<void> {\n // Clean stale artifacts from prior builds (e.g. server-mode builds that\n // left rsc/, ssr/, _worker.js in the outDir). Without this, a static\n // build after a server build inherits 140+ unused server chunks.\n await rm(outDir, { recursive: true, force: true }).catch(() => {});\n await mkdir(outDir, { recursive: true });\n\n const publicDir = join(outDir, publicDirName);\n await mkdir(publicDir, { recursive: true });\n\n // Copy client assets (JS, CSS, fonts, images).\n await cp(artifacts.client.path, publicDir, {\n recursive: true,\n filter: (src: string) => {\n if (config.clientJavascriptDisabled && src.endsWith('.js')) return false;\n return true;\n },\n });\n\n // Copy pre-rendered static pages (HTML + RSC flight + API routes).\n //\n // This is the one place the build merges two independently-produced trees\n // into a single directory, and `cp` resolves an overlap by overwriting with\n // no diagnostic — the deployment then contains one of the two artifacts and\n // nothing recorded which. Refuse instead (TIM-1266).\n await assertNoTreeCollision(artifacts.pages.path, publicDir);\n await cp(artifacts.pages.path, publicDir, { recursive: true });\n}\n\n/**\n * Write the `_headers` file, folding in the user's `public/_headers`.\n *\n * Every adapter used to `writeFile` a generated `_headers` over whatever\n * Vite had copied out of `public/`, so an app shipping its own CSP, CORS, or\n * cache rules deployed without them and without a word (TIM-1326). The\n * generated rules and the user's are not competitors — they address different\n * paths — so this merges rather than refusing, the way `_redirects` has since\n * TIM-1249.\n *\n * **Read from the project, not the output.** The generated file lands under\n * the same name in the output directory, and `runSharedBuildSteps` does not\n * clean `outDir`; a reader aimed there would fold the previous build's\n * generated rules back in and compound them on every rebuild — the defect\n * this pass fixed for `_redirects`.\n *\n * User rules go last. On Cloudflare and Netlify a `_headers` file applies\n * every matching rule, so appending means the user's rules take effect; where\n * a platform resolves a conflict in favour of the earlier rule instead, the\n * framework keeps the paths it owns and the user keeps the rest. Under either\n * reading this is no worse than the previous behaviour, which was to drop the\n * user's rules entirely.\n *\n * @internal Exported for testing.\n */\nexport async function writeHeadersFile(\n dir: string,\n config: TimberConfig,\n artifacts: BuildArtifacts\n): Promise<void> {\n const userRules = await readUserPlatformFile(config.root, HEADERS_FILE);\n await writeFile(\n join(dir, HEADERS_FILE),\n generateHeadersFile({\n base: adapterBase(config),\n immutableDirs: artifacts.immutableDirs,\n // Scanned from the directory being deployed, which holds everything\n // the platform will serve from it.\n unhashedPaths: await findUnhashedStaticFiles(dir, artifacts.immutableDirs),\n contentTypes: artifacts.output === 'static' ? artifacts.contentTypes : undefined,\n userRules: userRules ?? undefined,\n })\n );\n}\n\n/**\n * Read a user-authored platform file from the project's `public/` directory.\n * Returns null when the project has none, or when no root is configured —\n * a caller without a root cannot locate the project at all, and inventing\n * one from `process.cwd()` would read a different project's file.\n */\nasync function readUserPlatformFile(\n root: string | undefined,\n name: string\n): Promise<string | null> {\n if (!root) return null;\n try {\n return await readFile(join(root, USER_PLATFORM_DIR, name), 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Throw if copying `srcDir` over `destDir` would overwrite an existing file.\n *\n * Compared against the destination **as it stands**, not against the other\n * source tree: the first copy is filtered (client JS is dropped when client\n * JavaScript is disabled), so the files that are actually there are the only\n * ones a second copy can clobber.\n *\n * @internal Exported for testing.\n */\nexport async function assertNoTreeCollision(srcDir: string, destDir: string): Promise<void> {\n const [srcFiles, destFiles, identity] = await Promise.all([\n collectFiles(srcDir).catch(() => [] as string[]),\n collectFiles(destDir).catch(() => [] as string[]),\n // `cp` will resolve these paths the way the destination filesystem does,\n // so the comparison predicting it has to as well: on macOS a hand-written\n // `public/About/index.html` and a generated `about/index.html` are one\n // file, and an exact-string set waves the overwrite through (TIM-1266).\n detectFsIdentity(destDir),\n ]);\n\n const key = (p: string) => fsKey(p, identity);\n const existing = new Set(destFiles.map((f) => key(relative(destDir, f).replace(/\\\\/g, '/'))));\n const exempt = new Set(USER_MERGED_PLATFORM_FILES.map(key));\n const collisions = srcFiles\n .map((f) => relative(srcDir, f).replace(/\\\\/g, '/'))\n .filter((rel) => existing.has(key(rel)) && !exempt.has(key(rel)))\n .sort();\n\n if (collisions.length === 0) return;\n\n throw new Error(\n `[timber] Build output: ${collisions.length} file(s) in the pre-rendered site ` +\n `collide with files already in the output directory. Copying would silently ` +\n `overwrite them — a generated page and a file in public/ cannot share a path:\\n` +\n collisions.map((c) => ` - ${c}`).join('\\n')\n );\n}\n\nasync function collectFiles(dir: string): Promise<string[]> {\n const result: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n result.push(...(await collectFiles(fullPath)));\n } else {\n result.push(fullPath);\n }\n }\n return result;\n}\n"],"mappings":"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"}
@@ -1,10 +1,33 @@
1
- import { D as getWaitUntil } from "./primitives-DLAnvsrk.js";
2
- import { _ as addSpanEventSync, d as logSwrRefetchFailed, h as swallow } from "./logger-k2DQ4EUf.js";
1
+ import { l as waitUntilAls } from "./als-registry-DaxkVjt5.js";
2
+ import { E as addSpanEventSync, _ as swallow, p as logSwrRefetchFailed } from "./logger-DiDt5ppH.js";
3
3
  import { t as fnv1aHash } from "./fast-hash-C-tVYrLb.js";
4
- import { n as createSingleflight } from "./singleflight-2lUWfcAk.js";
5
- import { t as estimateByteSize } from "./sizeof-lXffQ1Vr.js";
6
- import { t as warnLossyJsonValue } from "./json-lossy-check-ClNvBM_3.js";
4
+ import { n as createSingleflight } from "./singleflight-BeVMMKi0.js";
5
+ import { t as estimateByteSize } from "./sizeof-UwzwB1uM.js";
6
+ import { t as warnLossyJsonValue } from "./json-lossy-check-ip0Qi0MT.js";
7
7
  import { t as getCdnPurgeHandler } from "./purge-store-Byr8XOjU.js";
8
+ //#region src/server/waituntil-bridge.ts
9
+ /**
10
+ * Per-request waitUntil bridge — ALS bridge for platform adapters.
11
+ *
12
+ * The generated entry point (Nitro, Cloudflare) wraps the handler with
13
+ * `runWithWaitUntil`, binding the platform's lifecycle extension function
14
+ * (e.g., h3's `event.waitUntil()` or CF's `ctx.waitUntil()`) for the
15
+ * request duration. The `waitUntil()` primitive reads from this ALS to
16
+ * dispatch background work to the correct platform API.
17
+ *
18
+ * Design doc: design/11-platform.md §"waitUntil()"
19
+ */
20
+ /**
21
+ * Get the current request's waitUntil function, if available.
22
+ *
23
+ * Returns undefined when no platform adapter has installed a waitUntil
24
+ * handler for the current request (e.g., on platforms that don't support
25
+ * lifecycle extension, or outside a request context).
26
+ */
27
+ function getWaitUntil() {
28
+ return waitUntilAls.getStore();
29
+ }
30
+ //#endregion
8
31
  //#region src/cache/stable-stringify.ts
9
32
  /**
10
33
  * Deterministic JSON serialization with sorted object keys.
@@ -479,10 +502,22 @@ var RedisCacheHandler = class {
479
502
  var DATA_PREFIX = "d:";
480
503
  var TAG_SET_PREFIX = "ts:";
481
504
  var TAG_VERSION_PREFIX = "tv:";
505
+ function isNativeStore(store) {
506
+ return !!(store.setWithTags && store.invalidateTag);
507
+ }
508
+ function isEagerStore(store) {
509
+ return !!(store.sadd && store.smembers && store.srem && store.sdel);
510
+ }
482
511
  function detectStrategy(store) {
483
- if (store.setWithTags && store.invalidateTag) return "native";
484
- if (store.sadd && store.smembers && store.srem && store.sdel) return "eager";
485
- return "lazy";
512
+ if (isNativeStore(store)) return {
513
+ kind: "native",
514
+ store
515
+ };
516
+ if (isEagerStore(store)) return {
517
+ kind: "eager",
518
+ store
519
+ };
520
+ return { kind: "lazy" };
486
521
  }
487
522
  var TagAwareCacheHandler = class {
488
523
  store;
@@ -512,7 +547,7 @@ var TagAwareCacheHandler = class {
512
547
  async get(key) {
513
548
  const raw = await this.store.get(this.dataKey(key));
514
549
  if (raw === null) return null;
515
- if (this.strategy === "native" || this.strategy === "eager") {
550
+ if (this.strategy.kind !== "lazy") {
516
551
  const entry = JSON.parse(raw);
517
552
  const stale = Date.now() > entry.expiresAt;
518
553
  return {
@@ -536,25 +571,26 @@ var TagAwareCacheHandler = class {
536
571
  }
537
572
  async set(key, value, opts) {
538
573
  const physicalTtl = Math.max(opts.ttl * 2 + 60, 120);
539
- if (this.strategy === "native") {
574
+ const strategy = this.strategy;
575
+ if (strategy.kind === "native") {
540
576
  const entry = {
541
577
  value,
542
578
  expiresAt: Date.now() + opts.ttl * 1e3,
543
579
  tags: opts.tags
544
580
  };
545
581
  const payload = JSON.stringify(entry);
546
- if (opts.tags.length > 0) await this.store.setWithTags(this.dataKey(key), payload, physicalTtl, this.prefixTags(opts.tags));
582
+ if (opts.tags.length > 0) await strategy.store.setWithTags(this.dataKey(key), payload, physicalTtl, this.prefixTags(opts.tags));
547
583
  else await this.store.set(this.dataKey(key), payload, physicalTtl);
548
584
  return;
549
585
  }
550
- if (this.strategy === "eager") {
586
+ if (strategy.kind === "eager") {
551
587
  const entry = {
552
588
  value,
553
589
  expiresAt: Date.now() + opts.ttl * 1e3,
554
590
  tags: opts.tags
555
591
  };
556
592
  await this.store.set(this.dataKey(key), JSON.stringify(entry), physicalTtl);
557
- if (opts.tags.length > 0) await Promise.all(opts.tags.map((tag) => this.store.sadd(this.tagSetKey(tag), [key], physicalTtl)));
593
+ if (opts.tags.length > 0) await Promise.all(opts.tags.map((tag) => strategy.store.sadd(this.tagSetKey(tag), [key], physicalTtl)));
558
594
  return;
559
595
  }
560
596
  const tagVersions = opts.tags.length > 0 ? await this.getTagVersions(opts.tags) : {};
@@ -567,31 +603,27 @@ var TagAwareCacheHandler = class {
567
603
  await this.store.set(this.dataKey(key), JSON.stringify(entry), physicalTtl);
568
604
  }
569
605
  async invalidate(opts) {
606
+ const strategy = this.strategy;
570
607
  if (opts.key) {
571
- if (this.strategy === "eager") {
572
- const raw = await this.store.get(this.dataKey(opts.key));
608
+ const key = opts.key;
609
+ if (strategy.kind === "eager") {
610
+ const raw = await this.store.get(this.dataKey(key));
573
611
  if (raw !== null) {
574
612
  const entry = JSON.parse(raw);
575
- if (entry.tags.length > 0) await Promise.all(entry.tags.map((tag) => this.store.srem(this.tagSetKey(tag), [opts.key])));
613
+ if (entry.tags.length > 0) await Promise.all(entry.tags.map((tag) => strategy.store.srem(this.tagSetKey(tag), [key])));
576
614
  }
577
615
  }
578
- await this.store.del(this.dataKey(opts.key));
616
+ await this.store.del(this.dataKey(key));
579
617
  }
580
618
  if (opts.tag) {
581
619
  const tag = opts.tag;
582
- if (this.strategy === "native") await this.store.invalidateTag(`${this.prefix}${tag}`);
583
- else if (this.strategy === "eager") {
584
- const members = await this.store.smembers(this.tagSetKey(tag));
620
+ if (strategy.kind === "native") await strategy.store.invalidateTag(`${this.prefix}${tag}`);
621
+ else if (strategy.kind === "eager") {
622
+ const members = await strategy.store.smembers(this.tagSetKey(tag));
585
623
  await Promise.all(members.map(async (k) => {
586
624
  const raw = await this.store.get(this.dataKey(k));
587
- if (raw === null) {
588
- await this.store.srem(this.tagSetKey(tag), [k]);
589
- return;
590
- }
591
- if (JSON.parse(raw).tags.includes(tag)) {
592
- await this.store.del(this.dataKey(k));
593
- await this.store.srem(this.tagSetKey(tag), [k]);
594
- } else await this.store.srem(this.tagSetKey(tag), [k]);
625
+ if (raw !== null && JSON.parse(raw).tags.includes(tag)) await this.store.del(this.dataKey(k));
626
+ await strategy.store.srem(this.tagSetKey(tag), [k]);
595
627
  }));
596
628
  } else await this.bumpTagVersion(opts.tag);
597
629
  }
@@ -729,8 +761,8 @@ var DEPLOYMENT_ID_HEADER = "X-Timber-Deployment-Id";
729
761
  /** Response header that signals the client to do a full page reload. */
730
762
  var RELOAD_HEADER = "X-Timber-Reload";
731
763
  /**
732
- * The current build's deployment ID. Set at startup from the manifest init
733
- * module (globalThis.__TIMBER_DEPLOYMENT_ID__). Null in dev mode.
764
+ * The current build's deployment ID. Set at startup from the runtime config
765
+ * (`virtual:timber-config`'s `deploymentId`). Null in dev mode.
734
766
  */
735
767
  var currentDeploymentId = null;
736
768
  /**
@@ -1145,6 +1177,6 @@ var cache = {
1145
1177
  }
1146
1178
  };
1147
1179
  //#endregion
1148
- export { setDefaultSingleflightTimeout as _, getManifestEntry as a, wasInvalidatedSince as b, lookupPrebuiltPayload as c, checkVersionSkew as d, MemoryCacheHandler as f, setCacheHandler as g, getCacheHandler as h, storeOverlayEntry as i, setPrebuiltPayloadSource as l, RedisCacheHandler as m, lookupOverlay as n, hasPrebuiltPayloadSource as o, TagAwareCacheHandler as p, overlayKey as r, isParamIndependent as s, cache as t, applyReloadHeaders as u, currentInvalidationEpoch as v, lastInvalidationEpochFor as y };
1180
+ export { setDefaultSingleflightTimeout as _, getManifestEntry as a, wasInvalidatedSince as b, lookupPrebuiltPayload as c, checkVersionSkew as d, MemoryCacheHandler as f, setCacheHandler as g, getCacheHandler as h, storeOverlayEntry as i, setPrebuiltPayloadSource as l, RedisCacheHandler as m, lookupOverlay as n, hasPrebuiltPayloadSource as o, TagAwareCacheHandler as p, overlayKey as r, isParamIndependent as s, cache as t, applyReloadHeaders as u, currentInvalidationEpoch as v, getWaitUntil as x, lastInvalidationEpochFor as y };
1149
1181
 
1150
- //# sourceMappingURL=cache-api-CUD9Ezaq.js.map
1182
+ //# sourceMappingURL=cache-api-CR23J_NC.js.map