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
package/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { c as CONFIG_FILE, d as writeConfig, i as renderCloud, l as findRender, t as CloudRenderError, u as readConfig } from "./cloud-COid1Ipa.mjs";
3
- import { t as failedCheck } from "./check-result-Culfu7Nx.mjs";
2
+ import { c as AssetsError, d as runAssets, f as CONFIG_FILE, h as writeConfig, i as renderCloud, l as megabytes, m as readConfig, p as findRender, t as CloudRenderError, u as pullAssets } from "./cloud-Cj1TIme8.mjs";
3
+ import { t as failedCheck } from "./check-result-DZWx73V8.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
6
  import path, { basename, dirname, join, posix, relative, resolve, sep } from "node:path";
@@ -343,8 +343,8 @@ const SCRIPTS = {
343
343
  "check:render": "tsc --noEmit -p . && framefields check film --render --json",
344
344
  frames: "tsx src/render.ts frames",
345
345
  grid: "tsx src/render.ts grid",
346
- preview: "tsx src/render.ts preview",
347
- render: "tsx src/render.ts",
346
+ preview: "framefields preview film",
347
+ render: "framefields render film",
348
348
  "render:cloud": "framefields render film --cloud"
349
349
  };
350
350
  /** The named render `init` records in framefields.json. */
