framefields 2.12.0 → 2.13.0

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 (382) hide show
  1. package/dist/audio/index.d.mts +6 -5
  2. package/dist/audio/index.mjs +13 -13
  3. package/dist/{audio-afTBdB3U.d.mts → audio-CHV33Od9.d.mts} +3 -4
  4. package/dist/audio-CHV33Od9.d.mts.map +1 -0
  5. package/dist/{audio-DHLoNcxD.mjs → audio-DHzLQ_RG.mjs} +4 -4
  6. package/dist/{audio-DHLoNcxD.mjs.map → audio-DHzLQ_RG.mjs.map} +1 -1
  7. package/dist/{audio-KHBadECb.mjs → audio-DS9Jg2ls.mjs} +1 -1
  8. package/dist/{audio-KHBadECb.mjs.map → audio-DS9Jg2ls.mjs.map} +1 -1
  9. package/dist/{check-result-Culfu7Nx.mjs → check-result-DZWx73V8.mjs} +1 -1
  10. package/dist/{check-result-Culfu7Nx.mjs.map → check-result-DZWx73V8.mjs.map} +1 -1
  11. package/dist/cli/check-worker.mjs +51 -51
  12. package/dist/cli/check-worker.mjs.map +1 -1
  13. package/dist/cli/local-worker.d.mts +28 -0
  14. package/dist/cli/local-worker.d.mts.map +1 -0
  15. package/dist/cli/local-worker.mjs +83 -0
  16. package/dist/cli/local-worker.mjs.map +1 -0
  17. package/dist/cli.mjs +229 -54
  18. package/dist/cli.mjs.map +1 -1
  19. package/dist/cloud/index.d.mts +2 -0
  20. package/dist/cloud/index.d.mts.map +1 -1
  21. package/dist/cloud/index.mjs +1 -1
  22. package/dist/{cloud-COid1Ipa.mjs → cloud-Cj1TIme8.mjs} +306 -7
  23. package/dist/cloud-Cj1TIme8.mjs.map +1 -0
  24. package/dist/components/index.d.mts +15 -14
  25. package/dist/components/index.mjs +47 -47
  26. package/dist/{dist-CySGkG54.mjs → dist-BSKAbyea.mjs} +2 -2
  27. package/dist/{dist-CySGkG54.mjs.map → dist-BSKAbyea.mjs.map} +1 -1
  28. package/dist/{dist-BwtxciN4.mjs → dist-B_rSWeOz.mjs} +1 -1
  29. package/dist/{dist-Bf2_efYP.mjs → dist-C8XSqfTx.mjs} +1 -1
  30. package/dist/{dist-Bf2_efYP.mjs.map → dist-C8XSqfTx.mjs.map} +1 -1
  31. package/dist/{dist-BSqeChht.mjs → dist-CUNvNDS3.mjs} +129 -82
  32. package/dist/dist-CUNvNDS3.mjs.map +1 -0
  33. package/dist/dist-CiTgmfUw.mjs +502 -0
  34. package/dist/dist-CiTgmfUw.mjs.map +1 -0
  35. package/dist/{dist-B-OPY7Cs.mjs → dist-D3BeAZ7X.mjs} +44 -10
  36. package/dist/dist-D3BeAZ7X.mjs.map +1 -0
  37. package/dist/{dist-BIE8fvlv.mjs → dist-DgZpN6IK.mjs} +1 -1
  38. package/dist/{dist-BIE8fvlv.mjs.map → dist-DgZpN6IK.mjs.map} +1 -1
  39. package/dist/{dist-2_lT3Dwc.mjs → dist-Kbf-JTry.mjs} +2 -2
  40. package/dist/{dist-2_lT3Dwc.mjs.map → dist-Kbf-JTry.mjs.map} +1 -1
  41. package/dist/effects/index.d.mts +6 -6
  42. package/dist/effects/index.mjs +36 -36
  43. package/dist/{effects-C8CL9cOq.mjs → effects-BiDgCK1L.mjs} +3 -3
  44. package/dist/{effects-C8CL9cOq.mjs.map → effects-BiDgCK1L.mjs.map} +1 -1
  45. package/dist/fonts/index.d.mts +1 -1
  46. package/dist/fonts/index.mjs +3 -3
  47. package/dist/{fonts-BQrDjnpV.mjs → fonts-DeDPWdvJ.mjs} +2 -2
  48. package/dist/{fonts-BQrDjnpV.mjs.map → fonts-DeDPWdvJ.mjs.map} +1 -1
  49. package/dist/{gpu-DHa-3Dou.mjs → gpu-CWjgql4C.mjs} +2 -2
  50. package/dist/{gpu-DHa-3Dou.mjs.map → gpu-CWjgql4C.mjs.map} +1 -1
  51. package/dist/index-BFTtXosj.d.mts +63 -0
  52. package/dist/index-BFTtXosj.d.mts.map +1 -0
  53. package/dist/{index-BW0Q1ygn.d.mts → index-C5sgRLlG.d.mts} +1 -1
  54. package/dist/{index-BW0Q1ygn.d.mts.map → index-C5sgRLlG.d.mts.map} +1 -1
  55. package/dist/{index-CdCrae-I.d.mts → index-CnZhBlob.d.mts} +2 -2
  56. package/dist/index-CnZhBlob.d.mts.map +1 -0
  57. package/dist/{index-CTv9ZieD.d.mts → index-D68eGFNE.d.mts} +3 -30
  58. package/dist/index-D68eGFNE.d.mts.map +1 -0
  59. package/dist/{index-WwuuX8ZJ.d.mts → index-DBh3WphX.d.mts} +2 -2
  60. package/dist/{index-WwuuX8ZJ.d.mts.map → index-DBh3WphX.d.mts.map} +1 -1
  61. package/dist/{index-gOVtTm-P.d.mts → index-DQ1U3HC3.d.mts} +14 -6
  62. package/dist/index-DQ1U3HC3.d.mts.map +1 -0
  63. package/dist/{index-CAuNuvIg.d.mts → index-Dibc_xpC.d.mts} +5 -5
  64. package/dist/{index-CAuNuvIg.d.mts.map → index-Dibc_xpC.d.mts.map} +1 -1
  65. package/dist/{index-BNClElng.d.mts → index-E2IXX0Cz.d.mts} +282 -284
  66. package/dist/index-E2IXX0Cz.d.mts.map +1 -0
  67. package/dist/{index-Fliv2Z-w.d.mts → index-X2u96TEo.d.mts} +131 -5
  68. package/dist/index-X2u96TEo.d.mts.map +1 -0
  69. package/dist/{index-Drk6HC2k.d.mts → index-YB9j9KUx.d.mts} +3 -3
  70. package/dist/{index-Drk6HC2k.d.mts.map → index-YB9j9KUx.d.mts.map} +1 -1
  71. package/dist/{index-COYNQ_mf.d.mts → index-a6JrbAK0.d.mts} +1 -1
  72. package/dist/{index-COYNQ_mf.d.mts.map → index-a6JrbAK0.d.mts.map} +1 -1
  73. package/dist/{index-DQa7mhzq.d.mts → index-rtCXNxGO.d.mts} +2 -2
  74. package/dist/{index-DQa7mhzq.d.mts.map → index-rtCXNxGO.d.mts.map} +1 -1
  75. package/dist/index.d.mts +16 -15
  76. package/dist/index.mjs +58 -58
  77. package/dist/preview/index.d.mts +5 -4
  78. package/dist/preview/index.mjs +12 -12
  79. package/dist/{preview-BUtt481A.mjs → preview-PDz7o2xg.mjs} +323 -35
  80. package/dist/preview-PDz7o2xg.mjs.map +1 -0
  81. package/dist/preview-engine/audio.mjs +1 -1
  82. package/dist/preview-engine/chunk-4P3MMJWD.mjs +1 -0
  83. package/dist/preview-engine/{chunk-4JNIEQS2.mjs → chunk-77WWW75O.mjs} +1 -1
  84. package/dist/preview-engine/{chunk-UKZVUYB6.mjs → chunk-7M5LE6EM.mjs} +1 -1
  85. package/dist/preview-engine/{chunk-KBCZKIIQ.mjs → chunk-CYM75INB.mjs} +1 -1
  86. package/dist/preview-engine/chunk-FRJPXWAG.mjs +1 -0
  87. package/dist/preview-engine/{chunk-FJTURGJV.mjs → chunk-IEEV5RB3.mjs} +1 -1
  88. package/dist/preview-engine/chunk-LZNHGH56.mjs +5 -0
  89. package/dist/preview-engine/{chunk-RGKS6YIA.mjs → chunk-N2VISDTG.mjs} +1 -1
  90. package/dist/preview-engine/{chunk-O75BFM4S.mjs → chunk-NVXFEDJS.mjs} +1 -1
  91. package/dist/preview-engine/{chunk-VUO4K52B.mjs → chunk-PD2HKW2S.mjs} +1 -1
  92. package/dist/preview-engine/{chunk-HTAHYSCW.mjs → chunk-R4H52Q7S.mjs} +1 -1
  93. package/dist/preview-engine/{chunk-6O7UDVNL.mjs → chunk-RYSV44B4.mjs} +1 -1
  94. package/dist/preview-engine/{chunk-JAUMCOOJ.mjs → chunk-SMHEMYCV.mjs} +1 -1
  95. package/dist/preview-engine/{chunk-TKXOSEIJ.mjs → chunk-SV3ZNZQU.mjs} +1 -1
  96. package/dist/preview-engine/{chunk-32WC4FRR.mjs → chunk-UE7Y65C3.mjs} +3 -3
  97. package/dist/preview-engine/chunk-UFPA36D2.mjs +2227 -0
  98. package/dist/preview-engine/{chunk-M4QVCQ3O.mjs → chunk-VMXJZ4KQ.mjs} +1 -1
  99. package/dist/preview-engine/{chunk-EYKN2VET.mjs → chunk-XYCR3STG.mjs} +1 -1
  100. package/dist/preview-engine/components.mjs +1 -1
  101. package/dist/preview-engine/effects.mjs +1 -1
  102. package/dist/preview-engine/framefields.mjs +1 -1
  103. package/dist/preview-engine/player.mjs +5 -5
  104. package/dist/preview-engine/{renderers-L6GFGHS6.mjs → renderers-AFTUFMQQ.mjs} +1 -1
  105. package/dist/preview-engine/renderers-DU7KPFVV.mjs +1 -1
  106. package/dist/preview-engine/{renderers-PREFONJG.mjs → renderers-EPSF5CSQ.mjs} +1 -1
  107. package/dist/preview-engine/{renderers-R22CDFO4.mjs → renderers-OJWWIVNW.mjs} +1 -1
  108. package/dist/preview-engine/{renderers-TS32FDV7.mjs → renderers-RHMRWX46.mjs} +1 -1
  109. package/dist/preview-engine/{renderers-PSBTV2DO.mjs → renderers-TTXTV4PC.mjs} +1 -1
  110. package/dist/preview-engine/renderers-VEHYARKY.mjs +1 -0
  111. package/dist/preview-engine/renderers-VRXAG3FR.mjs +1 -0
  112. package/dist/preview-engine/renderers-ZHSOWEMQ.mjs +1 -0
  113. package/dist/preview-engine/renderers-ZMDRNYSS.mjs +1 -0
  114. package/dist/preview-engine/signals.mjs +1 -1
  115. package/dist/preview-engine/{src-GPF7RIBU.mjs → src-YXNX4MLK.mjs} +1 -1
  116. package/dist/{program-Cvv_nb9T.mjs → program-Bn6ko_I4.mjs} +4 -4
  117. package/dist/{program-Cvv_nb9T.mjs.map → program-Bn6ko_I4.mjs.map} +1 -1
  118. package/dist/renderer/index.d.mts +4 -3
  119. package/dist/renderer/index.mjs +3 -3
  120. package/dist/{renderer-CZClDMgF.mjs → renderer--Q0pM9Vh.mjs} +5 -5
  121. package/dist/{renderer-CZClDMgF.mjs.map → renderer--Q0pM9Vh.mjs.map} +1 -1
  122. package/dist/renderer-1aSF5BmY.mjs +5 -0
  123. package/dist/{renderer-tRi3KNoG.mjs → renderer-45ifiDkn.mjs} +5 -5
  124. package/dist/{renderer-tRi3KNoG.mjs.map → renderer-45ifiDkn.mjs.map} +1 -1
  125. package/dist/{renderer-BTd6tFcS.mjs → renderer-549d94qG.mjs} +5 -5
  126. package/dist/{renderer-BTd6tFcS.mjs.map → renderer-549d94qG.mjs.map} +1 -1
  127. package/dist/{renderer-CMCmljb0.mjs → renderer-B-LUGB9h.mjs} +3 -3
  128. package/dist/{renderer-CMCmljb0.mjs.map → renderer-B-LUGB9h.mjs.map} +1 -1
  129. package/dist/renderer-B2e4Gr9u.mjs +5 -0
  130. package/dist/{renderer-sMFJtt_H.mjs → renderer-B5b-ehRb.mjs} +3 -3
  131. package/dist/{renderer-sMFJtt_H.mjs.map → renderer-B5b-ehRb.mjs.map} +1 -1
  132. package/dist/renderer-B6fz4j50.mjs +5 -0
  133. package/dist/{renderer-BJEexai1.mjs → renderer-BCTUqJG7.mjs} +5 -5
  134. package/dist/{renderer-BJEexai1.mjs.map → renderer-BCTUqJG7.mjs.map} +1 -1
  135. package/dist/renderer-BEftIYw-.mjs +5 -0
  136. package/dist/{renderer-smP1F57W.mjs → renderer-BHPgkoEL.mjs} +4 -4
  137. package/dist/{renderer-smP1F57W.mjs.map → renderer-BHPgkoEL.mjs.map} +1 -1
  138. package/dist/renderer-BHTnO-7e.mjs +5 -0
  139. package/dist/{renderer-LrAldCWN.mjs → renderer-BIieU9pY.mjs} +5 -5
  140. package/dist/{renderer-LrAldCWN.mjs.map → renderer-BIieU9pY.mjs.map} +1 -1
  141. package/dist/{renderer-snjhPaP-.mjs → renderer-BKi6jDi_.mjs} +4 -4
  142. package/dist/{renderer-snjhPaP-.mjs.map → renderer-BKi6jDi_.mjs.map} +1 -1
  143. package/dist/renderer-BMlnQqTO.mjs +5 -0
  144. package/dist/{renderer-C2kFIZ4r.mjs → renderer-BMpmmYOq.mjs} +4 -4
  145. package/dist/{renderer-C2kFIZ4r.mjs.map → renderer-BMpmmYOq.mjs.map} +1 -1
  146. package/dist/{renderer-_KIBvES8.mjs → renderer-BO_wuUKA.mjs} +5 -5
  147. package/dist/{renderer-_KIBvES8.mjs.map → renderer-BO_wuUKA.mjs.map} +1 -1
  148. package/dist/renderer-BOzcFezY.mjs +5 -0
  149. package/dist/{renderer-DLaUT6JZ.mjs → renderer-BPOh9x5X.mjs} +4 -4
  150. package/dist/{renderer-DLaUT6JZ.mjs.map → renderer-BPOh9x5X.mjs.map} +1 -1
  151. package/dist/{renderer-CNpq7rL-.mjs → renderer-BPiWsrC2.mjs} +3 -3
  152. package/dist/{renderer-CNpq7rL-.mjs.map → renderer-BPiWsrC2.mjs.map} +1 -1
  153. package/dist/{renderer-t1sXDiqm.mjs → renderer-BUj7jE6t.mjs} +3 -3
  154. package/dist/{renderer-t1sXDiqm.mjs.map → renderer-BUj7jE6t.mjs.map} +1 -1
  155. package/dist/renderer-BVbjJIKJ.mjs +5 -0
  156. package/dist/renderer-BXsHKf4k.mjs +5 -0
  157. package/dist/{renderer-rKw5_EjG.mjs → renderer-BZgJj8Cl.mjs} +4 -4
  158. package/dist/{renderer-rKw5_EjG.mjs.map → renderer-BZgJj8Cl.mjs.map} +1 -1
  159. package/dist/{renderer-5fGj_tqN.mjs → renderer-BgjPbgbn.mjs} +6 -6
  160. package/dist/{renderer-5fGj_tqN.mjs.map → renderer-BgjPbgbn.mjs.map} +1 -1
  161. package/dist/{renderer-D3QPNBEj.mjs → renderer-BjgFpwVK.mjs} +5 -5
  162. package/dist/{renderer-D3QPNBEj.mjs.map → renderer-BjgFpwVK.mjs.map} +1 -1
  163. package/dist/renderer-Bks49NVl.mjs +5 -0
  164. package/dist/{renderer-HhJPFidU.mjs → renderer-BlZgyBSo.mjs} +5 -5
  165. package/dist/{renderer-HhJPFidU.mjs.map → renderer-BlZgyBSo.mjs.map} +1 -1
  166. package/dist/{renderer-DO_zXwMJ.mjs → renderer-BqUAyzCZ.mjs} +5 -5
  167. package/dist/{renderer-DO_zXwMJ.mjs.map → renderer-BqUAyzCZ.mjs.map} +1 -1
  168. package/dist/{renderer-O4y02xkD.mjs → renderer-Br8km655.mjs} +4 -4
  169. package/dist/{renderer-O4y02xkD.mjs.map → renderer-Br8km655.mjs.map} +1 -1
  170. package/dist/{renderer-DEoerd-j.mjs → renderer-BsMZ5Iaq.mjs} +4 -4
  171. package/dist/{renderer-DEoerd-j.mjs.map → renderer-BsMZ5Iaq.mjs.map} +1 -1
  172. package/dist/{renderer-BBjkX0Vt.mjs → renderer-BtgqTg2K.mjs} +3 -3
  173. package/dist/{renderer-BOg8i8eF.mjs → renderer-BuvKGwk3.mjs} +1 -1
  174. package/dist/{renderer-BOg8i8eF.mjs.map → renderer-BuvKGwk3.mjs.map} +1 -1
  175. package/dist/{renderer-DsPLMzy1.mjs → renderer-C-3qhk5x.mjs} +2 -2
  176. package/dist/{renderer-DsPLMzy1.mjs.map → renderer-C-3qhk5x.mjs.map} +1 -1
  177. package/dist/{renderer-BwV-o_1b.mjs → renderer-C-GTxnfv.mjs} +4 -4
  178. package/dist/{renderer-BwV-o_1b.mjs.map → renderer-C-GTxnfv.mjs.map} +1 -1
  179. package/dist/renderer-C-t7qFKr.mjs +5 -0
  180. package/dist/{renderer-Bxiiar50.mjs → renderer-C1ctHdXl.mjs} +4 -4
  181. package/dist/{renderer-Bxiiar50.mjs.map → renderer-C1ctHdXl.mjs.map} +1 -1
  182. package/dist/renderer-C24n-6CX.mjs +6 -0
  183. package/dist/{renderer-xNOKSN3V.mjs → renderer-C7m7Yxgc.mjs} +5 -5
  184. package/dist/{renderer-xNOKSN3V.mjs.map → renderer-C7m7Yxgc.mjs.map} +1 -1
  185. package/dist/{renderer-4uZGSmUD.mjs → renderer-C9dqx3U7.mjs} +5 -5
  186. package/dist/{renderer-4uZGSmUD.mjs.map → renderer-C9dqx3U7.mjs.map} +1 -1
  187. package/dist/renderer-CCReX-7M.mjs +5 -0
  188. package/dist/{renderer-CtpEzVBn.mjs → renderer-CE4535aW.mjs} +3 -3
  189. package/dist/{renderer-CtpEzVBn.mjs.map → renderer-CE4535aW.mjs.map} +1 -1
  190. package/dist/renderer-CIxFQrAm.mjs +5 -0
  191. package/dist/{renderer-6g1ri445.mjs → renderer-CL-vyXgX.mjs} +5 -5
  192. package/dist/{renderer-6g1ri445.mjs.map → renderer-CL-vyXgX.mjs.map} +1 -1
  193. package/dist/renderer-CLHBMIqJ.mjs +5 -0
  194. package/dist/renderer-CMJKi-Ye.mjs +5 -0
  195. package/dist/{renderer-Bf7Z7WT5.mjs → renderer-CMnlgAGs.mjs} +4 -4
  196. package/dist/{renderer-Bf7Z7WT5.mjs.map → renderer-CMnlgAGs.mjs.map} +1 -1
  197. package/dist/{renderer-uA0UCxjA.mjs → renderer-CQFMyC_c.mjs} +4 -4
  198. package/dist/{renderer-uA0UCxjA.mjs.map → renderer-CQFMyC_c.mjs.map} +1 -1
  199. package/dist/{renderer-DKFaVaRJ.mjs → renderer-CYwVNbUh.mjs} +4 -4
  200. package/dist/{renderer-DKFaVaRJ.mjs.map → renderer-CYwVNbUh.mjs.map} +1 -1
  201. package/dist/{renderer-DZIxduEt.mjs → renderer-CZ5mwBW1.mjs} +3 -3
  202. package/dist/{renderer-DZIxduEt.mjs.map → renderer-CZ5mwBW1.mjs.map} +1 -1
  203. package/dist/{renderer-BSsKlcHk.mjs → renderer-C_1eqfI0.mjs} +5 -5
  204. package/dist/{renderer-BSsKlcHk.mjs.map → renderer-C_1eqfI0.mjs.map} +1 -1
  205. package/dist/renderer-C_H3mHZa.mjs +5 -0
  206. package/dist/{renderer-CGpi8CDT.mjs → renderer-CciiDHuU.mjs} +4 -4
  207. package/dist/{renderer-CGpi8CDT.mjs.map → renderer-CciiDHuU.mjs.map} +1 -1
  208. package/dist/renderer-CfkTdR5B.mjs +5 -0
  209. package/dist/{renderer-DGXqspB9.mjs → renderer-CgK7Q1G8.mjs} +3 -3
  210. package/dist/{renderer-B09I95bo.mjs → renderer-CnL8Cmmr.mjs} +3 -3
  211. package/dist/renderer-CnhkXJ0R.mjs +5 -0
  212. package/dist/{renderer-BwJ0nXXu.mjs → renderer-Cp_HOmp7.mjs} +5 -5
  213. package/dist/{renderer-BwJ0nXXu.mjs.map → renderer-Cp_HOmp7.mjs.map} +1 -1
  214. package/dist/renderer-CqpyVsq_.mjs +5 -0
  215. package/dist/renderer-CtWgIpTE.mjs +5 -0
  216. package/dist/{renderer-C3CGYjrC.mjs → renderer-Cu3iKMSJ.mjs} +5 -5
  217. package/dist/{renderer-C3CGYjrC.mjs.map → renderer-Cu3iKMSJ.mjs.map} +1 -1
  218. package/dist/{renderer-BzTj_CeK.mjs → renderer-CuPAQjDK.mjs} +4 -4
  219. package/dist/{renderer-BzTj_CeK.mjs.map → renderer-CuPAQjDK.mjs.map} +1 -1
  220. package/dist/{renderer-FvvywNvv.mjs → renderer-CwlY8Tb-.mjs} +3 -3
  221. package/dist/{renderer-FvvywNvv.mjs.map → renderer-CwlY8Tb-.mjs.map} +1 -1
  222. package/dist/{renderer-ByFPmHBC.mjs → renderer-CxSFvKd1.mjs} +4 -4
  223. package/dist/{renderer-ByFPmHBC.mjs.map → renderer-CxSFvKd1.mjs.map} +1 -1
  224. package/dist/{renderer-DL3o_lG1.mjs → renderer-CyUiXLRa.mjs} +5 -5
  225. package/dist/{renderer-DL3o_lG1.mjs.map → renderer-CyUiXLRa.mjs.map} +1 -1
  226. package/dist/renderer-CyuKr5ca.mjs +5 -0
  227. package/dist/renderer-CzgcZXKH.mjs +3 -0
  228. package/dist/{renderer-DCMoBppL.mjs → renderer-D-GWBoVT.mjs} +3 -3
  229. package/dist/{renderer-DCMoBppL.mjs.map → renderer-D-GWBoVT.mjs.map} +1 -1
  230. package/dist/{renderer-IAffbHXx.mjs → renderer-D-fzEZfX.mjs} +4 -4
  231. package/dist/{renderer-IAffbHXx.mjs.map → renderer-D-fzEZfX.mjs.map} +1 -1
  232. package/dist/renderer-D5yp74NL.mjs +3 -0
  233. package/dist/{renderer-BC_Nse6h.mjs → renderer-D8gN7aqk.mjs} +4 -4
  234. package/dist/{renderer-BC_Nse6h.mjs.map → renderer-D8gN7aqk.mjs.map} +1 -1
  235. package/dist/renderer-D9ON_1Hf.mjs +5 -0
  236. package/dist/renderer-DAnTgh4o.mjs +5 -0
  237. package/dist/{renderer-Dak_wVh9.mjs → renderer-DGOMfyh8.mjs} +2 -2
  238. package/dist/{renderer-Dak_wVh9.mjs.map → renderer-DGOMfyh8.mjs.map} +1 -1
  239. package/dist/{renderer-CInMMs5x.mjs → renderer-DGb_wgTW.mjs} +6 -6
  240. package/dist/{renderer-CInMMs5x.mjs.map → renderer-DGb_wgTW.mjs.map} +1 -1
  241. package/dist/{renderer-DO1SZ5xY.mjs → renderer-DJPZs_zV.mjs} +5 -5
  242. package/dist/{renderer-DO1SZ5xY.mjs.map → renderer-DJPZs_zV.mjs.map} +1 -1
  243. package/dist/renderer-DKJOon6y.d.mts +1 -0
  244. package/dist/{renderer-DQJHjU0L.mjs → renderer-DOZPZTxe.mjs} +5 -5
  245. package/dist/{renderer-DQJHjU0L.mjs.map → renderer-DOZPZTxe.mjs.map} +1 -1
  246. package/dist/{renderer-DaY04IyU.mjs → renderer-DRal7Goa.mjs} +5 -5
  247. package/dist/{renderer-DaY04IyU.mjs.map → renderer-DRal7Goa.mjs.map} +1 -1
  248. package/dist/renderer-DWgpivA3.mjs +5 -0
  249. package/dist/{renderer-qVJdxbXB.mjs → renderer-DXFJv_e6.mjs} +4 -4
  250. package/dist/{renderer-qVJdxbXB.mjs.map → renderer-DXFJv_e6.mjs.map} +1 -1
  251. package/dist/renderer-Dh_qNNwR.mjs +5 -0
  252. package/dist/renderer-DkCpXPMP.mjs +5 -0
  253. package/dist/{renderer-PnnkUWm-.mjs → renderer-Dp5ChuOs.mjs} +4 -4
  254. package/dist/{renderer-PnnkUWm-.mjs.map → renderer-Dp5ChuOs.mjs.map} +1 -1
  255. package/dist/{renderer-C_gR2H3R.mjs → renderer-DpZballM.mjs} +3 -3
  256. package/dist/{renderer-C_gR2H3R.mjs.map → renderer-DpZballM.mjs.map} +1 -1
  257. package/dist/renderer-Dre-6cDR.mjs +5 -0
  258. package/dist/renderer-Ds5z4_HX.mjs +5 -0
  259. package/dist/{renderer-b0H3oDae.mjs → renderer-DwGlDNOV.mjs} +3 -3
  260. package/dist/{renderer-b0H3oDae.mjs.map → renderer-DwGlDNOV.mjs.map} +1 -1
  261. package/dist/{renderer-oBgCEqaM.mjs → renderer-DxB_OfLs.mjs} +4 -4
  262. package/dist/{renderer-oBgCEqaM.mjs.map → renderer-DxB_OfLs.mjs.map} +1 -1
  263. package/dist/{renderer-BvRM3OZ6.mjs → renderer-Dz6P-rPI.mjs} +3 -3
  264. package/dist/{renderer-BvRM3OZ6.mjs.map → renderer-Dz6P-rPI.mjs.map} +1 -1
  265. package/dist/{renderer-DrL3J9ci.mjs → renderer-FPiLBwj5.mjs} +4 -4
  266. package/dist/{renderer-DrL3J9ci.mjs.map → renderer-FPiLBwj5.mjs.map} +1 -1
  267. package/dist/renderer-HGSCOMyP.mjs +5 -0
  268. package/dist/renderer-KMY8W-cJ.mjs +5 -0
  269. package/dist/{renderer-BXGuCnCJ.mjs → renderer-KgsVk9c6.mjs} +4 -4
  270. package/dist/{renderer-BXGuCnCJ.mjs.map → renderer-KgsVk9c6.mjs.map} +1 -1
  271. package/dist/{renderer-CLTRTtQ8.mjs → renderer-LXhEPCmy.mjs} +5 -5
  272. package/dist/{renderer-CLTRTtQ8.mjs.map → renderer-LXhEPCmy.mjs.map} +1 -1
  273. package/dist/{renderer-CN-mCIoI.mjs → renderer-NBMmvqWl.mjs} +5 -5
  274. package/dist/{renderer-CN-mCIoI.mjs.map → renderer-NBMmvqWl.mjs.map} +1 -1
  275. package/dist/{renderer-HXw4cJZx.mjs → renderer-Nnu32rqg.mjs} +3 -3
  276. package/dist/{renderer-HXw4cJZx.mjs.map → renderer-Nnu32rqg.mjs.map} +1 -1
  277. package/dist/renderer-R21YvXz3.mjs +5 -0
  278. package/dist/{renderer-Dj54y3h3.mjs → renderer-RAq3LnNy.mjs} +3 -3
  279. package/dist/{renderer-Dj54y3h3.mjs.map → renderer-RAq3LnNy.mjs.map} +1 -1
  280. package/dist/renderer-RtzCz37W.mjs +5 -0
  281. package/dist/{renderer-CiHVnhUk.mjs → renderer-RzkU_O1i.mjs} +5 -5
  282. package/dist/{renderer-CiHVnhUk.mjs.map → renderer-RzkU_O1i.mjs.map} +1 -1
  283. package/dist/{renderer-D3YbHjRG.mjs → renderer-S9tVGneU.mjs} +95 -80
  284. package/dist/renderer-S9tVGneU.mjs.map +1 -0
  285. package/dist/{renderer-DP9ScNM6.mjs → renderer-SJyp9-62.mjs} +3 -3
  286. package/dist/{renderer-DP9ScNM6.mjs.map → renderer-SJyp9-62.mjs.map} +1 -1
  287. package/dist/{renderer-TiaHrU5z.mjs → renderer-_54hiCq0.mjs} +5 -5
  288. package/dist/{renderer-TiaHrU5z.mjs.map → renderer-_54hiCq0.mjs.map} +1 -1
  289. package/dist/{renderer-CcmxR6Fy.d.mts → renderer-aRk849b3.d.mts} +2 -2
  290. package/dist/{renderer-CcmxR6Fy.d.mts.map → renderer-aRk849b3.d.mts.map} +1 -1
  291. package/dist/{renderer-Dy1xQOTu.mjs → renderer-dGEMVaZ3.mjs} +4 -4
  292. package/dist/{renderer-Dy1xQOTu.mjs.map → renderer-dGEMVaZ3.mjs.map} +1 -1
  293. package/dist/{renderer-Dp9FQKVP.mjs → renderer-dRXP2dJU.mjs} +5 -5
  294. package/dist/{renderer-Dp9FQKVP.mjs.map → renderer-dRXP2dJU.mjs.map} +1 -1
  295. package/dist/{renderer-DwH5e3hx.mjs → renderer-g9SstkTz.mjs} +3 -3
  296. package/dist/renderer-iMrqAjix.mjs +5 -0
  297. package/dist/{renderer-DX60Kr20.mjs → renderer-opVuiAQR.mjs} +3 -3
  298. package/dist/{renderer-DX60Kr20.mjs.map → renderer-opVuiAQR.mjs.map} +1 -1
  299. package/dist/{renderer-DrK6pyfz.mjs → renderer-puQhVfDS.mjs} +5 -5
  300. package/dist/{renderer-DrK6pyfz.mjs.map → renderer-puQhVfDS.mjs.map} +1 -1
  301. package/dist/renderer-sMed1u1O.mjs +5 -0
  302. package/dist/renderer-tsAuo46l.mjs +5 -0
  303. package/dist/{renderer-DaLy1dFA.mjs → renderer-vll8LX0I.mjs} +9 -9
  304. package/dist/{renderer-DaLy1dFA.mjs.map → renderer-vll8LX0I.mjs.map} +1 -1
  305. package/dist/{renderers-CP8CFWDs-DWRjjeUg.mjs → renderers-CP8CFWDs-BRQyvcut.mjs} +4 -4
  306. package/dist/{renderers-CP8CFWDs-DWRjjeUg.mjs.map → renderers-CP8CFWDs-BRQyvcut.mjs.map} +1 -1
  307. package/dist/sam/index.d.mts +3 -3
  308. package/dist/sam/index.mjs +1 -1
  309. package/dist/signals/index.d.mts +7 -7
  310. package/dist/signals/index.mjs +8 -8
  311. package/dist/{signals-BfJ1aqpT.mjs → signals-tiho_9fp.mjs} +4 -4
  312. package/dist/{signals-BfJ1aqpT.mjs.map → signals-tiho_9fp.mjs.map} +1 -1
  313. package/dist/{src-BU6vm9sP-DFJ3phW0.mjs → src-BU6vm9sP-DdTHmCr4.mjs} +3 -3
  314. package/dist/{src-BU6vm9sP-DFJ3phW0.mjs.map → src-BU6vm9sP-DdTHmCr4.mjs.map} +1 -1
  315. package/dist/{src-D7M8VTzv.mjs → src-BzFGotRc.mjs} +11 -11
  316. package/dist/{src-D7M8VTzv.mjs.map → src-BzFGotRc.mjs.map} +1 -1
  317. package/dist/storage/index.d.mts +206 -0
  318. package/dist/storage/index.d.mts.map +1 -0
  319. package/dist/storage/index.mjs +3 -0
  320. package/package.json +67 -59
  321. package/dist/audio-afTBdB3U.d.mts.map +0 -1
  322. package/dist/cloud-COid1Ipa.mjs.map +0 -1
  323. package/dist/dist-B-OPY7Cs.mjs.map +0 -1
  324. package/dist/dist-BSqeChht.mjs.map +0 -1
  325. package/dist/index-BNClElng.d.mts.map +0 -1
  326. package/dist/index-CTv9ZieD.d.mts.map +0 -1
  327. package/dist/index-CdCrae-I.d.mts.map +0 -1
  328. package/dist/index-Fliv2Z-w.d.mts.map +0 -1
  329. package/dist/index-gOVtTm-P.d.mts.map +0 -1
  330. package/dist/preview-BUtt481A.mjs.map +0 -1
  331. package/dist/preview-engine/chunk-5SLBE2FX.mjs +0 -1
  332. package/dist/preview-engine/chunk-74J4DJQA.mjs +0 -1
  333. package/dist/preview-engine/chunk-KIPXBOYG.mjs +0 -1974
  334. package/dist/preview-engine/chunk-P4Y3PMJF.mjs +0 -1
  335. package/dist/preview-engine/chunk-SE2C623Z.mjs +0 -5
  336. package/dist/preview-engine/renderers-TEKHQHCL.mjs +0 -1
  337. package/dist/preview-engine/renderers-U3RLYFCN.mjs +0 -1
  338. package/dist/preview-engine/renderers-V5HM6PZ2.mjs +0 -1
  339. package/dist/preview-engine/renderers-ZGX3A3QZ.mjs +0 -1
  340. package/dist/renderer--RJepuOy.mjs +0 -5
  341. package/dist/renderer-B1U6YRRV.d.mts +0 -117
  342. package/dist/renderer-B1U6YRRV.d.mts.map +0 -1
  343. package/dist/renderer-B4NFnaty.mjs +0 -5
  344. package/dist/renderer-B6g4ts0e.mjs +0 -5
  345. package/dist/renderer-BGoAr-tl.mjs +0 -5
  346. package/dist/renderer-BSOdBgdE.mjs +0 -5
  347. package/dist/renderer-BU6O0fpM.mjs +0 -5
  348. package/dist/renderer-BZ97iidG.mjs +0 -5
  349. package/dist/renderer-B_Klh1VT.mjs +0 -5
  350. package/dist/renderer-BaWQM1y-.mjs +0 -5
  351. package/dist/renderer-Bc0jvAj0.mjs +0 -5
  352. package/dist/renderer-Bd-NuU3M.mjs +0 -3
  353. package/dist/renderer-Bm077kZ6.mjs +0 -5
  354. package/dist/renderer-BtzE_e_Y.mjs +0 -5
  355. package/dist/renderer-C225eCAo.mjs +0 -5
  356. package/dist/renderer-CC4fhNup.mjs +0 -3
  357. package/dist/renderer-CLXdR4vz.mjs +0 -5
  358. package/dist/renderer-CszM8B3C.mjs +0 -5
  359. package/dist/renderer-Ctp8ZYfk.mjs +0 -5
  360. package/dist/renderer-CxQdSp8I.mjs +0 -5
  361. package/dist/renderer-D3YbHjRG.mjs.map +0 -1
  362. package/dist/renderer-D4GMRtDd.mjs +0 -6
  363. package/dist/renderer-DEsGIvTZ.mjs +0 -5
  364. package/dist/renderer-DIaUQ0EP.mjs +0 -5
  365. package/dist/renderer-DLjqcNzQ.mjs +0 -5
  366. package/dist/renderer-DMuQZa51.mjs +0 -5
  367. package/dist/renderer-DOgi2aF2.mjs +0 -5
  368. package/dist/renderer-DSh7cvi4.mjs +0 -5
  369. package/dist/renderer-DV1LVBBP.mjs +0 -5
  370. package/dist/renderer-Dhrj2bJz.mjs +0 -5
  371. package/dist/renderer-DoFUu1R4.mjs +0 -5
  372. package/dist/renderer-DsydX3cx.mjs +0 -5
  373. package/dist/renderer-DxVSoeYi.mjs +0 -5
  374. package/dist/renderer-Nc9bHb0n.mjs +0 -5
  375. package/dist/renderer-TFaSD2Db.mjs +0 -5
  376. package/dist/renderer-Z61ctppe.mjs +0 -5
  377. package/dist/renderer-awXf3sNS.mjs +0 -5
  378. package/dist/renderer-cHT28oYI.mjs +0 -5
  379. package/dist/renderer-g7Y3bFot.mjs +0 -5
  380. package/dist/renderer-qVv0OzVc.mjs +0 -5
  381. /package/dist/{chunk-W71TSjRM.mjs → chunk-DOL2i2sR.mjs} +0 -0
  382. /package/dist/{renderer-B6rZUBwE.mjs → renderer-Co2YqWX0.mjs} +0 -0
