@timber-js/app 0.2.0-alpha.185 → 0.2.0-alpha.187

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 (570) hide show
  1. package/dist/_chunks/{actions-O_LsyCE4.js → actions-35jnMdeJ.js} +4 -3
  2. package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-35jnMdeJ.js.map} +1 -1
  3. package/dist/_chunks/als-registry-C6kcfprT.js +41 -0
  4. package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -0
  5. package/dist/_chunks/als-slots-BEEIPKYm.js +26 -0
  6. package/dist/_chunks/als-slots-BEEIPKYm.js.map +1 -0
  7. package/dist/_chunks/base-path-DaQrzbez.js +80 -0
  8. package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
  9. package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
  10. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  11. package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
  12. package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
  13. package/dist/_chunks/{cache-api-B-lhk9p4.js → cache-api-DjNrIWRR.js} +8 -14
  14. package/dist/_chunks/cache-api-DjNrIWRR.js.map +1 -0
  15. package/dist/_chunks/cli-check-CpmN7Nh-.js +256 -0
  16. package/dist/_chunks/cli-check-CpmN7Nh-.js.map +1 -0
  17. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js +298 -0
  18. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js.map +1 -0
  19. package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-CGP6BZKO.js} +92 -14
  20. package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-CGP6BZKO.js.map} +1 -1
  21. package/dist/_chunks/convention-lint-kXsgc_-7.js +784 -0
  22. package/dist/_chunks/convention-lint-kXsgc_-7.js.map +1 -0
  23. package/dist/_chunks/error-boundary-D-ODYX41.js +353 -0
  24. package/dist/_chunks/error-boundary-D-ODYX41.js.map +1 -0
  25. package/dist/_chunks/{fast-hash-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
  26. package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
  27. package/dist/_chunks/file-cache-DmX7OqZP.js +454 -0
  28. package/dist/_chunks/file-cache-DmX7OqZP.js.map +1 -0
  29. package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
  30. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
  31. package/dist/_chunks/{logger-AWfuX-KJ.js → logger-D8xJZXIN.js} +34 -51
  32. package/dist/_chunks/logger-D8xJZXIN.js.map +1 -0
  33. package/dist/_chunks/mdx-file-C005ay-P.js +25 -0
  34. package/dist/_chunks/mdx-file-C005ay-P.js.map +1 -0
  35. package/dist/_chunks/{plugin-context---kTF5v8.js → plugin-context-rCinWLiE.js} +8 -2
  36. package/dist/_chunks/plugin-context-rCinWLiE.js.map +1 -0
  37. package/dist/_chunks/purge-store-Byr8XOjU.js +14 -0
  38. package/dist/_chunks/purge-store-Byr8XOjU.js.map +1 -0
  39. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js → resolve-schema-5ma5pp1b.js} +2 -2
  40. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js.map → resolve-schema-5ma5pp1b.js.map} +1 -1
  41. package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
  42. package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
  43. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
  44. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
  45. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
  46. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
  47. package/dist/_chunks/rsc-media-type-DRqE_lD_.js +46 -0
  48. package/dist/_chunks/rsc-media-type-DRqE_lD_.js.map +1 -0
  49. package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
  50. package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
  51. package/dist/_chunks/scanner-C8b0Gcw3.js +1564 -0
  52. package/dist/_chunks/scanner-C8b0Gcw3.js.map +1 -0
  53. package/dist/_chunks/schema-bridge-Cc2Gngu1.js +199 -0
  54. package/dist/_chunks/schema-bridge-Cc2Gngu1.js.map +1 -0
  55. package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
  56. package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -0
  57. package/dist/_chunks/segment-context-CjOlyB8Y.js +97 -0
  58. package/dist/_chunks/segment-context-CjOlyB8Y.js.map +1 -0
  59. package/dist/_chunks/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
  60. package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
  61. package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
  62. package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
  63. package/dist/_chunks/{ssr-data-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
  64. package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
  65. package/dist/_chunks/{use-query-states-DFvWd-EA.js → use-query-states-BbU5Ge1V.js} +74 -26
  66. package/dist/_chunks/use-query-states-BbU5Ge1V.js.map +1 -0
  67. package/dist/_chunks/use-segment-params-C4r4BD9T.js +398 -0
  68. package/dist/_chunks/use-segment-params-C4r4BD9T.js.map +1 -0
  69. package/dist/_chunks/walkers-RzN6AFjr.js +141 -0
  70. package/dist/_chunks/walkers-RzN6AFjr.js.map +1 -0
  71. package/dist/adapters/build-output-helper.d.ts +37 -0
  72. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare-dev.js +1 -1
  74. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  75. package/dist/adapters/cloudflare.d.ts.map +1 -1
  76. package/dist/adapters/cloudflare.js +1 -1
  77. package/dist/adapters/compress-module.d.ts +12 -0
  78. package/dist/adapters/compress-module.d.ts.map +1 -1
  79. package/dist/adapters/fs-identity.d.ts +64 -0
  80. package/dist/adapters/fs-identity.d.ts.map +1 -0
  81. package/dist/adapters/nitro.d.ts.map +1 -1
  82. package/dist/adapters/nitro.js +56 -5
  83. package/dist/adapters/nitro.js.map +1 -1
  84. package/dist/adapters/shared.d.ts +57 -1
  85. package/dist/adapters/shared.d.ts.map +1 -1
  86. package/dist/adapters/types.d.ts +13 -1
  87. package/dist/adapters/types.d.ts.map +1 -1
  88. package/dist/cache/fast-hash.d.ts +5 -0
  89. package/dist/cache/fast-hash.d.ts.map +1 -1
  90. package/dist/cache/index.js +1 -1
  91. package/dist/cdn/cloudflare-purge.js +30 -0
  92. package/dist/cdn/cloudflare-purge.js.map +1 -0
  93. package/dist/cdn/fastly-purge.js +33 -0
  94. package/dist/cdn/fastly-purge.js.map +1 -0
  95. package/dist/cdn/index.js +94 -0
  96. package/dist/cdn/index.js.map +1 -0
  97. package/dist/cdn/workers-cache-purge.js +35 -0
  98. package/dist/cdn/workers-cache-purge.js.map +1 -0
  99. package/dist/cli-check.d.ts +153 -0
  100. package/dist/cli-check.d.ts.map +1 -0
  101. package/dist/cli.d.ts +34 -8
  102. package/dist/cli.d.ts.map +1 -1
  103. package/dist/cli.js +46 -21
  104. package/dist/cli.js.map +1 -1
  105. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  106. package/dist/client/browser-entry/hydrate.d.ts +20 -9
  107. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  108. package/dist/client/browser-entry/index.d.ts +1 -1
  109. package/dist/client/browser-entry/index.d.ts.map +1 -1
  110. package/dist/client/browser-entry/post-hydration.d.ts +4 -1
  111. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  112. package/dist/client/browser-entry/router-init.d.ts +3 -0
  113. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  114. package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
  115. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
  116. package/dist/client/error-boundary.d.ts +7 -0
  117. package/dist/client/error-boundary.d.ts.map +1 -1
  118. package/dist/client/error-boundary.js +1 -162
  119. package/dist/client/history.d.ts +13 -6
  120. package/dist/client/history.d.ts.map +1 -1
  121. package/dist/client/index.d.ts +1 -0
  122. package/dist/client/index.d.ts.map +1 -1
  123. package/dist/client/index.js +42 -41
  124. package/dist/client/index.js.map +1 -1
  125. package/dist/client/internal.d.ts +4 -3
  126. package/dist/client/internal.d.ts.map +1 -1
  127. package/dist/client/internal.js +877 -311
  128. package/dist/client/internal.js.map +1 -1
  129. package/dist/client/link.d.ts +1 -7
  130. package/dist/client/link.d.ts.map +1 -1
  131. package/dist/client/navigation-api.d.ts +2 -2
  132. package/dist/client/navigation-commit.d.ts +87 -0
  133. package/dist/client/navigation-commit.d.ts.map +1 -0
  134. package/dist/client/navigation-context.d.ts +37 -20
  135. package/dist/client/navigation-context.d.ts.map +1 -1
  136. package/dist/client/navigation-root.d.ts +63 -23
  137. package/dist/client/navigation-root.d.ts.map +1 -1
  138. package/dist/client/params-context.d.ts +81 -0
  139. package/dist/client/params-context.d.ts.map +1 -0
  140. package/dist/client/router-effects.d.ts +129 -0
  141. package/dist/client/router-effects.d.ts.map +1 -0
  142. package/dist/client/router-lifecycle.d.ts +55 -0
  143. package/dist/client/router-lifecycle.d.ts.map +1 -0
  144. package/dist/client/router-pipeline.d.ts +84 -0
  145. package/dist/client/router-pipeline.d.ts.map +1 -0
  146. package/dist/client/router-ref.d.ts +1 -1
  147. package/dist/client/router-ref.d.ts.map +1 -1
  148. package/dist/client/router-skew.d.ts +21 -0
  149. package/dist/client/router-skew.d.ts.map +1 -0
  150. package/dist/client/router-types.d.ts +207 -0
  151. package/dist/client/router-types.d.ts.map +1 -0
  152. package/dist/client/router.d.ts +1 -182
  153. package/dist/client/router.d.ts.map +1 -1
  154. package/dist/client/rsc-fetch.d.ts +47 -26
  155. package/dist/client/rsc-fetch.d.ts.map +1 -1
  156. package/dist/client/segment-cache.d.ts +87 -34
  157. package/dist/client/segment-cache.d.ts.map +1 -1
  158. package/dist/client/ssr-data.d.ts +6 -0
  159. package/dist/client/ssr-data.d.ts.map +1 -1
  160. package/dist/client/stale-client.d.ts +69 -0
  161. package/dist/client/stale-client.d.ts.map +1 -0
  162. package/dist/client/state.d.ts +10 -1
  163. package/dist/client/state.d.ts.map +1 -1
  164. package/dist/client/top-loader.d.ts +2 -1
  165. package/dist/client/top-loader.d.ts.map +1 -1
  166. package/dist/client/unload-guard.d.ts +5 -0
  167. package/dist/client/unload-guard.d.ts.map +1 -1
  168. package/dist/client/use-cookie.d.ts.map +1 -1
  169. package/dist/client/use-query-states.d.ts +9 -3
  170. package/dist/client/use-query-states.d.ts.map +1 -1
  171. package/dist/client/use-router.d.ts +1 -1
  172. package/dist/client/use-segment-params.d.ts +18 -8
  173. package/dist/client/use-segment-params.d.ts.map +1 -1
  174. package/dist/codec.js +1 -1
  175. package/dist/cookies/define-cookie.d.ts.map +1 -1
  176. package/dist/cookies/index.js +5 -5
  177. package/dist/cookies/index.js.map +1 -1
  178. package/dist/index.d.ts +4 -1
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js +1009 -759
  181. package/dist/index.js.map +1 -1
  182. package/dist/params/index.js +1 -1
  183. package/dist/plugin-context.d.ts +46 -0
  184. package/dist/plugin-context.d.ts.map +1 -1
  185. package/dist/plugins/adapter-build.d.ts.map +1 -1
  186. package/dist/plugins/build-manifest.d.ts +1 -1
  187. package/dist/plugins/build-manifest.d.ts.map +1 -1
  188. package/dist/plugins/entries.d.ts.map +1 -1
  189. package/dist/plugins/fonts.d.ts.map +1 -1
  190. package/dist/plugins/request-dep/analysis.d.ts +106 -0
  191. package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
  192. package/dist/plugins/request-dep/index.d.ts +75 -0
  193. package/dist/plugins/request-dep/index.d.ts.map +1 -0
  194. package/dist/plugins/request-dep/origin.d.ts +61 -0
  195. package/dist/plugins/request-dep/origin.d.ts.map +1 -0
  196. package/dist/plugins/routing.d.ts.map +1 -1
  197. package/dist/plugins/shims.d.ts.map +1 -1
  198. package/dist/plugins/static-build.d.ts +160 -8
  199. package/dist/plugins/static-build.d.ts.map +1 -1
  200. package/dist/routing/codegen-shared.d.ts +3 -44
  201. package/dist/routing/codegen-shared.d.ts.map +1 -1
  202. package/dist/routing/codegen-types.d.ts +28 -31
  203. package/dist/routing/codegen-types.d.ts.map +1 -1
  204. package/dist/routing/codegen-write.d.ts +51 -0
  205. package/dist/routing/codegen-write.d.ts.map +1 -0
  206. package/dist/routing/codegen.d.ts.map +1 -1
  207. package/dist/routing/collision-probe.d.ts +104 -0
  208. package/dist/routing/collision-probe.d.ts.map +1 -0
  209. package/dist/routing/collision-spaces.d.ts +26 -0
  210. package/dist/routing/collision-spaces.d.ts.map +1 -0
  211. package/dist/routing/convention-lint.d.ts +18 -4
  212. package/dist/routing/convention-lint.d.ts.map +1 -1
  213. package/dist/routing/export-detect.d.ts +16 -0
  214. package/dist/routing/export-detect.d.ts.map +1 -1
  215. package/dist/routing/index.js +4 -3
  216. package/dist/routing/interception.d.ts +235 -6
  217. package/dist/routing/interception.d.ts.map +1 -1
  218. package/dist/routing/link-codegen.d.ts +19 -4
  219. package/dist/routing/link-codegen.d.ts.map +1 -1
  220. package/dist/routing/manifest-codegen.d.ts +1 -7
  221. package/dist/routing/manifest-codegen.d.ts.map +1 -1
  222. package/dist/routing/scanner.d.ts.map +1 -1
  223. package/dist/routing/segment-classify.d.ts +33 -0
  224. package/dist/routing/segment-classify.d.ts.map +1 -1
  225. package/dist/routing/segment-keys.d.ts +95 -0
  226. package/dist/routing/segment-keys.d.ts.map +1 -0
  227. package/dist/routing/slot-placement.d.ts +48 -0
  228. package/dist/routing/slot-placement.d.ts.map +1 -0
  229. package/dist/routing/types.d.ts +0 -6
  230. package/dist/routing/types.d.ts.map +1 -1
  231. package/dist/routing/walkers.d.ts +6 -0
  232. package/dist/routing/walkers.d.ts.map +1 -1
  233. package/dist/schema-bridge.d.ts +60 -9
  234. package/dist/schema-bridge.d.ts.map +1 -1
  235. package/dist/search-params/define.d.ts +62 -14
  236. package/dist/search-params/define.d.ts.map +1 -1
  237. package/dist/search-params/index.d.ts +0 -1
  238. package/dist/search-params/index.d.ts.map +1 -1
  239. package/dist/search-params/index.js +221 -10
  240. package/dist/search-params/index.js.map +1 -1
  241. package/dist/search-params/parse-total.d.ts +70 -0
  242. package/dist/search-params/parse-total.d.ts.map +1 -0
  243. package/dist/search-params/wrappers.d.ts +26 -3
  244. package/dist/search-params/wrappers.d.ts.map +1 -1
  245. package/dist/server/access-gate.d.ts +19 -8
  246. package/dist/server/access-gate.d.ts.map +1 -1
  247. package/dist/server/action-handler.d.ts.map +1 -1
  248. package/dist/server/actions.d.ts +6 -3
  249. package/dist/server/actions.d.ts.map +1 -1
  250. package/dist/server/als-registry.d.ts +18 -1
  251. package/dist/server/als-registry.d.ts.map +1 -1
  252. package/dist/server/build-manifest.d.ts +13 -1
  253. package/dist/server/build-manifest.d.ts.map +1 -1
  254. package/dist/server/chain-url-parts.d.ts +82 -0
  255. package/dist/server/chain-url-parts.d.ts.map +1 -0
  256. package/dist/server/children-interception.d.ts +49 -0
  257. package/dist/server/children-interception.d.ts.map +1 -0
  258. package/dist/server/compress.d.ts.map +1 -1
  259. package/dist/server/default-status-page.d.ts +45 -0
  260. package/dist/server/default-status-page.d.ts.map +1 -0
  261. package/dist/server/deny-boundary.d.ts +148 -15
  262. package/dist/server/deny-boundary.d.ts.map +1 -1
  263. package/dist/server/deny-renderer.d.ts +15 -4
  264. package/dist/server/deny-renderer.d.ts.map +1 -1
  265. package/dist/server/error-boundary-wrapper.d.ts +85 -15
  266. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  267. package/dist/server/head-response.d.ts +35 -0
  268. package/dist/server/head-response.d.ts.map +1 -0
  269. package/dist/server/index.d.ts +0 -1
  270. package/dist/server/index.d.ts.map +1 -1
  271. package/dist/server/index.js +3 -2
  272. package/dist/server/index.js.map +1 -1
  273. package/dist/server/internal.d.ts +3 -1
  274. package/dist/server/internal.d.ts.map +1 -1
  275. package/dist/server/internal.js +712 -418
  276. package/dist/server/internal.js.map +1 -1
  277. package/dist/server/metadata-collector.d.ts +52 -0
  278. package/dist/server/metadata-collector.d.ts.map +1 -0
  279. package/dist/server/param-coercion.d.ts +22 -6
  280. package/dist/server/param-coercion.d.ts.map +1 -1
  281. package/dist/server/pipeline-helpers.d.ts +0 -18
  282. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  283. package/dist/server/pipeline-interception.d.ts +59 -9
  284. package/dist/server/pipeline-interception.d.ts.map +1 -1
  285. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  286. package/dist/server/pipeline-phases.d.ts.map +1 -1
  287. package/dist/server/pipeline.d.ts +11 -0
  288. package/dist/server/pipeline.d.ts.map +1 -1
  289. package/dist/server/primitives.d.ts +23 -0
  290. package/dist/server/primitives.d.ts.map +1 -1
  291. package/dist/server/publish-params.d.ts +33 -0
  292. package/dist/server/publish-params.d.ts.map +1 -0
  293. package/dist/server/request-context.d.ts +48 -0
  294. package/dist/server/request-context.d.ts.map +1 -1
  295. package/dist/server/route-element-builder.d.ts +22 -3
  296. package/dist/server/route-element-builder.d.ts.map +1 -1
  297. package/dist/server/route-handler.d.ts.map +1 -1
  298. package/dist/server/route-matcher.d.ts +13 -0
  299. package/dist/server/route-matcher.d.ts.map +1 -1
  300. package/dist/server/rsc-cache-key-guard.d.ts +78 -0
  301. package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
  302. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  303. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  304. package/dist/server/rsc-entry/error-renderer.d.ts +15 -3
  305. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  306. package/dist/server/rsc-entry/helpers.d.ts +2 -17
  307. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  308. package/dist/server/rsc-entry/index.d.ts +0 -1
  309. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  310. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  311. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  312. package/dist/server/rsc-entry/rsc-payload.d.ts +1 -2
  313. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  314. package/dist/server/rsc-entry/rsc-stream.d.ts +15 -2
  315. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  316. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  317. package/dist/server/skippable-prefix.d.ts +23 -0
  318. package/dist/server/skippable-prefix.d.ts.map +1 -0
  319. package/dist/server/slot-interception.d.ts +80 -0
  320. package/dist/server/slot-interception.d.ts.map +1 -0
  321. package/dist/server/slot-resolver.d.ts +70 -8
  322. package/dist/server/slot-resolver.d.ts.map +1 -1
  323. package/dist/server/ssr-bridge-types.d.ts +17 -0
  324. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  325. package/dist/server/ssr-entry.d.ts +0 -1
  326. package/dist/server/ssr-entry.d.ts.map +1 -1
  327. package/dist/server/ssr-wrappers.d.ts +24 -13
  328. package/dist/server/ssr-wrappers.d.ts.map +1 -1
  329. package/dist/server/state-tree-diff.d.ts +6 -27
  330. package/dist/server/state-tree-diff.d.ts.map +1 -1
  331. package/dist/server/static-generator.d.ts +6 -0
  332. package/dist/server/static-generator.d.ts.map +1 -1
  333. package/dist/server/static-not-found.d.ts +52 -0
  334. package/dist/server/static-not-found.d.ts.map +1 -0
  335. package/dist/server/status-code-resolver.d.ts +8 -1
  336. package/dist/server/status-code-resolver.d.ts.map +1 -1
  337. package/dist/server/tree-builder.d.ts +28 -36
  338. package/dist/server/tree-builder.d.ts.map +1 -1
  339. package/dist/server/types.d.ts +12 -7
  340. package/dist/server/types.d.ts.map +1 -1
  341. package/dist/server/utils/element-type.d.ts +40 -0
  342. package/dist/server/utils/element-type.d.ts.map +1 -0
  343. package/dist/shared/als-slots.d.ts +41 -0
  344. package/dist/shared/als-slots.d.ts.map +1 -0
  345. package/dist/shared/base-path.d.ts +56 -0
  346. package/dist/shared/base-path.d.ts.map +1 -0
  347. package/dist/shared/param-value.d.ts +80 -0
  348. package/dist/shared/param-value.d.ts.map +1 -0
  349. package/dist/shared/payload-root.d.ts +108 -0
  350. package/dist/shared/payload-root.d.ts.map +1 -0
  351. package/dist/shared/rsc-cache-key.d.ts +163 -0
  352. package/dist/shared/rsc-cache-key.d.ts.map +1 -0
  353. package/dist/shared/rsc-error-envelope.d.ts +25 -0
  354. package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
  355. package/dist/shared/rsc-manifest.d.ts +28 -0
  356. package/dist/shared/rsc-manifest.d.ts.map +1 -0
  357. package/dist/shared/rsc-media-type.d.ts +40 -0
  358. package/dist/shared/rsc-media-type.d.ts.map +1 -0
  359. package/dist/shared/rsc-payload-path.d.ts +42 -0
  360. package/dist/shared/rsc-payload-path.d.ts.map +1 -0
  361. package/dist/shared/segment-info.d.ts +59 -0
  362. package/dist/shared/segment-info.d.ts.map +1 -0
  363. package/dist/shared/slot-params.d.ts +51 -0
  364. package/dist/shared/slot-params.d.ts.map +1 -0
  365. package/dist/shared/static-platform-files.d.ts +71 -0
  366. package/dist/shared/static-platform-files.d.ts.map +1 -0
  367. package/docs/api/30-api-server.mdx +1 -1
  368. package/docs/api/31-api-client.mdx +4 -2
  369. package/docs/api/33-api-search-params.mdx +38 -16
  370. package/docs/api/35-api-typescript.mdx +3 -3
  371. package/docs/api/36-cli.mdx +34 -7
  372. package/docs/learn/00-introduction.mdx +1 -1
  373. package/docs/learn/02-pages-and-layouts.mdx +2 -2
  374. package/docs/learn/05-typed-params.mdx +8 -8
  375. package/docs/learn/07-typed-routes.mdx +12 -7
  376. package/docs/learn/11-error-handling.mdx +18 -0
  377. package/docs/learn/12-client-navigation.mdx +2 -2
  378. package/docs/learn/14-deploying.mdx +23 -0
  379. package/docs/more/01-advanced-routing.mdx +173 -3
  380. package/docs/more/03-coming-from-nextjs.mdx +2 -2
  381. package/docs/more/04-metadata-and-fonts.mdx +1 -1
  382. package/docs/more/50-ai-agent-instructions.mdx +6 -4
  383. package/package.json +9 -6
  384. package/src/adapters/build-output-helper.ts +116 -3
  385. package/src/adapters/cloudflare.ts +90 -12
  386. package/src/adapters/compress-module.ts +79 -1
  387. package/src/adapters/fs-identity.ts +156 -0
  388. package/src/adapters/nitro.ts +6 -6
  389. package/src/adapters/shared.ts +196 -21
  390. package/src/adapters/types.ts +13 -1
  391. package/src/cache/fast-hash.ts +5 -0
  392. package/src/cli-check.ts +458 -0
  393. package/src/cli.ts +59 -24
  394. package/src/client/browser-entry/action-dispatch.ts +11 -5
  395. package/src/client/browser-entry/hydrate.ts +40 -29
  396. package/src/client/browser-entry/index.ts +15 -6
  397. package/src/client/browser-entry/post-hydration.ts +10 -9
  398. package/src/client/browser-entry/router-init.ts +104 -48
  399. package/src/client/browser-entry/rsc-stream.ts +11 -2
  400. package/src/client/error-boundary.tsx +85 -16
  401. package/src/client/history.ts +13 -6
  402. package/src/client/index.ts +14 -3
  403. package/src/client/internal.ts +4 -3
  404. package/src/client/link.tsx +120 -72
  405. package/src/client/navigation-api.ts +3 -3
  406. package/src/client/navigation-commit.ts +197 -0
  407. package/src/client/navigation-context.ts +40 -67
  408. package/src/client/navigation-root.tsx +326 -101
  409. package/src/client/params-context.ts +192 -0
  410. package/src/client/router-effects.ts +231 -0
  411. package/src/client/router-lifecycle.ts +288 -0
  412. package/src/client/router-pipeline.ts +393 -0
  413. package/src/client/router-ref.ts +1 -1
  414. package/src/client/router-skew.ts +30 -0
  415. package/src/client/router-types.ts +230 -0
  416. package/src/client/router.ts +243 -707
  417. package/src/client/rsc-fetch.ts +183 -106
  418. package/src/client/segment-cache.ts +129 -44
  419. package/src/client/ssr-data.ts +6 -0
  420. package/src/client/stale-client.ts +191 -0
  421. package/src/client/state.ts +14 -1
  422. package/src/client/top-loader.tsx +2 -1
  423. package/src/client/unload-guard.ts +34 -2
  424. package/src/client/use-cookie.ts +9 -2
  425. package/src/client/use-query-states.ts +102 -39
  426. package/src/client/use-router.ts +1 -1
  427. package/src/client/use-segment-params.ts +41 -18
  428. package/src/cookies/define-cookie.ts +6 -1
  429. package/src/index.ts +25 -4
  430. package/src/plugin-context.ts +58 -0
  431. package/src/plugins/adapter-build.ts +4 -0
  432. package/src/plugins/build-manifest.ts +34 -13
  433. package/src/plugins/entries.ts +4 -0
  434. package/src/plugins/fonts.ts +11 -8
  435. package/src/plugins/request-dep/analysis.ts +447 -0
  436. package/src/plugins/request-dep/index.ts +376 -0
  437. package/src/plugins/request-dep/origin.ts +310 -0
  438. package/src/plugins/routing.ts +97 -102
  439. package/src/plugins/shims.ts +0 -1
  440. package/src/plugins/static-build.ts +391 -95
  441. package/src/routing/codegen-shared.ts +3 -79
  442. package/src/routing/codegen-types.ts +28 -31
  443. package/src/routing/codegen-write.ts +139 -0
  444. package/src/routing/codegen.ts +86 -172
  445. package/src/routing/collision-probe.ts +438 -0
  446. package/src/routing/collision-spaces.ts +281 -0
  447. package/src/routing/convention-lint.ts +139 -40
  448. package/src/routing/export-detect.ts +151 -7
  449. package/src/routing/interception.ts +896 -50
  450. package/src/routing/link-codegen.ts +32 -65
  451. package/src/routing/manifest-codegen.ts +6 -62
  452. package/src/routing/scanner.ts +117 -92
  453. package/src/routing/segment-classify.ts +57 -0
  454. package/src/routing/segment-keys.ts +146 -0
  455. package/src/routing/slot-placement.ts +97 -0
  456. package/src/routing/types.ts +0 -6
  457. package/src/routing/walkers.ts +8 -0
  458. package/src/schema-bridge.ts +180 -58
  459. package/src/search-params/define.ts +108 -66
  460. package/src/search-params/index.ts +0 -1
  461. package/src/search-params/parse-total.ts +78 -0
  462. package/src/search-params/wrappers.ts +60 -11
  463. package/src/server/access-gate.tsx +60 -40
  464. package/src/server/action-handler.ts +4 -5
  465. package/src/server/actions.ts +6 -3
  466. package/src/server/als-registry.ts +18 -1
  467. package/src/server/build-manifest.ts +14 -1
  468. package/src/server/chain-url-parts.ts +163 -0
  469. package/src/server/children-interception.ts +115 -0
  470. package/src/server/compress.ts +9 -1
  471. package/src/server/default-status-page.ts +127 -0
  472. package/src/server/deny-boundary.ts +269 -41
  473. package/src/server/deny-renderer.ts +111 -39
  474. package/src/server/error-boundary-wrapper.ts +166 -79
  475. package/src/server/head-response.ts +54 -0
  476. package/src/server/index.ts +1 -3
  477. package/src/server/internal.ts +2 -2
  478. package/src/server/metadata-collector.ts +115 -0
  479. package/src/server/param-coercion.ts +51 -69
  480. package/src/server/pipeline-helpers.ts +2 -47
  481. package/src/server/pipeline-interception.ts +81 -32
  482. package/src/server/pipeline-outcome.ts +4 -5
  483. package/src/server/pipeline-phases.ts +77 -25
  484. package/src/server/pipeline.ts +57 -10
  485. package/src/server/prebuilt-runtime.ts +4 -4
  486. package/src/server/primitives.ts +25 -0
  487. package/src/server/publish-params.ts +42 -0
  488. package/src/server/request-context.ts +97 -18
  489. package/src/server/route-element-builder.ts +241 -253
  490. package/src/server/route-handler.ts +8 -8
  491. package/src/server/route-matcher.ts +21 -9
  492. package/src/server/rsc-cache-key-guard.ts +164 -0
  493. package/src/server/rsc-entry/api-handler.ts +6 -8
  494. package/src/server/rsc-entry/deny-fallback.ts +3 -2
  495. package/src/server/rsc-entry/error-renderer.ts +94 -35
  496. package/src/server/rsc-entry/helpers.ts +33 -28
  497. package/src/server/rsc-entry/index.ts +36 -33
  498. package/src/server/rsc-entry/render-route.ts +18 -10
  499. package/src/server/rsc-entry/revalidate-renderer.ts +3 -2
  500. package/src/server/rsc-entry/rsc-payload.ts +113 -40
  501. package/src/server/rsc-entry/rsc-stream.ts +29 -5
  502. package/src/server/rsc-entry/ssr-renderer.ts +38 -22
  503. package/src/server/skippable-prefix.ts +92 -0
  504. package/src/server/slot-interception.ts +168 -0
  505. package/src/server/slot-resolver.ts +263 -158
  506. package/src/server/ssr-bridge-types.ts +18 -0
  507. package/src/server/ssr-entry.ts +20 -10
  508. package/src/server/ssr-wrappers.tsx +33 -32
  509. package/src/server/state-tree-diff.ts +14 -55
  510. package/src/server/static-generator.ts +68 -29
  511. package/src/server/static-not-found.ts +134 -0
  512. package/src/server/status-code-resolver.ts +28 -11
  513. package/src/server/tree-builder.ts +35 -218
  514. package/src/server/types.ts +12 -7
  515. package/src/server/utils/element-type.ts +72 -0
  516. package/src/shared/als-slots.ts +72 -0
  517. package/src/shared/base-path.ts +80 -0
  518. package/src/shared/param-value.ts +244 -0
  519. package/src/shared/payload-root.ts +151 -0
  520. package/src/shared/rsc-cache-key.ts +269 -0
  521. package/src/shared/rsc-error-envelope.ts +31 -0
  522. package/src/shared/rsc-manifest.ts +29 -0
  523. package/src/shared/rsc-media-type.ts +43 -0
  524. package/src/shared/rsc-payload-path.ts +45 -0
  525. package/src/shared/segment-info.ts +60 -0
  526. package/src/shared/slot-params.ts +111 -0
  527. package/src/shared/static-platform-files.ts +75 -0
  528. package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
  529. package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
  530. package/dist/_chunks/cache-api-B-lhk9p4.js.map +0 -1
  531. package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
  532. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js +0 -668
  533. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +0 -1
  534. package/dist/_chunks/define-COtkxMRT.js +0 -191
  535. package/dist/_chunks/define-COtkxMRT.js.map +0 -1
  536. package/dist/_chunks/define-c4au4I9R.js +0 -82
  537. package/dist/_chunks/define-c4au4I9R.js.map +0 -1
  538. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
  539. package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
  540. package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
  541. package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
  542. package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
  543. package/dist/_chunks/registry-DbJPKoBp.js +0 -20
  544. package/dist/_chunks/registry-DbJPKoBp.js.map +0 -1
  545. package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
  546. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +0 -119
  547. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +0 -1
  548. package/dist/_chunks/segment-classify-Byy425ng.js.map +0 -1
  549. package/dist/_chunks/segment-context-ZDnXDkbz.js +0 -34
  550. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +0 -1
  551. package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
  552. package/dist/_chunks/use-query-states-DFvWd-EA.js.map +0 -1
  553. package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
  554. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
  555. package/dist/_chunks/walkers-_6zKFlch.js +0 -1002
  556. package/dist/_chunks/walkers-_6zKFlch.js.map +0 -1
  557. package/dist/client/error-boundary.js.map +0 -1
  558. package/dist/plugins/request-dep.d.ts +0 -32
  559. package/dist/plugins/request-dep.d.ts.map +0 -1
  560. package/dist/search-params/registry.d.ts +0 -20
  561. package/dist/search-params/registry.d.ts.map +0 -1
  562. package/dist/segment-params/define.d.ts +0 -89
  563. package/dist/segment-params/define.d.ts.map +0 -1
  564. package/dist/segment-params/index.d.ts +0 -3
  565. package/dist/segment-params/index.d.ts.map +0 -1
  566. package/dist/segment-params/index.js +0 -2
  567. package/src/plugins/request-dep.ts +0 -499
  568. package/src/search-params/registry.ts +0 -31
  569. package/src/segment-params/define.ts +0 -249
  570. package/src/segment-params/index.ts +0 -9
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The hard-navigate error envelope shared by the server and the client router.
3
+ *
4
+ * A client-navigation (RSC) request cannot carry an error *page* — the response
5
+ * body must be Flight data or the decoder crashes. Instead the server answers
6
+ * with this envelope: an `X-Timber-Error: 1` header and a minimal JSON body.
7
+ * The client treats it as "give up on SPA navigation and hard-navigate", and
8
+ * the resulting document request renders the real error page as HTML.
9
+ *
10
+ * The header name lives here so the four server producers and the single
11
+ * client consumer cannot drift apart. See design/10-error-handling.md
12
+ * §"Error Page Rendering for Client Navigation".
13
+ */
14
+
15
+ /** Header the client checks to decide whether to hard-navigate. */
16
+ export const TIMBER_ERROR_HEADER = 'X-Timber-Error';
17
+
18
+ /**
19
+ * Build the hard-navigate envelope for a status code.
20
+ *
21
+ * `responseHeaders` carries anything middleware already set (cookies, cache
22
+ * directives); the content type and error header are overwritten because the
23
+ * body is always this envelope. The body deliberately carries no message —
24
+ * only the status already on the wire (design/13-security.md principle 4).
25
+ */
26
+ export function rscErrorEnvelope(status: number, responseHeaders?: Headers): Response {
27
+ const headers = responseHeaders ?? new Headers();
28
+ headers.set(TIMBER_ERROR_HEADER, '1');
29
+ headers.set('content-type', 'application/json; charset=utf-8');
30
+ return new Response(JSON.stringify({ error: true, status }), { status, headers });
31
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The RSC manifest — the shape the static build writes and the client reads.
3
+ *
4
+ * In `output: 'static'` there is no server at navigation time and a generated
5
+ * `.rsc` file carries no response headers, so anything a navigation would
6
+ * normally learn from headers has to be inlined here at build time.
7
+ *
8
+ * Route params used to be such a thing (TIM-1255, TIM-1285). They are not any
9
+ * more: they ride inside the payload, on its root row, so the
10
+ * `.rsc` file carries them the same way it carries the tree, and the static
11
+ * path stopped needing a special case (TIM-1294). What is left is the content
12
+ * hash, which genuinely cannot live inside the file it names.
13
+ *
14
+ * Declared once rather than in each half. The producer
15
+ * (`plugins/static-build.ts`) and the consumer (`client/rsc-fetch.ts`) each
16
+ * had their own copy, and the copies drifted the moment a field was added to
17
+ * one — a static SPA navigation then committed `null` for the field the
18
+ * producer was faithfully writing.
19
+ *
20
+ * Isomorphic: no server, client, or build-time imports.
21
+ */
22
+
23
+ export interface RscManifestEntry {
24
+ /** The content-hashed URL the payload actually lives at, in route space. */
25
+ url: string;
26
+ }
27
+
28
+ /** Keyed by the unhashed `/_rsc/*.rsc` path. */
29
+ export type RscManifest = Record<string, RscManifestEntry>;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The RSC Flight media type, and the request predicate over it.
3
+ *
4
+ * One module owns the string because two independently-written spellings of
5
+ * "is this an RSC request?" must agree, and the consequence of them
6
+ * disagreeing is cache poisoning rather than a visible bug. The Cloudflare
7
+ * adapter's `isRsc` decides what may enter the edge cache; the origin's
8
+ * pipeline decides which headers may vary the response. TIM-1269 made the
9
+ * adapter's `VARY_HONORED` allowlist exempt `Accept` *because* `isRsc`
10
+ * excludes Flight responses from the cache, and exempt the `X-Timber-*`
11
+ * headers *because* the origin reads them only behind its own RSC check. If
12
+ * one predicate is ever tightened (a real media-type parse, a
13
+ * parameter-aware match) and the other is not, the adapter can classify a
14
+ * request as a document while the origin treats it as RSC, and store a
15
+ * Flight payload under the document's key — the class
16
+ * `design/48-payload-addressing.md` exists to prevent.
17
+ *
18
+ * `tests/rsc-media-type-single-source.test.ts` fails if the literal reappears
19
+ * in executable source outside this file.
20
+ *
21
+ * Isomorphic: zero imports, so `adapters/cloudflare.ts` — which Node's native
22
+ * ESM loader evaluates before Vite's resolver exists — can load it and
23
+ * interpolate the value into the generated worker. Same precedent as
24
+ * `shared/rsc-cache-key.ts`.
25
+ *
26
+ * See design/19-client-navigation.md, design/25-production-deployments.md
27
+ * §"`Vary` and the Workers Cache API".
28
+ */
29
+
30
+ /** Media type of a React Flight payload. */
31
+ export const RSC_CONTENT_TYPE = 'text/x-component';
32
+
33
+ /**
34
+ * Is this request asking for an RSC payload rather than a full document?
35
+ *
36
+ * Substring containment, deliberately: `Accept` is a list, and a client may
37
+ * send `text/x-component;charset=utf-8` or list it alongside other types.
38
+ * Tightening this to a real media-type parse is a behaviour change that has
39
+ * to move the adapter's generated `isRsc` in the same commit — see above.
40
+ */
41
+ export function isRscRequest(req: Request): boolean {
42
+ return (req.headers.get('Accept') ?? '').includes(RSC_CONTENT_TYPE);
43
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Where a route's Flight payload lives in `output: 'static'`.
3
+ *
4
+ * The static build writes these files and the client fetches them, so the two
5
+ * halves must agree byte for byte. They used to state the naming rule
6
+ * separately — `plugins/static-build.ts` for the write and
7
+ * `client/rsc-fetch.ts` for the read — which is a duplicate representation with
8
+ * nothing checking it. One function now, called by both.
9
+ *
10
+ * ## The shape
11
+ *
12
+ * The payload path mirrors the HTML path: every route gets a directory and the
13
+ * artifact is the `index` inside it.
14
+ *
15
+ * / → /_rsc/index.rsc (cf. index.html)
16
+ * /about → /_rsc/about/index.rsc (cf. about/index.html)
17
+ * /blog/hello → /_rsc/blog/hello/index.rsc
18
+ *
19
+ * That shape is **injective**, which the previous one (`/about` →
20
+ * `/_rsc/about.rsc`, root → `/_rsc/index.rsc`) was not: a site with both `/`
21
+ * and `/index` produced two payloads at `_rsc/index.rsc`, and the second write
22
+ * won silently — a client navigation to one route was served the other route's
23
+ * payload, same content type and same shape, undetectable downstream
24
+ * (TIM-1266).
25
+ *
26
+ * Injectivity holds because two distinct non-root routes give distinct
27
+ * directories, and the root's `/_rsc/index.rsc` has no directory component for
28
+ * a non-root route to occupy — reaching it would need an empty route path,
29
+ * which is not a route.
30
+ *
31
+ * Isomorphic: no server, client, or build-time imports.
32
+ */
33
+
34
+ /**
35
+ * The route-space path of a route's static Flight payload.
36
+ *
37
+ * @param routePath A route-space pathname: leading slash, no deployment base,
38
+ * no query or fragment, no trailing slash (except the root `/`). Callers
39
+ * normalize; this function does not, because the two callers normalize from
40
+ * different sources (a browser URL, a build-time route entry).
41
+ */
42
+ export function rscPayloadPath(routePath: string): string {
43
+ const prefix = routePath === '/' ? '' : routePath;
44
+ return `/_rsc${prefix}/index.rsc`;
45
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The segment metadata wire contract between server and client.
3
+ *
4
+ * One declaration, imported by both ends. The producer
5
+ * (`server/rsc-entry/helpers.ts` → `X-Timber-Segments` and the
6
+ * `self.__timber_segments` bootstrap script) and the consumers
7
+ * (`client/segment-cache.ts`, the history stack, the prefetch cache) used to
8
+ * declare this shape separately, which is how a field gets added to one side
9
+ * only.
10
+ *
11
+ * See design/19-client-navigation.md §"X-Timber-State-Tree Header"
12
+ * See design/07-routing.md §"Intercepting Routes"
13
+ */
14
+
15
+ /**
16
+ * Metadata for one rendered segment or slot, sent via `X-Timber-Segments`.
17
+ */
18
+ export interface SegmentInfo {
19
+ /** The segment's URL path (e.g. `/`, `/feed`), or the slot key for slots. */
20
+ path: string;
21
+ /** Outlet key — includes route group name when applicable (e.g. `/(marketing)`). */
22
+ segmentId?: string;
23
+ /**
24
+ * The segment's directory path in `app/`, groups included and slots elided
25
+ * (e.g. `app/(browse)/feed` → `/(browse)/feed`). Absent on slot entries.
26
+ *
27
+ * This is the identity interception scoping compares against, and it is the
28
+ * reason it travels: `path`/`segmentId` are URL-addressed and collapse
29
+ * `(browse)/feed` and `(landing)/feed` to the same key, while a scope has to
30
+ * tell those two directories apart. See `computeSegmentTreePaths`.
31
+ */
32
+ treePath?: string;
33
+ isRequestDependent: boolean;
34
+ /** True for parallel route slot entries, keyed by slot path (e.g. `/@sidebar`). */
35
+ slot?: boolean;
36
+ /** Parent segment path for slot entries — attaches the slot to its SegmentNode. */
37
+ parentSegment?: string;
38
+ /** True when the slot's access.ts denied on this render. Denied slots are excluded from the state tree. */
39
+ denied?: boolean;
40
+ /** True when the slot was skipped (cached content reused). Payloads with skipped slots are not replayable. */
41
+ skipped?: boolean;
42
+ }
43
+
44
+ /**
45
+ * The client's `X-Timber-State-Tree` request header.
46
+ *
47
+ * `segments` and `slots` are a caching optimization — they tell the server what
48
+ * the client can reuse. `treePaths` is not: it describes the *shape* of the
49
+ * tree currently on screen, so the server can answer "does the rendered route
50
+ * pass through the segment that owns this intercepting slot?" without
51
+ * re-deriving it from the address bar, which stops being the source route the
52
+ * moment a modal is open (TIM-1282).
53
+ *
54
+ * None of the three is a security input. Every `access.ts` runs regardless.
55
+ */
56
+ export interface StateTree {
57
+ segments: string[];
58
+ slots?: string[];
59
+ treePaths?: string[];
60
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Per-slot segment params — the one definition both halves of the API read.
3
+ *
4
+ * A parallel slot matches the URL through its *own* sub-tree, so it can derive
5
+ * a param the main route never had, or derive the same name with a different
6
+ * type (`[...year]` → `string[]` where the main route's `[year]` gave
7
+ * `string`). The server answers `getSegmentParams(slotPath)` from a per-slot
8
+ * map; the client answers `useSegmentParams(slotPath)` from the same map,
9
+ * published on the RSC payload (TIM-1285).
10
+ *
11
+ * The merge lives here rather than in either half because the two must agree
12
+ * about what "the slot's params" are — a divergence is invisible until
13
+ * somebody reads a param of the wrong type, which is exactly the class of bug
14
+ * this module closes.
15
+ *
16
+ * Isomorphic: no server or client imports.
17
+ *
18
+ * See design/41-global-params.md §"Params in a parallel slot".
19
+ */
20
+
21
+ /** Slot tree path → that slot's own coerced params. */
22
+ export type SlotParamsRecord = Record<string, Record<string, string | string[]>>;
23
+
24
+ /**
25
+ * The params a slot sees: the main route's as a base, the slot's own on top.
26
+ *
27
+ * Params from segments *above* the slot are not re-derived by the slot's own
28
+ * chain, so they have to come from the main route; params the slot does
29
+ * re-derive may have a different type than the main route gave them, so the
30
+ * slot's win.
31
+ *
32
+ * Null-prototype, like every other param record the framework hands out
33
+ * (`coerceSegmentParams` installs one unconditionally). A spread literal would
34
+ * inherit `Object.prototype`, so a lookup for a param the route does not
35
+ * define would resolve to an inherited member — `params.constructor` returning
36
+ * a function instead of `undefined` — in the one param record that was built
37
+ * by merging. See design/13-security.md #36c.
38
+ */
39
+ export function mergeSlotParams(
40
+ mainParams: Record<string, string | string[]>,
41
+ slotParams: Record<string, string | string[]>
42
+ ): Record<string, string | string[]> {
43
+ return Object.assign(Object.create(null), mainParams, slotParams);
44
+ }
45
+
46
+ /**
47
+ * Resolve the params for a segment path against a published slot map.
48
+ *
49
+ * Returns the merge when `segmentPath` names a slot that published params,
50
+ * and the main route's record otherwise — an ordinary (non-slot) segment
51
+ * path, an unknown path, or a request with no slots at all. Mirrors the
52
+ * server's `getSegmentParams(segmentPath)` branch exactly.
53
+ *
54
+ * `Object.hasOwn` rather than `in` or a truthiness test: the map arrives from
55
+ * JSON, so a segment path of `constructor` or `toString` would otherwise
56
+ * resolve to an inherited member of `Object.prototype`.
57
+ */
58
+ export function resolveSegmentParams(
59
+ mainParams: Record<string, string | string[]>,
60
+ slotParams: SlotParamsRecord | null | undefined,
61
+ segmentPath: string | undefined
62
+ ): Record<string, string | string[]> {
63
+ if (!segmentPath || !slotParams || !Object.hasOwn(slotParams, segmentPath)) return mainParams;
64
+ return cachedMerge(mainParams, slotParams, segmentPath);
65
+ }
66
+
67
+ /**
68
+ * The merged record for one (main record, slot map, path) triple, reused until
69
+ * one of the three changes.
70
+ *
71
+ * `useSegmentParams(slotPath)` calls this on every render. Returning a fresh
72
+ * object each time makes the hook's result change by reference on renders where
73
+ * nothing navigated, so a component using it as a `useEffect` dependency
74
+ * re-runs the effect — and re-renders in a loop if that effect sets state —
75
+ * while memoized children below it lose their memoization.
76
+ *
77
+ * Keyed on the *identities* of the two records, not their contents: both are
78
+ * replaced rather than mutated on every navigation (`setCurrentParams`,
79
+ * `setCurrentSlotParams`, and the server's per-request store), so identity is
80
+ * the correct equality here and a deep comparison would be slower and no more
81
+ * accurate.
82
+ *
83
+ * A `WeakMap` chain rather than a `Map`, so a superseded navigation's records
84
+ * and their merges become collectable as soon as nothing else holds them.
85
+ */
86
+ const mergeCache = new WeakMap<
87
+ object,
88
+ WeakMap<object, Map<string, Record<string, string | string[]>>>
89
+ >();
90
+
91
+ function cachedMerge(
92
+ mainParams: Record<string, string | string[]>,
93
+ slotParams: SlotParamsRecord,
94
+ segmentPath: string
95
+ ): Record<string, string | string[]> {
96
+ let bySlotMap = mergeCache.get(mainParams);
97
+ if (!bySlotMap) {
98
+ bySlotMap = new WeakMap();
99
+ mergeCache.set(mainParams, bySlotMap);
100
+ }
101
+ let byPath = bySlotMap.get(slotParams);
102
+ if (!byPath) {
103
+ byPath = new Map();
104
+ bySlotMap.set(slotParams, byPath);
105
+ }
106
+ const cached = byPath.get(segmentPath);
107
+ if (cached) return cached;
108
+ const merged = mergeSlotParams(mainParams, slotParams[segmentPath]);
109
+ byPath.set(segmentPath, merged);
110
+ return merged;
111
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Platform files the static build is allowed to overwrite in the output.
3
+ *
4
+ * The build merges two trees into the deployed directory — the client bundle
5
+ * (which carries everything the user put in `public/`) and the pre-rendered
6
+ * site. That merge otherwise refuses overlaps, because a silent overwrite
7
+ * leaves one of two artifacts deployed with nothing recording which
8
+ * (TIM-1266).
9
+ *
10
+ * These names are the exception, and only because the pre-rendered copy is
11
+ * *derived from* the one it replaces rather than competing with it:
12
+ * `plugins/static-build.ts` reads `public/_redirects` and writes the
13
+ * generated rules plus the user's, so the winner is a superset of the loser.
14
+ *
15
+ * That holds only for a file the current pass produced, which is why
16
+ * `cleanConditionalArtifacts` deletes a previous build's `_redirects` before
17
+ * generation: written only when a pass finds redirects, it would otherwise
18
+ * survive into a pass that produced nothing and claim an exemption it no
19
+ * longer earns.
20
+ *
21
+ * `_headers` is NOT here. It is not written into the pre-rendered tree at
22
+ * all — adapters generate it directly into the output, folding in the
23
+ * user's copy as they go (TIM-1326).
24
+ *
25
+ * Declared once so the code that performs the merge and the code that
26
+ * produces the merged file cannot disagree about which names are exempt.
27
+ *
28
+ * Isomorphic: no server, client, or build-time imports.
29
+ */
30
+
31
+ /** Platform redirect rules (Cloudflare Pages, Netlify). See TIM-1245/TIM-1249. */
32
+ export const REDIRECTS_FILE = '_redirects';
33
+
34
+ /** Platform header rules (Cloudflare Pages, Netlify). See TIM-1241/TIM-1326. */
35
+ export const HEADERS_FILE = '_headers';
36
+
37
+ /**
38
+ * Where a user authors platform files. Stated once because two modules read
39
+ * from here — `plugins/static-build.ts` for `_redirects`, adapters for
40
+ * `_headers` — and they must look in the same place.
41
+ *
42
+ * Both read the **project source**, never the build output. The generated
43
+ * file lands under the same name in the output directory, so a reader aimed
44
+ * there would fold the previous build's generated rules back in and compound
45
+ * them on every rebuild.
46
+ */
47
+ export const USER_PLATFORM_DIR = 'public';
48
+
49
+ /** Output-relative paths whose pre-rendered copy subsumes the `public/` one. */
50
+ export const USER_MERGED_PLATFORM_FILES: readonly string[] = [REDIRECTS_FILE];
51
+
52
+ /**
53
+ * Output paths the framework writes itself, which no route may claim.
54
+ *
55
+ * These are written outside the per-entry writer — `_redirects` after
56
+ * generation, `_headers` by the adapter after the copy — so the collision
57
+ * tracker never sees them and a route rendering to one of these paths is
58
+ * overwritten with nothing recording it.
59
+ *
60
+ * Reserved rather than tracked, because there is no version of "serve a route
61
+ * at `/_headers`" that works: Cloudflare Pages and Netlify read these two
62
+ * files themselves and never serve them, so the route is unservable however
63
+ * the conflict is resolved.
64
+ *
65
+ * That justification is per-file, not per-mechanism. `.nojekyll` is written
66
+ * the same way and is deliberately NOT here: only the `github-pages` target
67
+ * writes it, and everywhere else `/.nojekyll` is an ordinary servable path,
68
+ * so reserving it globally would refuse a valid Cloudflare site. Its write
69
+ * site skips the write when a file is already there instead — GitHub Pages
70
+ * only cares that the file exists.
71
+ *
72
+ * Same reasoning as the synthetic 404 entry using an internal urlPath so a
73
+ * real `/404` route cannot collide with `404.html`.
74
+ */
75
+ export const RESERVED_OUTPUT_PATHS: readonly string[] = [REDIRECTS_FILE, HEADERS_FILE];
@@ -1,196 +0,0 @@
1
- import { basename, join, relative } from "node:path";
2
- import { cp, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
3
- //#region src/adapters/shared.ts
4
- /** Cache-Control value for hashed (immutable) assets. */
5
- var IMMUTABLE_CACHE = "public, max-age=31536000, immutable";
6
- /** Cache-Control value for unhashed static assets. */
7
- var STATIC_CACHE = "public, max-age=3600, must-revalidate";
8
- /**
9
- * Generate a `_headers` file for static asset cache control.
10
- *
11
- * The `_headers` file is a platform convention supported by Cloudflare Workers
12
- * Static Assets, Cloudflare Pages, and Netlify. It maps URL patterns to
13
- * HTTP response headers.
14
- *
15
- * Only hashed (immutable) asset paths are listed here by default. When
16
- * `unhashedPaths` is provided, per-file rules are appended for unhashed
17
- * static assets (favicon.ico, robots.txt, etc.) so they get Cache-Control
18
- * on platforms like Cloudflare Workers Static Assets where the server
19
- * handler never sees static file requests.
20
- *
21
- * A `/*` catch-all is NOT used — it would be additive on Cloudflare,
22
- * producing duplicate Cache-Control directives on hashed assets
23
- * (invalid per RFC 9111).
24
- */
25
- var MAX_PER_FILE_RULES = 97;
26
- function generateHeadersFile(unhashedPaths, contentTypes) {
27
- let content = `# Auto-generated by @timber-js/app — static asset cache headers.
28
- # See design/25-production-deployments.md §"CDN / Edge Cache"
29
-
30
- /assets/*
31
- Cache-Control: ${IMMUTABLE_CACHE}
32
-
33
- /_timber/fonts/*
34
- Cache-Control: ${IMMUTABLE_CACHE}
35
-
36
- /_rsc/*
37
- Cache-Control: ${IMMUTABLE_CACHE}
38
- `;
39
- const allCtEntries = contentTypes ? Object.entries(contentTypes).sort(([a], [b]) => a.localeCompare(b)) : [];
40
- const ctEntries = allCtEntries.slice(0, MAX_PER_FILE_RULES);
41
- 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.`);
42
- const remainingBudget = MAX_PER_FILE_RULES - ctEntries.length;
43
- if (unhashedPaths && unhashedPaths.length > 0) {
44
- const capped = unhashedPaths.slice(0, Math.max(0, remainingBudget));
45
- 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.`);
46
- if (capped.length > 0) {
47
- content += `\n# Unhashed static assets — short-lived cache with revalidation\n`;
48
- for (const p of capped) content += `\n${p}\n Cache-Control: ${STATIC_CACHE}\n`;
49
- }
50
- }
51
- if (ctEntries.length > 0) {
52
- content += `\n# Content-Type for extensionless API routes\n`;
53
- for (const [urlPath, ct] of ctEntries) content += `\n${urlPath}\n Content-Type: ${ct}\n`;
54
- }
55
- return content;
56
- }
57
- //#endregion
58
- //#region src/adapters/build-output-helper.ts
59
- /**
60
- * Run the platform-agnostic build output steps shared by all adapters:
61
- *
62
- * 1. Create the output directory
63
- * 2. Copy client assets to the public/static directory
64
- * 3. Write the `_headers` file for static asset cache control
65
- * 4. Copy RSC and SSR server bundles into the output directory
66
- * 5. Write the manifest-init module if present
67
- *
68
- * Returns the resolved public directory path for further adapter-specific use.
69
- */
70
- async function runSharedBuildSteps(opts) {
71
- const { config, buildDir, outDir, publicDirName } = opts;
72
- await mkdir(outDir, { recursive: true });
73
- const clientDir = join(buildDir, "client");
74
- const publicDir = join(outDir, publicDirName);
75
- await mkdir(publicDir, { recursive: true });
76
- const referencedWasm = await findReferencedWasm(clientDir);
77
- await cp(clientDir, publicDir, {
78
- recursive: true,
79
- filter: (src) => {
80
- if (src.endsWith(".wasm") && !referencedWasm.has(basename(src))) return false;
81
- if (config.clientJavascriptDisabled && src.endsWith(".js")) return false;
82
- return true;
83
- }
84
- }).catch((e) => {
85
- if (e.code !== "ENOENT") throw e;
86
- });
87
- const unhashedPaths = await findUnhashedStaticFiles(publicDir);
88
- await writeFile(join(publicDir, "_headers"), generateHeadersFile(unhashedPaths));
89
- await cp(join(buildDir, "rsc"), join(outDir, "rsc"), { recursive: true });
90
- await cp(join(buildDir, "ssr"), join(outDir, "ssr"), { recursive: true }).catch((e) => {
91
- if (e.code !== "ENOENT") throw e;
92
- });
93
- await cp(join(buildDir, "prebuilt"), join(outDir, "prebuilt"), { recursive: true }).catch((e) => {
94
- if (e.code !== "ENOENT") throw e;
95
- });
96
- if (config.manifestInit) await writeFile(join(outDir, "_timber-manifest-init.js"), config.manifestInit);
97
- return publicDir;
98
- }
99
- /**
100
- * Find unhashed static files in the public directory that need per-file
101
- * Cache-Control rules in the `_headers` file.
102
- *
103
- * Excludes:
104
- * - Files under `assets/` and `_timber/` (covered by wildcard rules)
105
- * - Underscore-prefixed files (`_headers`, `_worker.js`, etc.)
106
- *
107
- * @internal Exported for testing.
108
- */
109
- var PRIORITY_FILES = /* @__PURE__ */ new Set([
110
- "/favicon.ico",
111
- "/robots.txt",
112
- "/sitemap.xml",
113
- "/manifest.json",
114
- "/manifest.webmanifest",
115
- "/apple-touch-icon.png"
116
- ]);
117
- async function findUnhashedStaticFiles(publicDir) {
118
- let files;
119
- try {
120
- files = await collectFiles(publicDir);
121
- } catch {
122
- return [];
123
- }
124
- const priority = [];
125
- const rest = [];
126
- for (const file of files) {
127
- const rel = relative(publicDir, file).replace(/\\/g, "/");
128
- if (rel.startsWith("assets/") || rel.startsWith("_timber/")) continue;
129
- if (rel.startsWith("rsc/") || rel.startsWith("ssr/") || rel.startsWith("_rsc/")) continue;
130
- if (basename(rel).startsWith("_")) continue;
131
- const urlPath = "/" + rel;
132
- if (PRIORITY_FILES.has(urlPath)) priority.push(urlPath);
133
- else rest.push(urlPath);
134
- }
135
- return [...priority.sort(), ...rest.sort()];
136
- }
137
- /**
138
- * Scan client JS files for references to .wasm filenames.
139
- * Returns the set of WASM basenames that are actually imported/referenced
140
- * by client code and must be preserved in the static output.
141
- */
142
- async function findReferencedWasm(clientDir) {
143
- const referenced = /* @__PURE__ */ new Set();
144
- let files;
145
- try {
146
- files = await collectFiles(clientDir);
147
- } catch {
148
- return referenced;
149
- }
150
- const jsFiles = files.filter((f) => f.endsWith(".js"));
151
- const wasmFiles = files.filter((f) => f.endsWith(".wasm")).map((f) => basename(f));
152
- if (wasmFiles.length === 0) return referenced;
153
- for (const jsFile of jsFiles) {
154
- const content = await readFile(jsFile, "utf-8");
155
- for (const wasmName of wasmFiles) if (content.includes(wasmName)) referenced.add(wasmName);
156
- }
157
- return referenced;
158
- }
159
- /**
160
- * Build a static-only output directory (no server entry). Copies client
161
- * assets and pre-rendered HTML/RSC/API files into `outDir/publicDirName`.
162
- * Used by both Cloudflare and Nitro adapters in `output: 'static'` mode.
163
- */
164
- async function buildStaticDirectoryOutput(config, buildDir, outDir, publicDirName) {
165
- await rm(outDir, {
166
- recursive: true,
167
- force: true
168
- }).catch(() => {});
169
- await mkdir(outDir, { recursive: true });
170
- const publicDir = join(outDir, publicDirName);
171
- await mkdir(publicDir, { recursive: true });
172
- await cp(join(buildDir, "client"), publicDir, {
173
- recursive: true,
174
- filter: (src) => {
175
- if (config.clientJavascriptDisabled && src.endsWith(".js")) return false;
176
- return true;
177
- }
178
- }).catch((e) => {
179
- if (e.code !== "ENOENT") throw e;
180
- });
181
- if (config.staticPagesDir) await cp(config.staticPagesDir, publicDir, { recursive: true });
182
- }
183
- async function collectFiles(dir) {
184
- const result = [];
185
- const entries = await readdir(dir, { withFileTypes: true });
186
- for (const entry of entries) {
187
- const fullPath = join(dir, entry.name);
188
- if (entry.isDirectory()) result.push(...await collectFiles(fullPath));
189
- else result.push(fullPath);
190
- }
191
- return result;
192
- }
193
- //#endregion
194
- export { generateHeadersFile as a, IMMUTABLE_CACHE as i, findUnhashedStaticFiles as n, runSharedBuildSteps as r, buildStaticDirectoryOutput as t };
195
-
196
- //# sourceMappingURL=build-output-helper-DOGYFb_X.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-output-helper-DOGYFb_X.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\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 * Only hashed (immutable) asset paths are listed here by default. 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// Cloudflare Workers Static Assets caps _headers at 100 rules.\n// Reserve 3 for the wildcard hashed-asset rules (/assets/*, /_timber/fonts/*, /_rsc/*).\nconst MAX_PER_FILE_RULES = 97;\n\nexport function generateHeadersFile(\n unhashedPaths?: string[],\n contentTypes?: Record<string, string>\n): string {\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/assets/*\n Cache-Control: ${IMMUTABLE_CACHE}\n\n/_timber/fonts/*\n Cache-Control: ${IMMUTABLE_CACHE}\n\n/_rsc/*\n Cache-Control: ${IMMUTABLE_CACHE}\n`;\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, MAX_PER_FILE_RULES);\n if (allCtEntries.length > MAX_PER_FILE_RULES) {\n console.warn(\n `[timber] _headers: ${allCtEntries.length} content-type rules exceed ` +\n `Cloudflare's 100-rule limit. Only the first ${MAX_PER_FILE_RULES} ` +\n `extensionless API routes will get Content-Type headers.`\n );\n }\n const remainingBudget = MAX_PER_FILE_RULES - 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 if (capped.length > 0) {\n content += `\\n# Unhashed static assets — short-lived cache with revalidation\\n`;\n for (const p of capped) {\n content += `\\n${p}\\n Cache-Control: ${STATIC_CACHE}\\n`;\n }\n }\n }\n\n if (ctEntries.length > 0) {\n content += `\\n# Content-Type for extensionless API routes\\n`;\n for (const [urlPath, ct] of ctEntries) {\n content += `\\n${urlPath}\\n Content-Type: ${ct}\\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 { generateHeadersFile } from './shared.js';\nimport type { TimberConfig } from './types';\n\n/** Options for the shared build output steps. */\nexport interface BuildOutputBaseOptions {\n /** Resolved timber config. */\n config: TimberConfig;\n /** Root build directory (e.g. `.timber/build`). */\n buildDir: string;\n /** Adapter-specific output directory (e.g. `.timber/build/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, buildDir, 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 clientDir = join(buildDir, 'client');\n const publicDir = join(outDir, publicDirName);\n await mkdir(publicDir, { recursive: true });\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 }).catch((e: NodeJS.ErrnoException) => {\n // Client dir may not exist when client JavaScript is disabled\n if (e.code !== 'ENOENT') throw e;\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 const unhashedPaths = await findUnhashedStaticFiles(publicDir);\n await writeFile(join(publicDir, '_headers'), generateHeadersFile(unhashedPaths));\n\n // 4. Copy RSC + SSR server bundles into the output directory.\n await cp(join(buildDir, 'rsc'), join(outDir, 'rsc'), { recursive: true });\n await cp(join(buildDir, 'ssr'), join(outDir, 'ssr'), { recursive: true }).catch(\n (e: NodeJS.ErrnoException) => {\n // SSR dir may not exist for static-only builds\n if (e.code !== 'ENOENT') throw e;\n }\n );\n\n // 4b. Copy prebuilt/ flight payloads if present (cache.component artifacts).\n // These are produced by the post-build capture pass (design/44) and read\n // at request time via the adapter's PrebuiltPayloadSource.\n await cp(join(buildDir, 'prebuilt'), join(outDir, 'prebuilt'), { recursive: true }).catch(\n (e: NodeJS.ErrnoException) => {\n // No prebuilt dir when the app has no cache.component calls\n if (e.code !== 'ENOENT') throw e;\n }\n );\n\n // 5. Write manifest-init module if present.\n if (config.manifestInit) {\n await writeFile(join(outDir, '_timber-manifest-init.js'), config.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 `assets/` and `_timber/` (covered by wildcard rules)\n * - Underscore-prefixed files (`_headers`, `_worker.js`, etc.)\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(publicDir: string): 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 for (const file of files) {\n const rel = relative(publicDir, file).replace(/\\\\/g, '/');\n if (rel.startsWith('assets/') || rel.startsWith('_timber/')) continue;\n if (rel.startsWith('rsc/') || rel.startsWith('ssr/') || rel.startsWith('_rsc/')) continue;\n if (basename(rel).startsWith('_')) continue;\n const urlPath = '/' + rel;\n if (PRIORITY_FILES.has(urlPath)) {\n priority.push(urlPath);\n } else {\n rest.push(urlPath);\n }\n }\n\n return [...priority.sort(), ...rest.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\n let files: string[];\n try {\n files = await collectFiles(clientDir);\n } catch {\n return referenced;\n }\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 buildDir: string,\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 const clientDir = join(buildDir, 'client');\n await cp(clientDir, publicDir, {\n recursive: true,\n filter: (src: string) => {\n if (config.clientJavascriptDisabled && src.endsWith('.js')) return false;\n return true;\n },\n }).catch((e: NodeJS.ErrnoException) => {\n if (e.code !== 'ENOENT') throw e;\n });\n\n // Copy pre-rendered static pages (HTML + RSC flight + API routes).\n if (config.staticPagesDir) {\n await cp(config.staticPagesDir, publicDir, { recursive: true });\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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"}