@@ -485,44 +485,30 @@ export async function buildFilm(): Promise<Composition> {
485
485
  const RENDER_TS = `import { existsSync } from "node:fs";
486
486
  import fs from "node:fs/promises";
487
487
  import path from "node:path";
488
- import { HeadlessMediaRenderer, frameCount, startPreview } from "framefields";
488
+ import { HeadlessMediaRenderer, frameCount } from "framefields";
489
489
  import { buildFilm } from "./film.js";
490
490
 
491
+ // Quick looks at the film: \`npm run frames -- 0 30 60\` and \`npm run grid\`.
492
+ // \`npm run render\` and \`npm run preview\` use the "film" render in
493
+ // framefields.json instead (\`framefields render film\`, \`framefields preview film\`).
494
+
491
495
  // Optional settings such as FRAMEFIELDS_API_KEY (see .env.example).
492
496
  const ENV = path.resolve(import.meta.dirname, "../.env");
493
497
  if (existsSync(ENV)) process.loadEnvFile(ENV);
494
498
 
495
499
  const OUT = path.resolve(import.meta.dirname, "../output");
496
500
  // \`npm run frames -- 0 30\` needs the \`--\`; pnpm passes it through: drop it.
497
- const [mode = "video", ...args] = process.argv
501
+ const [mode = "frames", ...args] = process.argv
498
502
  .slice(2)
499
503
  .filter((a) => a !== "--");
500
504
 
501
- if (mode === "preview") {
502
- // The page runs film.ts itself and renders it with WebGPU in the browser.
503
- const session = await startPreview({
504
- entry: new URL("./film.ts", import.meta.url),
505
- export: "buildFilm",
506
- });
507
- console.log(\`Preview at \${session.url}\`);
508
- await session.closed; // until its tab closes or the next preview replaces it
509
- process.exit(0);
510
- }
511
-
512
505
  const film = await buildFilm();
513
506
  await fs.mkdir(OUT, { recursive: true });
514
507
 
515
- if (mode === "frames") {
516
- const renderer = new HeadlessMediaRenderer();
517
- for (const frame of (args.length ? args : ["0"]).map(Number)) {
518
- const png = await film.renderFrame({ frame, renderer });
519
- const file = path.join(OUT, \`f\${String(frame).padStart(4, "0")}.png\`);
520
- await fs.writeFile(file, png);
521
- console.log(\`Wrote \${path.relative(process.cwd(), file)}\`);
522
- }
523
- } else if (mode === "grid") {
508
+ if (mode === "grid") {
509
+ const last = frameCount(film.durationMs ?? (await film.computeDuration()), film.fps) - 1;
524
510
  const png = await film.renderFrameGrid({
525
- frames: args.length ? args.map(Number) : [...new Set([0, Math.floor((frameCount(film.durationMs ?? await film.computeDuration(), film.fps) - 1) / 2), frameCount(film.durationMs ?? await film.computeDuration(), film.fps) - 1])],
511
+ frames: args.length ? args.map(Number) : [...new Set([0, Math.floor(last / 2), last])],
526
512
  columns: 4,
527
513
  cellWidth: 480,
528
514
  showLabels: true,
@@ -530,12 +516,13 @@ if (mode === "frames") {
530
516
  await fs.writeFile(path.join(OUT, "grid.png"), png);
531
517
  console.log("Wrote output/grid.png");
532
518
  } else {
533
- const result = await film.renderVideo({
534
- outputPath: path.join(OUT, "output.mp4"),
535
- quality: "high",
536
- });
537
- await result.cleanup?.();
538
- console.log(\`Exported \${result.filePath}\`);
519
+ const renderer = new HeadlessMediaRenderer();
520
+ for (const frame of (args.length ? args : ["0"]).map(Number)) {
521
+ const png = await film.renderFrame({ frame, renderer });
522
+ const file = path.join(OUT, \`f\${String(frame).padStart(4, "0")}.png\`);
523
+ await fs.writeFile(file, png);
524
+ console.log(\`Wrote \${path.relative(process.cwd(), file)}\`);
525
+ }
539
526
  }
540
527
 
541
528
  // Native GPU and encoder threads keep Node alive; always exit explicitly.
@@ -551,7 +538,7 @@ ${run("typecheck")}
551
538
  ${run("frames")} -- 0 30 60 # PNGs in output/
552
539
  ${run("grid")} # a contact sheet of the motion
553
540
  ${run("preview")} # play it in the browser
554
- ${run("render")} # output/output.mp4
541
+ ${run("render")} # output/film.mp4
555
542
  ${run("render:cloud")} # on cloud GPUs, from the pushed commit
556
543
  \`\`\`
557
544
 
@@ -799,6 +786,27 @@ function shownPath(cwd, root) {
799
786
  return relative(cwd, root) || ".";
800
787
  }
801
788
 
789
+ //#endregion
790
+ //#region src/cli/project-node.ts
791
+ /**
792
+ * Node arguments to run a CLI worker against the user's project: the
793
+ * project's own tsx loader for a TypeScript entry (TypeScript belongs to the
794
+ * consumer project; init's scaffold has it), and the worker script, from
795
+ * source when the CLI runs from source.
796
+ */
797
+ function projectNodeArgs(entry, worker) {
798
+ const source = import.meta.url.endsWith(".ts");
799
+ const args = source ? ["--conditions=development"] : [];
800
+ if (source || /\.[cm]?tsx?$/.test(entry)) try {
801
+ const require = createRequire(resolve("package.json"));
802
+ args.push("--import", pathToFileURL(require.resolve("tsx")).href);
803
+ } catch {
804
+ return { error: "Install the project's tsx dev dependency to load a TypeScript entry." };
805
+ }
806
+ args.push(fileURLToPath(new URL(source ? `./${worker}.ts` : `./cli/${worker}.mjs`, import.meta.url)));
807
+ return args;
808
+ }
809
+
802
810
  //#endregion
803
811
  //#region src/cli/check.ts
804
812
  /** The worker's IPC result is separate from arbitrary builder stdout/stderr. */
@@ -809,15 +817,8 @@ async function runCheck(options) {
809
817
  const timeout = options.timeoutMs ?? 6e4;
810
818
  if (!Number.isSafeInteger(timeout) || timeout <= 0) throw new Error("--timeout must be a positive integer in milliseconds");
811
819
  const fail = (code, message) => failedCheck(entry, exportName, sdkVersion, code, message);
812
- const source = import.meta.url.endsWith(".ts");
813
- const args = source ? ["--conditions=development"] : [];
814
- if (source || /\.[cm]?tsx?$/.test(entry)) try {
815
- const require = createRequire(resolve("package.json"));
816
- args.push("--import", pathToFileURL(require.resolve("tsx")).href);
817
- } catch {
818
- return fail("missing_ts_loader", "Install the project's tsx dev dependency to check a TypeScript entry.");
819
- }
820
- args.push(fileURLToPath(new URL(source ? "./check-worker.ts" : "./cli/check-worker.mjs", import.meta.url)));
820
+ const args = projectNodeArgs(entry, "check-worker");
821
+ if ("error" in args) return fail("missing_ts_loader", args.error);
821
822
  return new Promise((done) => {
822
823
  const child = spawn(process.execPath, args, { stdio: [
823
824
  "ignore",
@@ -883,8 +884,7 @@ async function runCloudRender(o, log, render = renderCloud) {
883
884
  return 2;
884
885
  }
885
886
  const spec = target.name ? findRender(cwd, target.name) : void 0;
886
- const codec = o.codec ?? spec?.codec ?? "h264";
887
- const outputPath = o.output ?? spec?.output ?? path.join("output", `${target.name ?? path.basename(target.entry ?? "").replace(/\.[^.]+$/, "")}.${codec === "vp9" ? "webm" : "mp4"}`);
887
+ const outputPath = renderOutput(target, spec, o.codec ?? spec?.codec ?? "h264", o.output);
888
888
  const planWorkers = o.plan && (workers ?? spec?.workers ?? 1) === 1 ? "auto" : workers;
889
889
  const controller = new AbortController();
890
890
  const onSigint = () => {
@@ -909,7 +909,8 @@ async function runCloudRender(o, log, render = renderCloud) {
909
909
  outputPath: o.plan ? void 0 : outputPath,
910
910
  signal: controller.signal,
911
911
  onProgress: narrate,
912
- onWarning: (m) => log(`warning: ${m}`)
912
+ onWarning: (m) => log(`warning: ${m}`),
913
+ onLog: log
913
914
  });
914
915
  if (o.json) {
915
916
  log(JSON.stringify(result));
@@ -952,6 +953,11 @@ function renderCommand(o) {
952
953
  ];
953
954
  return [`framefields render ${o.entry ?? ""} --cloud`.replace(" ", " "), ...flags.filter(([, v]) => v !== void 0).map(([f, v]) => `${f} ${v}`)].join(" ");
954
955
  }
956
+ /** What a render named `name` (or the module `entry`) produces, wherever it runs. */
957
+ function renderOutput(target, spec, codec, output) {
958
+ const base = target.name ?? path.basename(target.entry ?? "").replace(/\.[^.]+$/, "");
959
+ return output ?? spec?.output ?? path.join("output", `${base}.${codec === "vp9" ? "webm" : "mp4"}`);
960
+ }
955
961
  /**
956
962
  * What `framefields render [arg]` renders: a render named in framefields.json,
957
963
  * or a module path; with no argument, the project's only named render.
@@ -961,7 +967,7 @@ function pickRender(arg, cwd) {
961
967
  const names = Object.keys(renders);
962
968
  if (arg === void 0) {
963
969
  if (names.length === 1) return { name: names[0] };
964
- return { error: names.length ? `Name the render: ${names.join(", ")}. \`framefields renders\` lists them.` : `Name a module, e.g. \`framefields render src/film.ts --cloud\`, or add "renders" to ${CONFIG_FILE}.` };
970
+ return { error: names.length ? `Name the render: ${names.join(", ")}. \`framefields renders\` lists them.` : `Name a module, e.g. \`framefields render src/film.ts\`, or add "renders" to ${CONFIG_FILE}.` };
965
971
  }