@@ -0,0 +1,502 @@
1
+ import { createReadStream, createWriteStream, existsSync } from "node:fs";
2
+ import { dirname, join, relative, sep } from "node:path";
3
+ import { mkdir, open, readFile, rename, rm } from "node:fs/promises";
4
+ import { createHash, randomBytes } from "node:crypto";
5
+ import { AwsClient } from "aws4fetch";
6
+ import { Readable, Transform } from "node:stream";
7
+ import { pipeline } from "node:stream/promises";
8
+
9
+ //#region ../storage/dist/index.mjs
10
+ /**
11
+ * Hashing and verified downloads: every byte an asset contributes is checked
12
+ * against the sha256 its manifest entry pins.
13
+ */
14
+ var AssetError = class extends Error {
15
+ name = "AssetError";
16
+ constructor(code, message, options) {
17
+ super(message, options);
18
+ this.code = code;
19
+ }
20
+ };
21
+ async function hashFile(path$1) {
22
+ const hash = createHash("sha256");
23
+ let size = 0;
24
+ for await (const chunk of createReadStream(path$1)) {
25
+ hash.update(chunk);
26
+ size += chunk.length;
27
+ }
28
+ return {
29
+ sha256: hash.digest("hex"),
30
+ size
31
+ };
32
+ }
33
+ /**
34
+ * Downloads `url` to `dest` through a temporary file, and only renames it
35
+ * into place once its size and sha256 match `expected`.
36
+ */
37
+ async function downloadVerified(url, dest, expected, options = {}) {
38
+ const attempts = options.attempts ?? 3;
39
+ for (let attempt = 1;; attempt++) try {
40
+ await downloadOnce(url, dest, expected, options);
41
+ return;
42
+ } catch (err) {
43
+ if (!(err instanceof AssetError ? err.code === "ASSET_DOWNLOAD_FAILED" : !options.signal?.aborted) || attempt >= attempts) throw err;
44
+ await new Promise((r) => setTimeout(r, 500 * 2 ** attempt));
45
+ }
46
+ }
47
+ async function downloadOnce(url, dest, expected, options) {
48
+ const shown = redactQuery(url);
49
+ const res = await (options.fetch ?? fetch)(url, { signal: options.signal });
50
+ if (!res.ok || !res.body) {
51
+ await res.body?.cancel();
52
+ if (res.status === 404) throw new AssetError("ASSET_NOT_FOUND", `${shown} returned 404`);
53
+ if (res.status === 401 || res.status === 403) throw new AssetError("ASSET_FORBIDDEN", `${shown} returned ${res.status}: the bucket isn't public there, or the signed URL expired`);
54
+ throw new AssetError("ASSET_DOWNLOAD_FAILED", `${shown} returned ${res.status}`);
55
+ }
56
+ await mkdir(dirname(dest), { recursive: true });
57
+ const temp = `${dest}.${randomBytes(4).toString("hex")}.part`;
58
+ const hash = createHash("sha256");
59
+ let size = 0;
60
+ const tap = new Transform({ transform(chunk, _encoding, done) {
61
+ size += chunk.length;
62
+ if (size > expected.size) return done(new AssetError("ASSET_HASH_MISMATCH", `${shown} is larger than the ${expected.size} bytes framefields.json pins`));
63
+ hash.update(chunk);
64
+ done(null, chunk);
65
+ } });
66
+ try {
67
+ await pipeline(Readable.fromWeb(res.body), tap, createWriteStream(temp), { signal: options.signal }).catch((err) => {
68
+ if (err instanceof AssetError || options.signal?.aborted) throw err;
69
+ throw new AssetError("ASSET_DOWNLOAD_FAILED", `${shown}: ${err.message}`, { cause: err });
70
+ });
71
+ const sha256 = hash.digest("hex");
72
+ if (size !== expected.size || sha256 !== expected.sha256) throw new AssetError("ASSET_HASH_MISMATCH", `${shown} is not the file framefields.json pins (got ${size} bytes, sha256 ${sha256.slice(0, 12)}…; expected ${expected.size} bytes, ${expected.sha256.slice(0, 12)}…)`);
73
+ await rename(temp, dest);
74
+ } finally {
75
+ await rm(temp, { force: true });
76
+ }
77
+ }
78
+ /** Signed URLs carry credentials in the query: never print them. */
79
+ function redactQuery(url) {
80
+ const q = url.indexOf("?");
81
+ return q < 0 ? url : `${url.slice(0, q)}?…`;
82
+ }
83
+ const TYPES = {
84
+ mp4: "video/mp4",
85
+ m4v: "video/mp4",
86
+ mov: "video/quicktime",
87
+ webm: "video/webm",
88
+ mkv: "video/x-matroska",
89
+ mp3: "audio/mpeg",
90
+ m4a: "audio/mp4",
91
+ aac: "audio/aac",
92
+ wav: "audio/wav",
93
+ flac: "audio/flac",
94
+ ogg: "audio/ogg",
95
+ png: "image/png",
96
+ jpg: "image/jpeg",
97
+ jpeg: "image/jpeg",
98
+ webp: "image/webp",
99
+ avif: "image/avif",
100
+ gif: "image/gif",
101
+ svg: "image/svg+xml",
102
+ json: "application/json",
103
+ lottie: "application/zip",
104
+ glb: "model/gltf-binary",
105
+ gltf: "model/gltf+json",
106
+ ttf: "font/ttf",
107
+ otf: "font/otf",
108
+ woff2: "font/woff2",
109
+ cube: "text/plain",
110
+ srt: "text/plain",
111
+ vtt: "text/vtt"
112
+ };
113
+ /** The Content-Type a CDN serves the file with. */
114
+ function contentType(path$1) {
115
+ return TYPES[path$1.slice(path$1.lastIndexOf(".") + 1).toLowerCase()] ?? "application/octet-stream";
116
+ }
117
+ const REMOTE_NAME = /^[A-Za-z0-9][\w-]{0,63}$/;
118
+ const SHA256 = /^[0-9a-f]{64}$/;
119
+ const FILE$1 = "framefields.json";
120
+ var ManifestError = class extends Error {
121
+ name = "ManifestError";
122
+ };
123
+ /** Validates `storage`; errors name the remote and field at fault. */
124
+ function parseStorage(value) {
125
+ if (!isRecord(value) || !isRecord(value.remotes)) throw new ManifestError(`${FILE$1}: "storage" needs "remotes", e.g. { "remotes": { "media": { "endpoint": "https://<account>.r2.cloudflarestorage.com", "bucket": "films" } } }`);
126
+ const remotes = {};
127
+ for (const [name, spec] of Object.entries(value.remotes)) remotes[name] = parseRemote(name, spec);
128
+ const names = Object.keys(remotes);
129
+ if (names.length === 0) throw new ManifestError(`${FILE$1}: "storage.remotes" is empty`);
130
+ if (value.default !== void 0 && !names.includes(value.default)) throw new ManifestError(`${FILE$1}: "storage.default" must name a remote (${names.join(", ")})`);
131
+ return {
132
+ ...typeof value.default === "string" && { default: value.default },
133
+ remotes
134
+ };
135
+ }
136
+ function parseRemote(name, spec) {
137
+ const fail = (message) => {
138
+ throw new ManifestError(`${FILE$1}: storage.remotes.${name} ${message}`);
139
+ };
140
+ if (!REMOTE_NAME.test(name)) fail("has an invalid name: use letters, digits, - and _ (at most 64)");
141
+ if (!isRecord(spec)) fail("must be an object with an endpoint and a bucket");
142
+ const s = spec;
143
+ if (!isHttpUrl(s.endpoint)) fail("needs \"endpoint\": the S3 API URL, e.g. \"https://<account>.r2.cloudflarestorage.com\"");
144
+ if (typeof s.bucket !== "string" || !/^[a-z0-9][a-z0-9.-]{1,62}$/.test(s.bucket)) fail("needs \"bucket\": the bucket name");
145
+ if (s.region !== void 0 && typeof s.region !== "string") fail("\"region\" must be a string");
146
+ if (s.prefix !== void 0 && (typeof s.prefix !== "string" || s.prefix.startsWith("/") || s.prefix.split("/").includes(".."))) fail("\"prefix\" must be a key prefix such as \"films/launch/\"");
147
+ if (s.publicUrl !== void 0 && !isHttpUrl(s.publicUrl)) fail("\"publicUrl\" must be an http(s) URL, e.g. \"https://media.example.com\"");
148
+ return {
149
+ endpoint: s.endpoint,
150
+ bucket: s.bucket,
151
+ ...s.region !== void 0 && { region: s.region },
152
+ ...typeof s.prefix === "string" && s.prefix && { prefix: normalizePrefix(s.prefix) },
153
+ ...s.publicUrl !== void 0 && { publicUrl: s.publicUrl }
154
+ };
155
+ }
156
+ /** Validates `assets`; errors name the path and field at fault. */
157
+ function parseAssets(value, storage) {
158
+ if (!isRecord(value)) throw new ManifestError(`${FILE$1}: "assets" must map project paths to { "sha256", "size" }`);
159
+ const out = {};
160
+ for (const [path$1, entry] of Object.entries(value)) {
161
+ const fail = (message) => {
162
+ throw new ManifestError(`${FILE$1}: assets["${path$1}"] ${message}`);
163
+ };
164
+ if (!isAssetPath(path$1)) fail("must be a path inside the project, e.g. assets/footage/intro.mp4");
165
+ if (!isRecord(entry)) fail("must be { \"sha256\", \"size\" }");
166
+ const e = entry;
167
+ if (typeof e.sha256 !== "string" || !SHA256.test(e.sha256)) fail("needs \"sha256\": 64 lowercase hex digits");
168
+ if (typeof e.size !== "number" || !Number.isSafeInteger(e.size) || e.size < 0) fail("needs \"size\" in bytes");
169
+ if (e.url !== void 0 && !isHttpUrl(e.url)) fail("\"url\" must be an http(s) URL");
170
+ if (e.remote !== void 0) {
171
+ if (typeof e.remote !== "string" || !storage?.remotes[e.remote]) fail(`"remote" must name a remote in "storage.remotes"`);
172
+ } else if (e.url === void 0 && !storage) fail("needs a \"url\", or a \"storage\" section with a remote to hold it");
173
+ out[path$1] = {
174
+ sha256: e.sha256,
175
+ size: e.size,
176
+ ...e.remote !== void 0 && { remote: e.remote },
177
+ ...e.url !== void 0 && { url: e.url }
178
+ };
179
+ }
180
+ return out;
181
+ }
182
+ /** The remote an asset (or a new one, without `name`) belongs to. */
183
+ function pickRemote(storage, name) {
184
+ const names = Object.keys(storage?.remotes ?? {});
185
+ const chosen = name ?? storage?.default ?? (names.length === 1 ? names[0] : void 0);
186
+ if (!storage || names.length === 0) throw new ManifestError(`${FILE$1} has no "storage" remotes: add one (an R2 or S3 bucket) first`);
187
+ if (!chosen) throw new ManifestError(`${FILE$1}: name the remote (${names.join(", ")}), or set "storage.default"`);
188
+ const remote = storage.remotes[chosen];
189
+ if (!remote) throw new ManifestError(`${FILE$1}: no remote named "${chosen}" (${names.join(", ")})`);
190
+ return {
191
+ name: chosen,
192
+ remote
193
+ };
194
+ }
195
+ /** The object key holding `sha256`: `<prefix>sha256/ab/<hash>`. */
196
+ function objectKey(sha256, prefix = "") {
197
+ return `${prefix}sha256/${sha256.slice(0, 2)}/${sha256}`;
198
+ }
199
+ /** The asset's URL on the remote's public domain, if it has one. */
200
+ function publicUrl(remote, sha256) {
201
+ if (!remote.publicUrl) return void 0;
202
+ return `${remote.publicUrl.replace(/\/+$/, "")}/${objectKey(sha256, remote.prefix)}`;
203
+ }
204
+ /**
205
+ * Where to download an asset without credentials: a signed URL handed in
206
+ * (`signed`, by sha256), its own `url`, or its remote's public domain.
207
+ * Undefined means the asset is on a private remote and needs a signature.
208
+ */
209
+ function readUrl(entry, storage, signed) {
210
+ const given = signed?.[entry.sha256];
211
+ if (given) return given;
212
+ if (entry.url) return entry.url;
213
+ if (!storage) return void 0;
214
+ return publicUrl(pickRemote(storage, entry.remote).remote, entry.sha256);
215
+ }
216
+ function isAssetPath(path$1) {
217
+ return path$1.length > 0 && path$1.length <= 1024 && !path$1.startsWith("/") && !path$1.includes("\\") && !path$1.split("/").some((part) => part === "" || part === "." || part === "..");
218
+ }
219
+ function normalizePrefix(prefix) {
220
+ return prefix.endsWith("/") ? prefix : `${prefix}/`;
221
+ }
222
+ function isHttpUrl(value) {
223
+ if (typeof value !== "string") return false;
224
+ try {
225
+ const { protocol } = new URL(value);
226
+ return protocol === "https:" || protocol === "http:";
227
+ } catch {
228
+ return false;
229
+ }
230
+ }
231
+ function isRecord(value) {
232
+ return typeof value === "object" && value !== null && !Array.isArray(value);
233
+ }
234
+ /**
235
+ * The few S3 calls asset storage needs (HEAD, PUT, multipart upload,
236
+ * presigned GET), signed with SigV4 by aws4fetch. Works with any
237
+ * S3-compatible service; R2 is the one to pick, since it charges no egress.
238
+ */
239
+ /**
240
+ * Keys for `remote` from the environment:
241
+ * `FRAMEFIELDS_STORAGE_<REMOTE>_ACCESS_KEY_ID` / `…_SECRET_ACCESS_KEY`
242
+ * (the remote's name upper-cased, `-` as `_`), else the standard
243
+ * `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`.
244
+ */
245
+ function credentialsFromEnv(remote, env = process.env) {
246
+ const scope = `FRAMEFIELDS_STORAGE_${remote.toUpperCase().replace(/-/g, "_")}`;
247
+ const own = env[`${scope}_ACCESS_KEY_ID`];
248
+ const ownSecret = env[`${scope}_SECRET_ACCESS_KEY`];
249
+ if (own && ownSecret) return {
250
+ accessKeyId: own,
251
+ secretAccessKey: ownSecret
252
+ };
253
+ const id = env.AWS_ACCESS_KEY_ID;
254
+ const secret = env.AWS_SECRET_ACCESS_KEY;
255
+ if (!id || !secret) return void 0;
256
+ return {
257
+ accessKeyId: id,
258
+ secretAccessKey: secret,
259
+ ...env.AWS_SESSION_TOKEN && { sessionToken: env.AWS_SESSION_TOKEN }
260
+ };
261
+ }
262
+ /** The env vars `credentialsFromEnv` reads for `remote`, for messages. */
263
+ function credentialEnvNames(remote) {
264
+ const scope = `FRAMEFIELDS_STORAGE_${remote.toUpperCase().replace(/-/g, "_")}`;
265
+ return [`${scope}_ACCESS_KEY_ID`, `${scope}_SECRET_ACCESS_KEY`];
266
+ }
267
+ var StorageError = class extends Error {
268
+ name = "StorageError";
269
+ constructor(message, status) {
270
+ super(message);
271
+ this.status = status;
272
+ }
273
+ };
274
+ const MiB = 1024 * 1024;
275
+ /**
276
+ * Content-addressed objects never change: CDNs and browsers may keep them
277
+ * forever, which is what makes a custom domain in front of the bucket cheap.
278
+ */
279
+ const IMMUTABLE = "public, max-age=31536000, immutable";
280
+ /** One remote's bucket, signed with `credentials`. */
281
+ var Bucket = class {
282
+ aws;
283
+ fetch;
284
+ constructor(remote, credentials, options = {}) {
285
+ this.remote = remote;
286
+ this.options = options;
287
+ this.aws = new AwsClient({
288
+ ...credentials,
289
+ service: "s3",
290
+ region: remote.region ?? "auto",
291
+ retries: 3
292
+ });
293
+ this.fetch = options.fetch ?? fetch;
294
+ }
295
+ keyFor(sha256) {
296
+ return objectKey(sha256, this.remote.prefix);
297
+ }
298
+ /** Whether the bucket holds `sha256` at the expected size. */
299
+ async has(sha256, size) {
300
+ const res = await this.send(this.keyFor(sha256), { method: "HEAD" });
301
+ if (res.status === 404) return false;
302
+ if (!res.ok) throw await this.failure("HEAD", res);
303
+ return Number(res.headers.get("content-length")) === size;
304
+ }
305
+ /**
306
+ * Uploads `file` (already hashed) under its content key. The bucket
307
+ * checks every byte against the sha256 sent with it.
308
+ */
309
+ async upload(file, digest, onProgress) {
310
+ const key = this.keyFor(digest.sha256);
311
+ const headers = {
312
+ "content-type": contentType(file),
313
+ "cache-control": IMMUTABLE
314
+ };
315
+ const threshold = this.options.multipartThreshold ?? 64 * MiB;
316
+ if (digest.size <= threshold) {
317
+ const handle = await open(file);
318
+ try {
319
+ const body = await handle.readFile();
320
+ await this.put(key, body, digest.sha256, headers);
321
+ } finally {
322
+ await handle.close();
323
+ }
324
+ onProgress?.({
325
+ sent: digest.size,
326
+ total: digest.size
327
+ });
328
+ return;
329
+ }
330
+ await this.uploadParts(file, key, digest.size, headers, onProgress);
331
+ }
332
+ /** A GET URL anyone can use until it expires (at most 7 days). */
333
+ async presign(sha256, expiresSec = 86400) {
334
+ const url = new URL(this.url(this.keyFor(sha256)));
335
+ url.searchParams.set("X-Amz-Expires", String(Math.min(expiresSec, 604800)));
336
+ return (await this.aws.sign(url, {
337
+ method: "GET",
338
+ aws: { signQuery: true }
339
+ })).url;
340
+ }
341
+ async put(key, body, sha256, headers, query = "") {
342
+ const res = await this.send(key, {
343
+ method: "PUT",
344
+ body,
345
+ headers: {
346
+ ...headers,
347
+ "x-amz-content-sha256": sha256
348
+ },
349
+ query
350
+ });
351
+ if (!res.ok) throw await this.failure("PUT", res);
352
+ return res;
353
+ }
354
+ async uploadParts(file, key, size, headers, onProgress) {
355
+ const partSize = Math.max(this.options.partSize ?? 16 * MiB, Math.ceil(size / 1e4), 5 * MiB);
356
+ const created = await this.send(key, {
357
+ method: "POST",
358
+ query: "uploads=",
359
+ headers
360
+ });
361
+ if (!created.ok) throw await this.failure("CreateMultipartUpload", created);
362
+ const uploadId = /<UploadId>([^<]+)<\/UploadId>/.exec(await created.text())?.[1];
363
+ if (!uploadId) throw new StorageError("CreateMultipartUpload returned no UploadId");
364
+ const id = encodeURIComponent(uploadId);
365
+ const count = Math.ceil(size / partSize);
366
+ const etags = new Array(count);
367
+ const handle = await open(file);
368
+ let next = 0;
369
+ let sent = 0;
370
+ const worker = async () => {
371
+ while (next < count) {
372
+ const index = next++;
373
+ const length = Math.min(partSize, size - index * partSize);
374
+ const chunk = Buffer.alloc(length);
375
+ await handle.read(chunk, 0, length, index * partSize);
376
+ const sha = createHash("sha256").update(chunk).digest("hex");
377
+ etags[index] = (await this.put(key, chunk, sha, {}, `partNumber=${index + 1}&uploadId=${id}`)).headers.get("etag") ?? "";
378
+ sent += length;
379
+ onProgress?.({
380
+ sent,
381
+ total: size
382
+ });
383
+ }
384
+ };
385
+ try {
386
+ await Promise.all(Array.from({ length: Math.min(this.options.concurrency ?? 4, count) }, worker));
387
+ const body = `<CompleteMultipartUpload>${etags.map((etag, i) => `<Part><PartNumber>${i + 1}</PartNumber><ETag>${escapeXml(etag)}</ETag></Part>`).join("")}</CompleteMultipartUpload>`;
388
+ const done = await this.send(key, {
389
+ method: "POST",
390
+ query: `uploadId=${id}`,
391
+ body,
392
+ headers: { "content-type": "application/xml" }
393
+ });
394
+ const text = await done.text();
395
+ if (!done.ok || text.includes("<Error>")) throw new StorageError(`CompleteMultipartUpload failed (${done.status}): ${errorCode(text)}`, done.status);
396
+ } catch (err) {
397
+ await this.send(key, {
398
+ method: "DELETE",
399
+ query: `uploadId=${id}`
400
+ }).catch(() => void 0);
401
+ throw err;
402
+ } finally {
403
+ await handle.close();
404
+ }
405
+ }
406
+ url(key, query = "") {
407
+ const base = this.remote.endpoint.replace(/\/+$/, "");
408
+ const path$1 = key.split("/").map(encodeURIComponent).join("/");
409
+ return `${base}/${this.remote.bucket}/${path$1}${query ? `?${query}` : ""}`;
410
+ }
411
+ async send(key, init) {
412
+ const signed = await this.aws.sign(this.url(key, init.query), {
413
+ method: init.method,
414
+ headers: init.headers,
415
+ body: init.body
416
+ });
417
+ return this.fetch(signed);
418
+ }
419
+ async failure(what, res) {
420
+ const text = await res.text().catch(() => "");
421
+ const hint = res.status === 403 ? ": check the remote's keys and that they may write to the bucket" : res.status === 404 ? ": check the remote's endpoint and bucket" : "";
422
+ return new StorageError(`${what} ${this.remote.bucket} failed (${res.status} ${errorCode(text)})${hint}`, res.status);
423
+ }
424
+ };
425
+ function errorCode(xml) {
426
+ return /<Code>([^<]+)<\/Code>/.exec(xml)?.[1] ?? "no error code";
427
+ }
428
+ function escapeXml(text) {
429
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
430
+ }
431
+ /**
432
+ * Finding a project's pinned assets from file paths: what a preview or an
433
+ * engine asks for is an absolute path, and a pinned file that isn't on disk
434
+ * is read from its bucket instead.
435
+ */
436
+ const FILE = "framefields.json";
437
+ /** The nearest folder at or above `dir` holding a framefields.json. */
438
+ function findProjectDir(dir) {
439
+ for (let at = dir;; at = dirname(at)) {
440
+ if (existsSync(join(at, FILE))) return at;
441
+ if (dirname(at) === at) return void 0;
442
+ }
443
+ }
444
+ /** The `storage` and `assets` of the project at `dir`; undefined without assets. */
445
+ async function readProjectManifest(dir) {
446
+ const file = join(dir, FILE);
447
+ if (!existsSync(file)) return void 0;
448
+ let raw;
449
+ try {
450
+ raw = JSON.parse(await readFile(file, "utf8"));
451
+ } catch (err) {
452
+ throw new ManifestError(`${FILE} is not valid JSON: ${err.message}`);
453
+ }
454
+ if (raw.assets === void 0) return void 0;
455
+ const storage = raw.storage === void 0 ? void 0 : parseStorage(raw.storage);
456
+ return {
457
+ storage,
458
+ assets: parseAssets(raw.assets, storage)
459
+ };
460
+ }
461
+ /** Signatures last 6 h and are reused for 5, so long sessions keep working. */
462
+ const SIGNED_SEC = 6 * 3600;
463
+ const REUSE_MS = 5 * 3600 * 1e3;
464
+ /**
465
+ * Pinned-asset lookup for the project at or above `dir`, or undefined when
466
+ * it pins none.
467
+ */
468
+ async function openAssetLocator(dir, options = {}) {
469
+ const root = findProjectDir(dir);
470
+ const manifest = root && await readProjectManifest(root);
471
+ if (!root || !manifest) return void 0;
472
+ const signed = /* @__PURE__ */ new Map();
473
+ const entry = (file) => {
474
+ const rel = relative(root, file).split(sep).join("/");
475
+ return rel.startsWith("../") ? void 0 : manifest.assets[rel];
476
+ };
477
+ return {
478
+ root,
479
+ entry,
480
+ async url(file) {
481
+ const pinned = entry(file);
482
+ if (!pinned) return void 0;
483
+ const open$1 = readUrl(pinned, manifest.storage);
484
+ if (open$1) return open$1;
485
+ const cached = signed.get(pinned.sha256);
486
+ if (cached && Date.now() - cached.at < REUSE_MS) return cached.url;
487
+ const { name, remote } = pickRemote(manifest.storage, pinned.remote);
488
+ const keys = credentialsFromEnv(name, options.env);
489
+ if (!keys) return void 0;
490
+ const url = await new Bucket(remote, keys, { fetch: options.fetch }).presign(pinned.sha256, SIGNED_SEC);
491
+ signed.set(pinned.sha256, {
492
+ url,
493
+ at: Date.now()
494
+ });
495
+ return url;
496
+ }
497
+ };
498
+ }
499
+
500
+ //#endregion
501
+ export { redactQuery as S, parseStorage as _, SHA256 as a, readProjectManifest as b, credentialEnvNames as c, findProjectDir as d, hashFile as f, parseAssets as g, openAssetLocator as h, REMOTE_NAME as i, credentialsFromEnv as l, objectKey as m, Bucket as n, StorageError as o, isAssetPath as p, ManifestError as r, contentType as s, AssetError as t, downloadVerified as u, pickRemote as v, readUrl as x, publicUrl as y };
502
+ //# sourceMappingURL=dist-CiTgmfUw.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dist-CiTgmfUw.mjs","names":["path"],"sources":["../../storage/dist/index.mjs"],"sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { mkdir, open, readFile, rename, rm } from \"node:fs/promises\";\nimport { AwsClient } from \"aws4fetch\";\nimport { createReadStream, createWriteStream, existsSync } from \"node:fs\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport { Readable, Transform } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\n\n//#region src/files.ts\n/**\n* Hashing and verified downloads: every byte an asset contributes is checked\n* against the sha256 its manifest entry pins.\n*/\nvar AssetError = class extends Error {\n\tname = \"AssetError\";\n\tconstructor(code, message, options) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t}\n};\nasync function hashFile(path) {\n\tconst hash = createHash(\"sha256\");\n\tlet size = 0;\n\tfor await (const chunk of createReadStream(path)) {\n\t\thash.update(chunk);\n\t\tsize += chunk.length;\n\t}\n\treturn {\n\t\tsha256: hash.digest(\"hex\"),\n\t\tsize\n\t};\n}\n/**\n* Downloads `url` to `dest` through a temporary file, and only renames it\n* into place once its size and sha256 match `expected`.\n*/\nasync function downloadVerified(url, dest, expected, options = {}) {\n\tconst attempts = options.attempts ?? 3;\n\tfor (let attempt = 1;; attempt++) try {\n\t\tawait downloadOnce(url, dest, expected, options);\n\t\treturn;\n\t} catch (err) {\n\t\tif (!(err instanceof AssetError ? err.code === \"ASSET_DOWNLOAD_FAILED\" : !options.signal?.aborted) || attempt >= attempts) throw err;\n\t\tawait new Promise((r) => setTimeout(r, 500 * 2 ** attempt));\n\t}\n}\nasync function downloadOnce(url, dest, expected, options) {\n\tconst shown = redactQuery(url);\n\tconst res = await (options.fetch ?? fetch)(url, { signal: options.signal });\n\tif (!res.ok || !res.body) {\n\t\tawait res.body?.cancel();\n\t\tif (res.status === 404) throw new AssetError(\"ASSET_NOT_FOUND\", `${shown} returned 404`);\n\t\tif (res.status === 401 || res.status === 403) throw new AssetError(\"ASSET_FORBIDDEN\", `${shown} returned ${res.status}: the bucket isn't public there, or the signed URL expired`);\n\t\tthrow new AssetError(\"ASSET_DOWNLOAD_FAILED\", `${shown} returned ${res.status}`);\n\t}\n\tawait mkdir(dirname(dest), { recursive: true });\n\tconst temp = `${dest}.${randomBytes(4).toString(\"hex\")}.part`;\n\tconst hash = createHash(\"sha256\");\n\tlet size = 0;\n\tconst tap = new Transform({ transform(chunk, _encoding, done) {\n\t\tsize += chunk.length;\n\t\tif (size > expected.size) return done(new AssetError(\"ASSET_HASH_MISMATCH\", `${shown} is larger than the ${expected.size} bytes framefields.json pins`));\n\t\thash.update(chunk);\n\t\tdone(null, chunk);\n\t} });\n\ttry {\n\t\tawait pipeline(Readable.fromWeb(res.body), tap, createWriteStream(temp), { signal: options.signal }).catch((err) => {\n\t\t\tif (err instanceof AssetError || options.signal?.aborted) throw err;\n\t\t\tthrow new AssetError(\"ASSET_DOWNLOAD_FAILED\", `${shown}: ${err.message}`, { cause: err });\n\t\t});\n\t\tconst sha256 = hash.digest(\"hex\");\n\t\tif (size !== expected.size || sha256 !== expected.sha256) throw new AssetError(\"ASSET_HASH_MISMATCH\", `${shown} is not the file framefields.json pins (got ${size} bytes, sha256 ${sha256.slice(0, 12)}…; expected ${expected.size} bytes, ${expected.sha256.slice(0, 12)}…)`);\n\t\tawait rename(temp, dest);\n\t} finally {\n\t\tawait rm(temp, { force: true });\n\t}\n}\n/** Signed URLs carry credentials in the query: never print them. */\nfunction redactQuery(url) {\n\tconst q = url.indexOf(\"?\");\n\treturn q < 0 ? url : `${url.slice(0, q)}?…`;\n}\nconst TYPES = {\n\tmp4: \"video/mp4\",\n\tm4v: \"video/mp4\",\n\tmov: \"video/quicktime\",\n\twebm: \"video/webm\",\n\tmkv: \"video/x-matroska\",\n\tmp3: \"audio/mpeg\",\n\tm4a: \"audio/mp4\",\n\taac: \"audio/aac\",\n\twav: \"audio/wav\",\n\tflac: \"audio/flac\",\n\togg: \"audio/ogg\",\n\tpng: \"image/png\",\n\tjpg: \"image/jpeg\",\n\tjpeg: \"image/jpeg\",\n\twebp: \"image/webp\",\n\tavif: \"image/avif\",\n\tgif: \"image/gif\",\n\tsvg: \"image/svg+xml\",\n\tjson: \"application/json\",\n\tlottie: \"application/zip\",\n\tglb: \"model/gltf-binary\",\n\tgltf: \"model/gltf+json\",\n\tttf: \"font/ttf\",\n\totf: \"font/otf\",\n\twoff2: \"font/woff2\",\n\tcube: \"text/plain\",\n\tsrt: \"text/plain\",\n\tvtt: \"text/vtt\"\n};\n/** The Content-Type a CDN serves the file with. */\nfunction contentType(path) {\n\treturn TYPES[path.slice(path.lastIndexOf(\".\") + 1).toLowerCase()] ?? \"application/octet-stream\";\n}\n\n//#endregion\n//#region src/manifest.ts\nconst REMOTE_NAME = /^[A-Za-z0-9][\\w-]{0,63}$/;\nconst SHA256 = /^[0-9a-f]{64}$/;\nconst FILE$1 = \"framefields.json\";\nvar ManifestError = class extends Error {\n\tname = \"ManifestError\";\n};\n/** Validates `storage`; errors name the remote and field at fault. */\nfunction parseStorage(value) {\n\tif (!isRecord(value) || !isRecord(value.remotes)) throw new ManifestError(`${FILE$1}: \"storage\" needs \"remotes\", e.g. { \"remotes\": { \"media\": { \"endpoint\": \"https://<account>.r2.cloudflarestorage.com\", \"bucket\": \"films\" } } }`);\n\tconst remotes = {};\n\tfor (const [name, spec] of Object.entries(value.remotes)) remotes[name] = parseRemote(name, spec);\n\tconst names = Object.keys(remotes);\n\tif (names.length === 0) throw new ManifestError(`${FILE$1}: \"storage.remotes\" is empty`);\n\tif (value.default !== void 0 && !names.includes(value.default)) throw new ManifestError(`${FILE$1}: \"storage.default\" must name a remote (${names.join(\", \")})`);\n\treturn {\n\t\t...typeof value.default === \"string\" && { default: value.default },\n\t\tremotes\n\t};\n}\nfunction parseRemote(name, spec) {\n\tconst fail = (message) => {\n\t\tthrow new ManifestError(`${FILE$1}: storage.remotes.${name} ${message}`);\n\t};\n\tif (!REMOTE_NAME.test(name)) fail(\"has an invalid name: use letters, digits, - and _ (at most 64)\");\n\tif (!isRecord(spec)) fail(\"must be an object with an endpoint and a bucket\");\n\tconst s = spec;\n\tif (!isHttpUrl(s.endpoint)) fail(\"needs \\\"endpoint\\\": the S3 API URL, e.g. \\\"https://<account>.r2.cloudflarestorage.com\\\"\");\n\tif (typeof s.bucket !== \"string\" || !/^[a-z0-9][a-z0-9.-]{1,62}$/.test(s.bucket)) fail(\"needs \\\"bucket\\\": the bucket name\");\n\tif (s.region !== void 0 && typeof s.region !== \"string\") fail(\"\\\"region\\\" must be a string\");\n\tif (s.prefix !== void 0 && (typeof s.prefix !== \"string\" || s.prefix.startsWith(\"/\") || s.prefix.split(\"/\").includes(\"..\"))) fail(\"\\\"prefix\\\" must be a key prefix such as \\\"films/launch/\\\"\");\n\tif (s.publicUrl !== void 0 && !isHttpUrl(s.publicUrl)) fail(\"\\\"publicUrl\\\" must be an http(s) URL, e.g. \\\"https://media.example.com\\\"\");\n\treturn {\n\t\tendpoint: s.endpoint,\n\t\tbucket: s.bucket,\n\t\t...s.region !== void 0 && { region: s.region },\n\t\t...typeof s.prefix === \"string\" && s.prefix && { prefix: normalizePrefix(s.prefix) },\n\t\t...s.publicUrl !== void 0 && { publicUrl: s.publicUrl }\n\t};\n}\n/** Validates `assets`; errors name the path and field at fault. */\nfunction parseAssets(value, storage) {\n\tif (!isRecord(value)) throw new ManifestError(`${FILE$1}: \"assets\" must map project paths to { \"sha256\", \"size\" }`);\n\tconst out = {};\n\tfor (const [path, entry] of Object.entries(value)) {\n\t\tconst fail = (message) => {\n\t\t\tthrow new ManifestError(`${FILE$1}: assets[\"${path}\"] ${message}`);\n\t\t};\n\t\tif (!isAssetPath(path)) fail(\"must be a path inside the project, e.g. assets/footage/intro.mp4\");\n\t\tif (!isRecord(entry)) fail(\"must be { \\\"sha256\\\", \\\"size\\\" }\");\n\t\tconst e = entry;\n\t\tif (typeof e.sha256 !== \"string\" || !SHA256.test(e.sha256)) fail(\"needs \\\"sha256\\\": 64 lowercase hex digits\");\n\t\tif (typeof e.size !== \"number\" || !Number.isSafeInteger(e.size) || e.size < 0) fail(\"needs \\\"size\\\" in bytes\");\n\t\tif (e.url !== void 0 && !isHttpUrl(e.url)) fail(\"\\\"url\\\" must be an http(s) URL\");\n\t\tif (e.remote !== void 0) {\n\t\t\tif (typeof e.remote !== \"string\" || !storage?.remotes[e.remote]) fail(`\"remote\" must name a remote in \"storage.remotes\"`);\n\t\t} else if (e.url === void 0 && !storage) fail(\"needs a \\\"url\\\", or a \\\"storage\\\" section with a remote to hold it\");\n\t\tout[path] = {\n\t\t\tsha256: e.sha256,\n\t\t\tsize: e.size,\n\t\t\t...e.remote !== void 0 && { remote: e.remote },\n\t\t\t...e.url !== void 0 && { url: e.url }\n\t\t};\n\t}\n\treturn out;\n}\n/** The remote an asset (or a new one, without `name`) belongs to. */\nfunction pickRemote(storage, name) {\n\tconst names = Object.keys(storage?.remotes ?? {});\n\tconst chosen = name ?? storage?.default ?? (names.length === 1 ? names[0] : void 0);\n\tif (!storage || names.length === 0) throw new ManifestError(`${FILE$1} has no \"storage\" remotes: add one (an R2 or S3 bucket) first`);\n\tif (!chosen) throw new ManifestError(`${FILE$1}: name the remote (${names.join(\", \")}), or set \"storage.default\"`);\n\tconst remote = storage.remotes[chosen];\n\tif (!remote) throw new ManifestError(`${FILE$1}: no remote named \"${chosen}\" (${names.join(\", \")})`);\n\treturn {\n\t\tname: chosen,\n\t\tremote\n\t};\n}\n/** The object key holding `sha256`: `<prefix>sha256/ab/<hash>`. */\nfunction objectKey(sha256, prefix = \"\") {\n\treturn `${prefix}sha256/${sha256.slice(0, 2)}/${sha256}`;\n}\n/** The asset's URL on the remote's public domain, if it has one. */\nfunction publicUrl(remote, sha256) {\n\tif (!remote.publicUrl) return void 0;\n\treturn `${remote.publicUrl.replace(/\\/+$/, \"\")}/${objectKey(sha256, remote.prefix)}`;\n}\n/**\n* Where to download an asset without credentials: a signed URL handed in\n* (`signed`, by sha256), its own `url`, or its remote's public domain.\n* Undefined means the asset is on a private remote and needs a signature.\n*/\nfunction readUrl(entry, storage, signed) {\n\tconst given = signed?.[entry.sha256];\n\tif (given) return given;\n\tif (entry.url) return entry.url;\n\tif (!storage) return void 0;\n\treturn publicUrl(pickRemote(storage, entry.remote).remote, entry.sha256);\n}\nfunction isAssetPath(path) {\n\treturn path.length > 0 && path.length <= 1024 && !path.startsWith(\"/\") && !path.includes(\"\\\\\") && !path.split(\"/\").some((part) => part === \"\" || part === \".\" || part === \"..\");\n}\nfunction normalizePrefix(prefix) {\n\treturn prefix.endsWith(\"/\") ? prefix : `${prefix}/`;\n}\nfunction isHttpUrl(value) {\n\tif (typeof value !== \"string\") return false;\n\ttry {\n\t\tconst { protocol } = new URL(value);\n\t\treturn protocol === \"https:\" || protocol === \"http:\";\n\t} catch {\n\t\treturn false;\n\t}\n}\nfunction isRecord(value) {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n//#endregion\n//#region src/bucket.ts\n/**\n* The few S3 calls asset storage needs (HEAD, PUT, multipart upload,\n* presigned GET), signed with SigV4 by aws4fetch. Works with any\n* S3-compatible service; R2 is the one to pick, since it charges no egress.\n*/\n/**\n* Keys for `remote` from the environment:\n* `FRAMEFIELDS_STORAGE_<REMOTE>_ACCESS_KEY_ID` / `…_SECRET_ACCESS_KEY`\n* (the remote's name upper-cased, `-` as `_`), else the standard\n* `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`.\n*/\nfunction credentialsFromEnv(remote, env = process.env) {\n\tconst scope = `FRAMEFIELDS_STORAGE_${remote.toUpperCase().replace(/-/g, \"_\")}`;\n\tconst own = env[`${scope}_ACCESS_KEY_ID`];\n\tconst ownSecret = env[`${scope}_SECRET_ACCESS_KEY`];\n\tif (own && ownSecret) return {\n\t\taccessKeyId: own,\n\t\tsecretAccessKey: ownSecret\n\t};\n\tconst id = env.AWS_ACCESS_KEY_ID;\n\tconst secret = env.AWS_SECRET_ACCESS_KEY;\n\tif (!id || !secret) return void 0;\n\treturn {\n\t\taccessKeyId: id,\n\t\tsecretAccessKey: secret,\n\t\t...env.AWS_SESSION_TOKEN && { sessionToken: env.AWS_SESSION_TOKEN }\n\t};\n}\n/** The env vars `credentialsFromEnv` reads for `remote`, for messages. */\nfunction credentialEnvNames(remote) {\n\tconst scope = `FRAMEFIELDS_STORAGE_${remote.toUpperCase().replace(/-/g, \"_\")}`;\n\treturn [`${scope}_ACCESS_KEY_ID`, `${scope}_SECRET_ACCESS_KEY`];\n}\nvar StorageError = class extends Error {\n\tname = \"StorageError\";\n\tconstructor(message, status) {\n\t\tsuper(message);\n\t\tthis.status = status;\n\t}\n};\nconst MiB = 1024 * 1024;\n/**\n* Content-addressed objects never change: CDNs and browsers may keep them\n* forever, which is what makes a custom domain in front of the bucket cheap.\n*/\nconst IMMUTABLE = \"public, max-age=31536000, immutable\";\n/** One remote's bucket, signed with `credentials`. */\nvar Bucket = class {\n\taws;\n\tfetch;\n\tconstructor(remote, credentials, options = {}) {\n\t\tthis.remote = remote;\n\t\tthis.options = options;\n\t\tthis.aws = new AwsClient({\n\t\t\t...credentials,\n\t\t\tservice: \"s3\",\n\t\t\tregion: remote.region ?? \"auto\",\n\t\t\tretries: 3\n\t\t});\n\t\tthis.fetch = options.fetch ?? fetch;\n\t}\n\tkeyFor(sha256) {\n\t\treturn objectKey(sha256, this.remote.prefix);\n\t}\n\t/** Whether the bucket holds `sha256` at the expected size. */\n\tasync has(sha256, size) {\n\t\tconst res = await this.send(this.keyFor(sha256), { method: \"HEAD\" });\n\t\tif (res.status === 404) return false;\n\t\tif (!res.ok) throw await this.failure(\"HEAD\", res);\n\t\treturn Number(res.headers.get(\"content-length\")) === size;\n\t}\n\t/**\n\t* Uploads `file` (already hashed) under its content key. The bucket\n\t* checks every byte against the sha256 sent with it.\n\t*/\n\tasync upload(file, digest, onProgress) {\n\t\tconst key = this.keyFor(digest.sha256);\n\t\tconst headers = {\n\t\t\t\"content-type\": contentType(file),\n\t\t\t\"cache-control\": IMMUTABLE\n\t\t};\n\t\tconst threshold = this.options.multipartThreshold ?? 64 * MiB;\n\t\tif (digest.size <= threshold) {\n\t\t\tconst handle = await open(file);\n\t\t\ttry {\n\t\t\t\tconst body = await handle.readFile();\n\t\t\t\tawait this.put(key, body, digest.sha256, headers);\n\t\t\t} finally {\n\t\t\t\tawait handle.close();\n\t\t\t}\n\t\t\tonProgress?.({\n\t\t\t\tsent: digest.size,\n\t\t\t\ttotal: digest.size\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this.uploadParts(file, key, digest.size, headers, onProgress);\n\t}\n\t/** A GET URL anyone can use until it expires (at most 7 days). */\n\tasync presign(sha256, expiresSec = 86400) {\n\t\tconst url = new URL(this.url(this.keyFor(sha256)));\n\t\turl.searchParams.set(\"X-Amz-Expires\", String(Math.min(expiresSec, 604800)));\n\t\treturn (await this.aws.sign(url, {\n\t\t\tmethod: \"GET\",\n\t\t\taws: { signQuery: true }\n\t\t})).url;\n\t}\n\tasync put(key, body, sha256, headers, query = \"\") {\n\t\tconst res = await this.send(key, {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody,\n\t\t\theaders: {\n\t\t\t\t...headers,\n\t\t\t\t\"x-amz-content-sha256\": sha256\n\t\t\t},\n\t\t\tquery\n\t\t});\n\t\tif (!res.ok) throw await this.failure(\"PUT\", res);\n\t\treturn res;\n\t}\n\tasync uploadParts(file, key, size, headers, onProgress) {\n\t\tconst partSize = Math.max(this.options.partSize ?? 16 * MiB, Math.ceil(size / 1e4), 5 * MiB);\n\t\tconst created = await this.send(key, {\n\t\t\tmethod: \"POST\",\n\t\t\tquery: \"uploads=\",\n\t\t\theaders\n\t\t});\n\t\tif (!created.ok) throw await this.failure(\"CreateMultipartUpload\", created);\n\t\tconst uploadId = /<UploadId>([^<]+)<\\/UploadId>/.exec(await created.text())?.[1];\n\t\tif (!uploadId) throw new StorageError(\"CreateMultipartUpload returned no UploadId\");\n\t\tconst id = encodeURIComponent(uploadId);\n\t\tconst count = Math.ceil(size / partSize);\n\t\tconst etags = new Array(count);\n\t\tconst handle = await open(file);\n\t\tlet next = 0;\n\t\tlet sent = 0;\n\t\tconst worker = async () => {\n\t\t\twhile (next < count) {\n\t\t\t\tconst index = next++;\n\t\t\t\tconst length = Math.min(partSize, size - index * partSize);\n\t\t\t\tconst chunk = Buffer.alloc(length);\n\t\t\t\tawait handle.read(chunk, 0, length, index * partSize);\n\t\t\t\tconst sha = createHash(\"sha256\").update(chunk).digest(\"hex\");\n\t\t\t\tetags[index] = (await this.put(key, chunk, sha, {}, `partNumber=${index + 1}&uploadId=${id}`)).headers.get(\"etag\") ?? \"\";\n\t\t\t\tsent += length;\n\t\t\t\tonProgress?.({\n\t\t\t\t\tsent,\n\t\t\t\t\ttotal: size\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\t\ttry {\n\t\t\tawait Promise.all(Array.from({ length: Math.min(this.options.concurrency ?? 4, count) }, worker));\n\t\t\tconst body = `<CompleteMultipartUpload>${etags.map((etag, i) => `<Part><PartNumber>${i + 1}</PartNumber><ETag>${escapeXml(etag)}</ETag></Part>`).join(\"\")}</CompleteMultipartUpload>`;\n\t\t\tconst done = await this.send(key, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tquery: `uploadId=${id}`,\n\t\t\t\tbody,\n\t\t\t\theaders: { \"content-type\": \"application/xml\" }\n\t\t\t});\n\t\t\tconst text = await done.text();\n\t\t\tif (!done.ok || text.includes(\"<Error>\")) throw new StorageError(`CompleteMultipartUpload failed (${done.status}): ${errorCode(text)}`, done.status);\n\t\t} catch (err) {\n\t\t\tawait this.send(key, {\n\t\t\t\tmethod: \"DELETE\",\n\t\t\t\tquery: `uploadId=${id}`\n\t\t\t}).catch(() => void 0);\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t}\n\turl(key, query = \"\") {\n\t\tconst base = this.remote.endpoint.replace(/\\/+$/, \"\");\n\t\tconst path = key.split(\"/\").map(encodeURIComponent).join(\"/\");\n\t\treturn `${base}/${this.remote.bucket}/${path}${query ? `?${query}` : \"\"}`;\n\t}\n\tasync send(key, init) {\n\t\tconst signed = await this.aws.sign(this.url(key, init.query), {\n\t\t\tmethod: init.method,\n\t\t\theaders: init.headers,\n\t\t\tbody: init.body\n\t\t});\n\t\treturn this.fetch(signed);\n\t}\n\tasync failure(what, res) {\n\t\tconst text = await res.text().catch(() => \"\");\n\t\tconst hint = res.status === 403 ? \": check the remote's keys and that they may write to the bucket\" : res.status === 404 ? \": check the remote's endpoint and bucket\" : \"\";\n\t\treturn new StorageError(`${what} ${this.remote.bucket} failed (${res.status} ${errorCode(text)})${hint}`, res.status);\n\t}\n};\nfunction errorCode(xml) {\n\treturn /<Code>([^<]+)<\\/Code>/.exec(xml)?.[1] ?? \"no error code\";\n}\nfunction escapeXml(text) {\n\treturn text.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/\"/g, \"&quot;\");\n}\n\n//#endregion\n//#region src/locate.ts\n/**\n* Finding a project's pinned assets from file paths: what a preview or an\n* engine asks for is an absolute path, and a pinned file that isn't on disk\n* is read from its bucket instead.\n*/\nconst FILE = \"framefields.json\";\n/** The nearest folder at or above `dir` holding a framefields.json. */\nfunction findProjectDir(dir) {\n\tfor (let at = dir;; at = dirname(at)) {\n\t\tif (existsSync(join(at, FILE))) return at;\n\t\tif (dirname(at) === at) return void 0;\n\t}\n}\n/** The `storage` and `assets` of the project at `dir`; undefined without assets. */\nasync function readProjectManifest(dir) {\n\tconst file = join(dir, FILE);\n\tif (!existsSync(file)) return void 0;\n\tlet raw;\n\ttry {\n\t\traw = JSON.parse(await readFile(file, \"utf8\"));\n\t} catch (err) {\n\t\tthrow new ManifestError(`${FILE} is not valid JSON: ${err.message}`);\n\t}\n\tif (raw.assets === void 0) return void 0;\n\tconst storage = raw.storage === void 0 ? void 0 : parseStorage(raw.storage);\n\treturn {\n\t\tstorage,\n\t\tassets: parseAssets(raw.assets, storage)\n\t};\n}\n/** Signatures last 6 h and are reused for 5, so long sessions keep working. */\nconst SIGNED_SEC = 6 * 3600;\nconst REUSE_MS = 5 * 3600 * 1e3;\n/**\n* Pinned-asset lookup for the project at or above `dir`, or undefined when\n* it pins none.\n*/\nasync function openAssetLocator(dir, options = {}) {\n\tconst root = findProjectDir(dir);\n\tconst manifest = root && await readProjectManifest(root);\n\tif (!root || !manifest) return void 0;\n\tconst signed = /* @__PURE__ */ new Map();\n\tconst entry = (file) => {\n\t\tconst rel = relative(root, file).split(sep).join(\"/\");\n\t\treturn rel.startsWith(\"../\") ? void 0 : manifest.assets[rel];\n\t};\n\treturn {\n\t\troot,\n\t\tentry,\n\t\tasync url(file) {\n\t\t\tconst pinned = entry(file);\n\t\t\tif (!pinned) return void 0;\n\t\t\tconst open$1 = readUrl(pinned, manifest.storage);\n\t\t\tif (open$1) return open$1;\n\t\t\tconst cached = signed.get(pinned.sha256);\n\t\t\tif (cached && Date.now() - cached.at < REUSE_MS) return cached.url;\n\t\t\tconst { name, remote } = pickRemote(manifest.storage, pinned.remote);\n\t\t\tconst keys = credentialsFromEnv(name, options.env);\n\t\t\tif (!keys) return void 0;\n\t\t\tconst url = await new Bucket(remote, keys, { fetch: options.fetch }).presign(pinned.sha256, SIGNED_SEC);\n\t\t\tsigned.set(pinned.sha256, {\n\t\t\t\turl,\n\t\t\t\tat: Date.now()\n\t\t\t});\n\t\t\treturn url;\n\t\t}\n\t};\n}\n\n//#endregion\nexport { AssetError, Bucket, ManifestError, REMOTE_NAME, SHA256, StorageError, contentType, credentialEnvNames, credentialsFromEnv, downloadVerified, findProjectDir, hashFile, isAssetPath, objectKey, openAssetLocator, parseAssets, parseStorage, pickRemote, publicUrl, readProjectManifest, readUrl, redactQuery };\n//# sourceMappingURL=index.mjs.map"],"mappings":"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"}