966
972
  if (renders[arg]) return { name: arg };
967
973
  if (existsSync(path.resolve(cwd, arg))) return { entry: arg };
@@ -1027,6 +1033,121 @@ function usd(value) {
1027
1033
  return value > 0 && value < .01 ? "<$0.01" : `$${value.toFixed(2)}`;
1028
1034
  }
1029
1035
 
1036
+ //#endregion
1037
+ //#region src/cli/local.ts
1038
+ /**
1039
+ * `framefields render [name|entry]` and `framefields preview [name|entry]`
1040
+ * on this machine. They read the same named renders in framefields.json as
1041
+ * `--cloud`, so a render goes to the same file wherever it runs.
1042
+ *
1043
+ * A local render first downloads pinned assets that are missing here; a
1044
+ * preview doesn't need to: the page streams them from their bucket.
1045
+ */
1046
+ async function runLocal(mode, o, log) {
1047
+ const cwd = o.cwd ?? process.cwd();
1048
+ const target = pickRender(o.entry, cwd);
1049
+ if ("error" in target) {
1050
+ log(target.error);
1051
+ return 2;
1052
+ }
1053
+ const spec = target.name ? findRender(cwd, target.name) : void 0;
1054
+ const entry = path.resolve(cwd, spec?.entry ?? target.entry);
1055
+ const codec = o.codec ?? spec?.codec ?? "h264";
1056
+ if (codec !== "h264" && codec !== "vp9") {
1057
+ log(`--codec must be h264 or vp9, not "${codec}".`);
1058
+ return 2;
1059
+ }
1060
+ const engine = projectEngine(entry);
1061
+ if (!engine) {
1062
+ log("framefields isn't installed in this project: `npm i framefields`.");
1063
+ return 2;
1064
+ }
1065
+ const job = {
1066
+ mode,
1067
+ entry,
1068
+ engine,
1069
+ export: o.export ?? spec?.export ?? "buildFilm",
1070
+ args: spec?.args,
1071
+ select: o.select ?? spec?.select,
1072
+ codec,
1073
+ quality: o.quality ?? spec?.quality,
1074
+ outputPath: path.resolve(cwd, renderOutput(target, spec, codec, o.output)),
1075
+ title: spec?.title ?? target.name
1076
+ };
1077
+ if (mode === "preview" && (job.args !== void 0 || job.select)) log("The preview calls the export without args or select; it shows what the export returns by default.");
1078
+ if (mode === "render" && !await ensureAssets(cwd, log)) return 1;
1079
+ const result = await runWorker(job, cwd);
1080
+ if (!result.ok) {
1081
+ log(result.message);
1082
+ return 1;
1083
+ }
1084
+ if (result.filePath) log(`Rendered ${path.relative(cwd, result.filePath) || result.filePath}`);
1085
+ return result.qaPassed === false ? 1 : 0;
1086
+ }
1087
+ /** The framefields the film imports, resolved from its module. */
1088
+ function projectEngine(entry) {
1089
+ try {
1090
+ return pathToFileURL(createRequire(entry).resolve("framefields")).href;
1091
+ } catch {
1092
+ return;
1093
+ }
1094
+ }
1095
+ /** Downloads pinned assets missing here; false (after saying why) when it can't. */
1096
+ async function ensureAssets(cwd, log) {
1097
+ const assets = readConfig(cwd).config.assets ?? {};
1098
+ if (Object.keys(assets).length === 0) return true;
1099
+ try {
1100
+ const { downloaded, changed } = await pullAssets({
1101
+ cwd,
1102
+ log
1103
+ });
1104
+ if (downloaded.length) {
1105
+ const bytes = downloaded.reduce((n, p) => n + (assets[p]?.size ?? 0), 0);
1106
+ log(`Downloaded ${downloaded.length} pinned assets (${megabytes(bytes)}).`);
1107
+ }
1108
+ if (changed.length) log(`Rendering local edits of pinned assets: ${changed.join(", ")}. \`framefields assets add\` pins them for the cloud.`);
1109
+ return true;
1110
+ } catch (err) {
1111
+ if (!(err instanceof AssetsError)) throw err;
1112
+ log(err.message);
1113
+ return false;
1114
+ }
1115
+ }
1116
+ function runWorker(job, cwd) {
1117
+ const args = projectNodeArgs(job.entry, "local-worker");
1118
+ if ("error" in args) return Promise.resolve({
1119
+ ok: false,
1120
+ message: args.error
1121
+ });
1122
+ return new Promise((done) => {
1123
+ const child = spawn(process.execPath, args, {
1124
+ cwd,
1125
+ stdio: [
1126
+ "inherit",
1127
+ "inherit",
1128
+ "inherit",
1129
+ "ipc"
1130
+ ]
1131
+ });
1132
+ let result;
1133
+ child.on("message", (message) => {
1134
+ result = message;
1135
+ });
1136
+ child.on("error", (error) => done({
1137
+ ok: false,
1138
+ message: error.message
1139
+ }));
1140
+ child.on("close", (code, signal) => done(result ?? (signal === "SIGINT" || code === 130 ? {
1141
+ ok: false,
1142
+ message: "Stopped."
1143
+ } : {
1144
+ ok: false,
1145
+ message: `The ${job.mode} exited without a result (code ${code}, signal ${signal}).`
1146
+ })));
1147
+ child.send(job);
1148
+ });
1149
+ }
1150
+
1030
1151
  //#endregion
1031
1152
  //#region src/cli/registry.ts
1032
1153
  /**
@@ -1077,8 +1198,11 @@ function openRegistry(source, cwd = process.cwd()) {
1077
1198
  * npx framefields list the components you can add
1078
1199
  * npx framefields fonts add <role...> install fonts (emoji)
1079
1200
  * npx framefields fonts list the fonts you can install
1201
+ * npx framefields assets add|push|pull|status media on your own bucket
1080
1202
  * npx framefields renders the renders named in framefields.json
1203
+ * npx framefields render <name> render on this machine's GPU
1081
1204
  * npx framefields render <name> --cloud render on api.framefields.dev
1205
+ * npx framefields preview <name> play it in the browser
1082
1206
  */
1083
1207
  const HELP = `Usage: framefields <command> [options]
1084
1208
 
@@ -1101,14 +1225,27 @@ Commands:
1101
1225
  Install fonts (pinned, hash-checked, with their license)
1102
1226
  and register them in the generated <components>/fonts.ts.
1103
1227
  fonts list List the fonts you can install.
1228
+ assets add <path...>
1229
+ Keep media out of git: hash files (or every file in a
1230
+ folder), upload them to the project's bucket (R2, S3, any
1231
+ S3-compatible storage) and pin them in framefields.json.
1232
+ assets push Upload recorded assets the bucket lacks.
1233
+ assets pull Download missing assets, checked against their sha256.
1234
+ assets status Which assets are here, missing or changed.
1104
1235
  renders List the renders named in framefields.json.
1105
- render [name|entry] --cloud
1106
- Render on api.framefields.dev from the pushed commit of
1107
- this git repo, and download the video. Needs
1108
- FRAMEFIELDS_API_KEY. A render named in framefields.json
1236
+ render [name|entry]
1237
+ Render on this machine: a render named in framefields.json
1109
1238
  (its fields are the defaults; flags override them), or a
1110
1239
  module (--export defaults to buildFilm). Without either,
1111
- the project's only named render.
1240
+ the project's only named render. Pinned assets missing
1241
+ here are downloaded first.
1242
+ render [name|entry] --cloud
1243
+ The same render on api.framefields.dev, from the pushed
1244
+ commit of this git repo, downloaded to the same file.
1245
+ Needs FRAMEFIELDS_API_KEY.
1246
+ preview [name|entry]
1247
+ Play it in the browser (localhost, WebGPU). Pinned assets
1248
+ that aren't here stream from their bucket.
1112
1249
 
1113
1250
  Options for check:
1114
1251
  --export <name> Composition or builder export (default buildFilm).
@@ -1118,6 +1255,10 @@ Options for check:
1118
1255
  --warnings-as-errors Fail on lint warnings.
1119
1256
  --json Machine-readable check, component list, or font list result.
1120
1257
 
1258
+ Options for render and preview:
1259
+ --export, --select, --codec, --quality and --output (render) override the
1260
+ named render's fields, locally and with --cloud.
1261
+
1121
1262
  Options for render --cloud:
1122
1263
  --workers <n|auto> 1 (default) renders on one GPU. auto measures the film
1123
1264
  first and splits it across as many GPUs as stay
@@ -1132,6 +1273,14 @@ Options for render --cloud:
1132
1273
  --json Print the final status as JSON.
1133
1274
  Ctrl-C cancels the render; GPU time already used is charged.
1134
1275
 
1276
+ Options for assets:
1277
+ --remote <name> The remote in framefields.json "storage" (default: its
1278
+ default, or its only one).
1279
+ --overwrite pull: replace files changed locally.
1280
+ Keys: FRAMEFIELDS_STORAGE_<REMOTE>_ACCESS_KEY_ID and _SECRET_ACCESS_KEY,
1281
+ or AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. Reads need none when the
1282
+ remote has a publicUrl (a custom domain or CDN in front of the bucket).
1283
+
1135
1284
  Options for init:
1136
1285
  --name <name> Package name (default: the folder's name).
1137
1286
  --pm <manager> npm, pnpm, yarn or bun (default: the one running this).
@@ -1159,6 +1308,9 @@ Examples:
1159
1308
  npx framefields init my-film --install
1160
1309
  npx framefields add mouse-pointer focus-zoom
1161
1310
  npx framefields fonts add emoji
1311
+ npx framefields assets add assets/footage
1312
+ npx framefields preview film
1313
+ npx framefields render film
1162
1314
  npx framefields render film --cloud --plan
1163
1315
  `;
1164
1316
  async function main(argv) {
@@ -1191,6 +1343,7 @@ async function main(argv) {
1191
1343
  codec: { type: "string" },
1192
1344
  quality: { type: "string" },
1193
1345
  select: { type: "string" },
1346
+ remote: { type: "string" },
1194
1347
  help: {
1195
1348
  type: "boolean",
1196
1349
  short: "h"
@@ -1203,6 +1356,7 @@ async function main(argv) {
1203
1356
  return command || values.help ? 0 : 1;
1204
1357
  }
1205
1358
  const cwd = process.cwd();
1359
+ if (existsSync(join(cwd, ".env"))) process.loadEnvFile(join(cwd, ".env"));
1206
1360
  const log = (line) => process.stdout.write(`${line}\n`);
1207
1361
  if (command === "api") {
1208
1362
  const catalog = JSON.parse(readFileSync(fileURLToPath(new URL(import.meta.url.endsWith(".ts") ? "../dist/api.json" : "./api.json", import.meta.url)), "utf8"));
@@ -1214,9 +1368,30 @@ async function main(argv) {
1214
1368
  }
1215
1369
  if (command === "check") return check(names, cwd, values, log);
1216
1370
  if (command === "renders") return listRenders(cwd, values.json, log);
1371
+ if (command === "assets") return runAssets(names, {
1372
+ cwd,
1373
+ log,
1374
+ remote: values.remote,
1375
+ overwrite: values.overwrite,
1376
+ json: values.json
1377
+ });
1378
+ if (command === "preview" || command === "render" && !values.cloud) {
1379
+ if (names.length > 1) {
1380
+ process.stderr.write(`Usage: framefields ${command} [name|entry] [--export <name>]\n`);
1381
+ return 2;
1382
+ }
1383
+ return runLocal(command === "preview" ? "preview" : "render", {
1384
+ entry: names[0],
1385
+ export: values.export,
1386
+ select: values.select,
1387
+ codec: values.codec,
1388
+ quality: values.quality,
1389
+ output: values.output
1390
+ }, log);
1391
+ }
1217
1392
  if (command === "render") {
1218
- if (names.length > 1 || !values.cloud) {
1219
- process.stderr.write("Usage: framefields render [name|entry] --cloud [--workers auto] [--plan]\nLocal renders run your project's render script (`npm run render`).\n");
1393
+ if (names.length > 1) {
1394
+ process.stderr.write("Usage: framefields render [name|entry] --cloud [--workers auto] [--plan]\n");
1220
1395
  return 2;
1221
1396
  }
1222
1397
  return runCloudRender({