framefields 2.14.0 → 2.16.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.
- package/NOTICE.md +5 -1
- package/dist/audio/index.d.mts +3 -3
- package/dist/audio/index.mjs +10 -10
- package/dist/{audio-DFwRbID_.mjs → audio-6TfPlfl4.mjs} +3 -3
- package/dist/{audio-DFwRbID_.mjs.map → audio-6TfPlfl4.mjs.map} +1 -1
- package/dist/{audio-CdCuGK5d.d.mts → audio-7oqTUi4G.d.mts} +2 -2
- package/dist/{audio-CdCuGK5d.d.mts.map → audio-7oqTUi4G.d.mts.map} +1 -1
- package/dist/cli/check-worker.mjs +44 -44
- package/dist/cli.mjs +1 -1
- package/dist/cloud/index.mjs +1 -1
- package/dist/{cloud-Cj1TIme8.mjs → cloud-jnk1hPYf.mjs} +2 -2
- package/dist/{cloud-Cj1TIme8.mjs.map → cloud-jnk1hPYf.mjs.map} +1 -1
- package/dist/components/index.d.mts +11 -11
- package/dist/components/index.mjs +43 -43
- package/dist/{dist-Kbf-JTry.mjs → dist-BtI6ukB5.mjs} +2 -2
- package/dist/{dist-Kbf-JTry.mjs.map → dist-BtI6ukB5.mjs.map} +1 -1
- package/dist/{dist-B8Nby2CU.mjs → dist-COOpgG9G.mjs} +4 -3
- package/dist/{dist-B8Nby2CU.mjs.map → dist-COOpgG9G.mjs.map} +1 -1
- package/dist/{dist--Uu5bQ_6.mjs → dist-XqlFM2a8.mjs} +13733 -5323
- package/dist/dist-XqlFM2a8.mjs.map +1 -0
- package/dist/{dist-CiTgmfUw.mjs → dist-f1zkl69f.mjs} +4 -4
- package/dist/dist-f1zkl69f.mjs.map +1 -0
- package/dist/{dist-B_rSWeOz.mjs → dist-umQOWz0a.mjs} +1 -1
- package/dist/effects/index.d.mts +4 -4
- package/dist/effects/index.mjs +35 -35
- package/dist/{effects-WMgv8ZaD.mjs → effects-DlRMovU5.mjs} +2 -2
- package/dist/{effects-WMgv8ZaD.mjs.map → effects-DlRMovU5.mjs.map} +1 -1
- package/dist/fonts/index.d.mts +1 -1
- package/dist/fonts/index.mjs +2 -2
- package/dist/{fonts-OW3yAfO5.mjs → fonts-BWYcXjyK.mjs} +3 -3
- package/dist/fonts-BWYcXjyK.mjs.map +1 -0
- package/dist/{gpu-R4T2Tndu.mjs → gpu-CH1PdM4T.mjs} +2 -2
- package/dist/{gpu-R4T2Tndu.mjs.map → gpu-CH1PdM4T.mjs.map} +1 -1
- package/dist/{index-CEKxvGY-.d.mts → index-BHTycml5.d.mts} +2 -2
- package/dist/{index-CEKxvGY-.d.mts.map → index-BHTycml5.d.mts.map} +1 -1
- package/dist/{index-DoP6EiHj.d.mts → index-BcxxxwhV.d.mts} +4 -4
- package/dist/{index-DoP6EiHj.d.mts.map → index-BcxxxwhV.d.mts.map} +1 -1
- package/dist/index-C-V6CAhP.d.mts.map +1 -1
- package/dist/{index-D1FqV1eu.d.mts → index-CMhkkc56.d.mts} +43 -11
- package/dist/index-CMhkkc56.d.mts.map +1 -0
- package/dist/{index-B0Vq8Bwf.d.mts → index-CYVpYGM-.d.mts} +2 -2
- package/dist/{index-B0Vq8Bwf.d.mts.map → index-CYVpYGM-.d.mts.map} +1 -1
- package/dist/{index-Bv7gxGK1.d.mts → index-Cq8jgdNY.d.mts} +90 -3
- package/dist/index-Cq8jgdNY.d.mts.map +1 -0
- package/dist/{index-9xte4JgL.d.mts → index-Dg5BAtDq.d.mts} +1446 -541
- package/dist/index-Dg5BAtDq.d.mts.map +1 -0
- package/dist/{index-C7-p9zwU.d.mts → index-DhL7ckvs.d.mts} +5 -5
- package/dist/index-DhL7ckvs.d.mts.map +1 -0
- package/dist/{index-GA9_Z8Fn.d.mts → index-RILu3ULT.d.mts} +2 -2
- package/dist/{index-GA9_Z8Fn.d.mts.map → index-RILu3ULT.d.mts.map} +1 -1
- package/dist/{index-C5sgRLlG.d.mts → index-TCtdSXd7.d.mts} +3 -1
- package/dist/index-TCtdSXd7.d.mts.map +1 -0
- package/dist/{index-CRaydvLi.d.mts → index-s2qQ8ifZ.d.mts} +886 -51
- package/dist/index-s2qQ8ifZ.d.mts.map +1 -0
- package/dist/index.d.mts +13 -13
- package/dist/index.mjs +52 -52
- package/dist/preview/index.d.mts +4 -4
- package/dist/preview/index.mjs +11 -11
- package/dist/preview-Dm912wly.mjs +1037 -0
- package/dist/preview-Dm912wly.mjs.map +1 -0
- package/dist/preview-engine/audio.mjs +1 -1
- package/dist/preview-engine/{chunk-64L4GUOF.mjs → chunk-4F3DG6YB.mjs} +2 -2
- package/dist/preview-engine/chunk-A2OTOW3B.mjs +4694 -0
- package/dist/preview-engine/{chunk-GNDE3OXQ.mjs → chunk-BR56TQBP.mjs} +1 -1
- package/dist/preview-engine/{chunk-ADLIF544.mjs → chunk-H2XKXXAU.mjs} +1 -1
- package/dist/preview-engine/chunk-NDUODAY2.mjs +3 -0
- package/dist/preview-engine/{chunk-FZ4RD7HV.mjs → chunk-QAQJSWUT.mjs} +1 -1
- package/dist/preview-engine/chunk-SWRGQTVC.mjs +138 -0
- package/dist/preview-engine/{chunk-52X7SURQ.mjs → chunk-TEA3GVBJ.mjs} +1 -1
- package/dist/preview-engine/chunk-VZUVB3BP.mjs +644 -0
- package/dist/preview-engine/{chunk-UBY2UYEL.mjs → chunk-XSHNQJ7L.mjs} +1 -1
- package/dist/preview-engine/components.mjs +1 -1
- package/dist/preview-engine/effects.mjs +1 -1
- package/dist/preview-engine/fonts.mjs +1 -1
- package/dist/preview-engine/framefields.mjs +1 -1
- package/dist/preview-engine/player.mjs +3 -3
- package/dist/preview-engine/{renderers-DU7KPFVV.mjs → renderers-6C7NWWDX.mjs} +1 -1
- package/dist/preview-engine/renderers-HHVGNMSJ.mjs +206 -0
- package/dist/preview-engine/{src-YXNX4MLK.mjs → src-RCNEKIRP.mjs} +1 -1
- package/dist/preview-page/index.html +19 -0
- package/dist/preview-page/main.css +1 -0
- package/dist/preview-page/main.js +326 -0
- package/dist/{program-tFKCWU2j.mjs → program-CMigyfso.mjs} +829 -52
- package/dist/program-CMigyfso.mjs.map +1 -0
- package/dist/renderer/index.d.mts +2 -2
- package/dist/renderer/index.mjs +2 -2
- package/dist/{renderer-DkOuQi84.mjs → renderer-0GMEL_Zi.mjs} +3 -3
- package/dist/{renderer-DkOuQi84.mjs.map → renderer-0GMEL_Zi.mjs.map} +1 -1
- package/dist/{renderer-BGp0An5A.mjs → renderer-3Wv2ZBJG.mjs} +3 -3
- package/dist/{renderer-BGp0An5A.mjs.map → renderer-3Wv2ZBJG.mjs.map} +1 -1
- package/dist/{renderer-BVIXKfbC.mjs → renderer-4nXkaAWu.mjs} +1178 -199
- package/dist/renderer-4nXkaAWu.mjs.map +1 -0
- package/dist/{renderer-Cw6_NL2i.mjs → renderer-6SnfLXeg.mjs} +3 -3
- package/dist/{renderer-Cw6_NL2i.mjs.map → renderer-6SnfLXeg.mjs.map} +1 -1
- package/dist/{renderer-BVU22lBS.mjs → renderer-8gHw3O0P.mjs} +2 -2
- package/dist/{renderer-BVU22lBS.mjs.map → renderer-8gHw3O0P.mjs.map} +1 -1
- package/dist/{renderer-BjDddtw9.mjs → renderer-AOBglZHC.mjs} +2 -2
- package/dist/{renderer-D-KHHWQD.mjs → renderer-B0bSARK3.mjs} +3 -3
- package/dist/{renderer-D-KHHWQD.mjs.map → renderer-B0bSARK3.mjs.map} +1 -1
- package/dist/{renderer-CCxk-RJR.mjs → renderer-B2_tuRfl.mjs} +2 -2
- package/dist/{renderer-CCxk-RJR.mjs.map → renderer-B2_tuRfl.mjs.map} +1 -1
- package/dist/{renderer-k5d7JSbs.mjs → renderer-B82FhkEr.mjs} +3 -3
- package/dist/{renderer-k5d7JSbs.mjs.map → renderer-B82FhkEr.mjs.map} +1 -1
- package/dist/{renderer-I0Hh9cLK.mjs → renderer-B9lzA0PY.mjs} +3 -3
- package/dist/{renderer-I0Hh9cLK.mjs.map → renderer-B9lzA0PY.mjs.map} +1 -1
- package/dist/{renderer-Dwwnx7Dk.mjs → renderer-BBSIWSry.mjs} +2 -2
- package/dist/{renderer-Dwwnx7Dk.mjs.map → renderer-BBSIWSry.mjs.map} +1 -1
- package/dist/{renderer-_pC-jB9O.mjs → renderer-BEKDMxbi.mjs} +2 -2
- package/dist/{renderer-_pC-jB9O.mjs.map → renderer-BEKDMxbi.mjs.map} +1 -1
- package/dist/renderer-BERGAxqA.mjs +5 -0
- package/dist/{renderer-raxwsiGI.mjs → renderer-BF960HY8.mjs} +3 -3
- package/dist/{renderer-raxwsiGI.mjs.map → renderer-BF960HY8.mjs.map} +1 -1
- package/dist/{renderer-Dr0tXA4k.mjs → renderer-BFwyVxCu.mjs} +3 -3
- package/dist/{renderer-Dr0tXA4k.mjs.map → renderer-BFwyVxCu.mjs.map} +1 -1
- package/dist/{renderer-DEjo6dw_.mjs → renderer-BNiwcI3-.mjs} +2 -2
- package/dist/{renderer-DEjo6dw_.mjs.map → renderer-BNiwcI3-.mjs.map} +1 -1
- package/dist/{renderer-DIEeHiQA.mjs → renderer-BPbVb2Q4.mjs} +2 -2
- package/dist/{renderer-DIEeHiQA.mjs.map → renderer-BPbVb2Q4.mjs.map} +1 -1
- package/dist/renderer-BQ_YkBMt.mjs +6 -0
- package/dist/{renderer-BBMtmxks.mjs → renderer-BUWxlA8T.mjs} +3 -3
- package/dist/{renderer-BBMtmxks.mjs.map → renderer-BUWxlA8T.mjs.map} +1 -1
- package/dist/renderer-BW0Tjsv9.mjs +5 -0
- package/dist/{renderer-Dgj46uEU.mjs → renderer-BX8liu-e.mjs} +2 -2
- package/dist/{renderer-ZnrEfkYh.mjs → renderer-BXIwDAr_.mjs} +2 -2
- package/dist/{renderer-ZnrEfkYh.mjs.map → renderer-BXIwDAr_.mjs.map} +1 -1
- package/dist/{renderer-DA8YEo_d.mjs → renderer-B_Hy1W-g.mjs} +3 -3
- package/dist/{renderer-DA8YEo_d.mjs.map → renderer-B_Hy1W-g.mjs.map} +1 -1
- package/dist/{renderer-iMiYStcW.mjs → renderer-Bb6cvSgh.mjs} +2 -2
- package/dist/{renderer-iMiYStcW.mjs.map → renderer-Bb6cvSgh.mjs.map} +1 -1
- package/dist/{renderer-BacY4nh8.mjs → renderer-BdppwWC9.mjs} +2 -2
- package/dist/{renderer-BacY4nh8.mjs.map → renderer-BdppwWC9.mjs.map} +1 -1
- package/dist/{renderer-CrxwW6VQ.mjs → renderer-Bhc24HVe.mjs} +3 -3
- package/dist/{renderer-CrxwW6VQ.mjs.map → renderer-Bhc24HVe.mjs.map} +1 -1
- package/dist/{renderer-BH7UCMPQ.mjs → renderer-BiNA2wF0.mjs} +2 -2
- package/dist/{renderer-BH7UCMPQ.mjs.map → renderer-BiNA2wF0.mjs.map} +1 -1
- package/dist/{renderer-DVPgWHZw.mjs → renderer-BmoBgTp5.mjs} +3 -3
- package/dist/{renderer-DVPgWHZw.mjs.map → renderer-BmoBgTp5.mjs.map} +1 -1
- package/dist/{renderer-C20efMI0.mjs → renderer-BmqFmCWS.mjs} +3 -3
- package/dist/{renderer-C20efMI0.mjs.map → renderer-BmqFmCWS.mjs.map} +1 -1
- package/dist/{renderer-B0yVUOPP.mjs → renderer-BnVwAObV.mjs} +2 -2
- package/dist/{renderer-B0yVUOPP.mjs.map → renderer-BnVwAObV.mjs.map} +1 -1
- package/dist/{renderer-CP8wLzTU.mjs → renderer-BxttZHme.mjs} +2 -2
- package/dist/{renderer-CP8wLzTU.mjs.map → renderer-BxttZHme.mjs.map} +1 -1
- package/dist/renderer-BzyPdUD1.mjs +5 -0
- package/dist/renderer-C0hM-mtY.mjs +5 -0
- package/dist/renderer-C6cyUTvk.mjs +5 -0
- package/dist/{renderer-BOSZAdgF.mjs → renderer-C8E4XsSg.mjs} +2 -2
- package/dist/{renderer-BOSZAdgF.mjs.map → renderer-C8E4XsSg.mjs.map} +1 -1
- package/dist/renderer-C8zY3pzk.mjs +5 -0
- package/dist/{renderer-DWq9gYRw.mjs → renderer-C9U-LY50.mjs} +3 -3
- package/dist/{renderer-DWq9gYRw.mjs.map → renderer-C9U-LY50.mjs.map} +1 -1
- package/dist/{renderer-Dj2H5JPR.mjs → renderer-CB2JVu5x.mjs} +3 -3
- package/dist/{renderer-Dj2H5JPR.mjs.map → renderer-CB2JVu5x.mjs.map} +1 -1
- package/dist/{renderer-Bcu3UrI-.mjs → renderer-CC4YBJ8Z.mjs} +3 -3
- package/dist/{renderer-Bcu3UrI-.mjs.map → renderer-CC4YBJ8Z.mjs.map} +1 -1
- package/dist/renderer-CEkSOyKu.mjs +5 -0
- package/dist/{renderer-DzLrvCB2.mjs → renderer-CIycc5O-.mjs} +2 -2
- package/dist/{renderer-DzLrvCB2.mjs.map → renderer-CIycc5O-.mjs.map} +1 -1
- package/dist/renderer-CJYtfa4x.mjs +5 -0
- package/dist/{renderer-BeNl_6EG.mjs → renderer-CJraQlV-.mjs} +2 -2
- package/dist/{renderer-BeNl_6EG.mjs.map → renderer-CJraQlV-.mjs.map} +1 -1
- package/dist/renderer-CKMtHGZh.mjs +5 -0
- package/dist/renderer-CLzicoiy.mjs +5 -0
- package/dist/renderer-CM2A4BHd.mjs +5 -0
- package/dist/{renderer-DtMVitEF.mjs → renderer-COWGWtob.mjs} +2 -2
- package/dist/{renderer-DtMVitEF.mjs.map → renderer-COWGWtob.mjs.map} +1 -1
- package/dist/{renderer-CT3zkfbf.mjs → renderer-COxG2XGf.mjs} +2 -2
- package/dist/{renderer-CT3zkfbf.mjs.map → renderer-COxG2XGf.mjs.map} +1 -1
- package/dist/{renderer-DNxWOz8Q.mjs → renderer-CQDCIsQm.mjs} +2 -2
- package/dist/{renderer-DNxWOz8Q.mjs.map → renderer-CQDCIsQm.mjs.map} +1 -1
- package/dist/{renderer-C5AoaymD.mjs → renderer-CRUeag8i.mjs} +3 -3
- package/dist/{renderer-C5AoaymD.mjs.map → renderer-CRUeag8i.mjs.map} +1 -1
- package/dist/{renderer-ngmYIIob.mjs → renderer-CWVput06.mjs} +3 -3
- package/dist/{renderer-ngmYIIob.mjs.map → renderer-CWVput06.mjs.map} +1 -1
- package/dist/renderer-CZlHjcxr.mjs +5 -0
- package/dist/{renderer-0rveCDm-.mjs → renderer-CbbnBLOB.mjs} +3 -3
- package/dist/{renderer-0rveCDm-.mjs.map → renderer-CbbnBLOB.mjs.map} +1 -1
- package/dist/renderer-CbimvSU8.mjs +5 -0
- package/dist/renderer-Ccvc63yd.mjs +5 -0
- package/dist/renderer-Cdp-SGfq.mjs +5 -0
- package/dist/renderer-CeTcSs3e.mjs +5 -0
- package/dist/{renderer-Brmbl12Y.mjs → renderer-CfLZein2.mjs} +3 -3
- package/dist/{renderer-Brmbl12Y.mjs.map → renderer-CfLZein2.mjs.map} +1 -1
- package/dist/{renderer-BJ8ea92W.mjs → renderer-Ch-q1O-q.mjs} +3 -3
- package/dist/{renderer-BJ8ea92W.mjs.map → renderer-Ch-q1O-q.mjs.map} +1 -1
- package/dist/{renderer-CP108ABB.mjs → renderer-Ch5JvJWl.mjs} +2 -2
- package/dist/{renderer-CP108ABB.mjs.map → renderer-Ch5JvJWl.mjs.map} +1 -1
- package/dist/{renderer-47y12Z37.mjs → renderer-ChtEzq-R.mjs} +2 -2
- package/dist/{renderer-47y12Z37.mjs.map → renderer-ChtEzq-R.mjs.map} +1 -1
- package/dist/{renderer-DhyMfG1v.mjs → renderer-Cj9nTC5l.mjs} +3 -3
- package/dist/{renderer-DhyMfG1v.mjs.map → renderer-Cj9nTC5l.mjs.map} +1 -1
- package/dist/{renderer-BDzn1AKF.mjs → renderer-CqT8HsSS.mjs} +2 -2
- package/dist/{renderer-BDzn1AKF.mjs.map → renderer-CqT8HsSS.mjs.map} +1 -1
- package/dist/{renderer-B7G1KohJ.mjs → renderer-CuQjMhdV.mjs} +2 -2
- package/dist/renderer-CvNuu52U.mjs +5 -0
- package/dist/renderer-CwciC0oI.mjs +5 -0
- package/dist/renderer-CysLUbIr.mjs +5 -0
- package/dist/{renderer-Cm0tsbQH.mjs → renderer-Cz30EVws.mjs} +2 -2
- package/dist/{renderer-Cm0tsbQH.mjs.map → renderer-Cz30EVws.mjs.map} +1 -1
- package/dist/renderer-D3A22Vxb.mjs +5 -0
- package/dist/renderer-D5SY9EmA.mjs +5 -0
- package/dist/renderer-D8h3ZvaE.mjs +5 -0
- package/dist/renderer-DE-B6N9n.mjs +5 -0
- package/dist/renderer-DETZTI7t.mjs +5 -0
- package/dist/{renderer-nHS3Sius.mjs → renderer-DHoX-5U_.mjs} +3 -3
- package/dist/{renderer-nHS3Sius.mjs.map → renderer-DHoX-5U_.mjs.map} +1 -1
- package/dist/{renderer-BWSRryIA.mjs → renderer-DOkm0Ycd.mjs} +2 -2
- package/dist/{renderer-BWSRryIA.mjs.map → renderer-DOkm0Ycd.mjs.map} +1 -1
- package/dist/{renderer-BHYJlK6H.d.mts → renderer-DU3f6ZrS.d.mts} +2 -2
- package/dist/{renderer-BHYJlK6H.d.mts.map → renderer-DU3f6ZrS.d.mts.map} +1 -1
- package/dist/{renderer-BpVOk9ux.mjs → renderer-DUzv-shq.mjs} +2 -2
- package/dist/{renderer-BpVOk9ux.mjs.map → renderer-DUzv-shq.mjs.map} +1 -1
- package/dist/renderer-DWnDj0IM.mjs +5 -0
- package/dist/renderer-DcGUIbQF.mjs +5 -0
- package/dist/renderer-Dfq6FoNO.mjs +5 -0
- package/dist/renderer-DhasXW6S.mjs +3 -0
- package/dist/{renderer-NRMlYkX6.mjs → renderer-DhnOWnEA.mjs} +3 -3
- package/dist/{renderer-NRMlYkX6.mjs.map → renderer-DhnOWnEA.mjs.map} +1 -1
- package/dist/{renderer-COgwYqev.mjs → renderer-Dhy1XHzz.mjs} +3 -3
- package/dist/{renderer-COgwYqev.mjs.map → renderer-Dhy1XHzz.mjs.map} +1 -1
- package/dist/renderer-DjCvpsV_.mjs +5 -0
- package/dist/{renderer-BfZNIiSv.mjs → renderer-DjJshz9Y.mjs} +2 -2
- package/dist/{renderer-BfZNIiSv.mjs.map → renderer-DjJshz9Y.mjs.map} +1 -1
- package/dist/{renderer-CKo7VR8x.mjs → renderer-DmTUIdus.mjs} +3 -3
- package/dist/{renderer-CKo7VR8x.mjs.map → renderer-DmTUIdus.mjs.map} +1 -1
- package/dist/{renderer-Baw6Utxi.mjs → renderer-Dq7AioJa.mjs} +2 -2
- package/dist/{renderer-Baw6Utxi.mjs.map → renderer-Dq7AioJa.mjs.map} +1 -1
- package/dist/renderer-DrAaM6JD.mjs +5 -0
- package/dist/{renderer-D-GWBoVT.mjs → renderer-Dt4sqNEu.mjs} +2 -2
- package/dist/{renderer-D-GWBoVT.mjs.map → renderer-Dt4sqNEu.mjs.map} +1 -1
- package/dist/{renderer-FYOL5Za6.mjs → renderer-Dtcs4idV.mjs} +3 -3
- package/dist/{renderer-FYOL5Za6.mjs.map → renderer-Dtcs4idV.mjs.map} +1 -1
- package/dist/renderer-Dxlv8LYm.mjs +5 -0
- package/dist/{renderer-D-RhYvVl.mjs → renderer-Gj8SrE2W.mjs} +2 -2
- package/dist/{renderer-D-RhYvVl.mjs.map → renderer-Gj8SrE2W.mjs.map} +1 -1
- package/dist/{renderer-D_j1WKMD.mjs → renderer-KfnXDJS0.mjs} +3 -3
- package/dist/{renderer-D_j1WKMD.mjs.map → renderer-KfnXDJS0.mjs.map} +1 -1
- package/dist/{renderer-Bpm145BW.mjs → renderer-MXVlg4p5.mjs} +3 -3
- package/dist/{renderer-Bpm145BW.mjs.map → renderer-MXVlg4p5.mjs.map} +1 -1
- package/dist/{renderer-Nnmi8Gt6.mjs → renderer-N2b6QZ1E.mjs} +3 -3
- package/dist/{renderer-Nnmi8Gt6.mjs.map → renderer-N2b6QZ1E.mjs.map} +1 -1
- package/dist/renderer-Pb43OO2t.mjs +5 -0
- package/dist/{renderer-Ca1KjNCO.mjs → renderer-Q7gDzm8c.mjs} +2 -2
- package/dist/{renderer-Ca1KjNCO.mjs.map → renderer-Q7gDzm8c.mjs.map} +1 -1
- package/dist/{renderer-D2wNFNRf.mjs → renderer-RCiANtRV.mjs} +2 -2
- package/dist/{renderer-D2wNFNRf.mjs.map → renderer-RCiANtRV.mjs.map} +1 -1
- package/dist/{renderer-Cqb7PGrI.mjs → renderer-Sig9nZcI.mjs} +2 -2
- package/dist/renderer-VQbm-cGr.mjs +5 -0
- package/dist/{renderer-W1bVNVR6.mjs → renderer-fabBgwQX.mjs} +3 -3
- package/dist/{renderer-W1bVNVR6.mjs.map → renderer-fabBgwQX.mjs.map} +1 -1
- package/dist/{renderer-zRq0j6Xy.mjs → renderer-g-0PCNoo.mjs} +3 -3
- package/dist/{renderer-zRq0j6Xy.mjs.map → renderer-g-0PCNoo.mjs.map} +1 -1
- package/dist/{renderer-2PjR3w-q.mjs → renderer-gmHKIbKI.mjs} +3 -3
- package/dist/{renderer-2PjR3w-q.mjs.map → renderer-gmHKIbKI.mjs.map} +1 -1
- package/dist/{renderer-03mYJLgX.mjs → renderer-kVZwiRoK.mjs} +3 -3
- package/dist/{renderer-03mYJLgX.mjs.map → renderer-kVZwiRoK.mjs.map} +1 -1
- package/dist/renderer-oPMypDM1.mjs +5 -0
- package/dist/{renderer-DcAKDAnS.mjs → renderer-p7tgxP-A.mjs} +3 -3
- package/dist/{renderer-DcAKDAnS.mjs.map → renderer-p7tgxP-A.mjs.map} +1 -1
- package/dist/{renderer-jUKdkmG5.mjs → renderer-tvYj306A.mjs} +81 -78
- package/dist/renderer-tvYj306A.mjs.map +1 -0
- package/dist/renderer-xvWGpVyp.mjs +5 -0
- package/dist/renderer-zafZbD6Q.mjs +5 -0
- package/dist/{renderers-CP8CFWDs-CshljORp.mjs → renderers-CP8CFWDs-DLjtjrwx.mjs} +2 -2
- package/dist/{renderers-CP8CFWDs-CshljORp.mjs.map → renderers-CP8CFWDs-DLjtjrwx.mjs.map} +1 -1
- package/dist/sam/index.d.mts +2 -2
- package/dist/sam/index.mjs +1 -1
- package/dist/signals/index.d.mts +4 -4
- package/dist/signals/index.mjs +4 -4
- package/dist/{src-BU6vm9sP-DdTHmCr4.mjs → src-B23p_eh7-Cj6-lvV6.mjs} +293 -6
- package/dist/src-B23p_eh7-Cj6-lvV6.mjs.map +1 -0
- package/dist/{src-Dy4gnc6w.mjs → src-CoHAjviq.mjs} +1349 -177
- package/dist/src-CoHAjviq.mjs.map +1 -0
- package/dist/storage/index.mjs +1 -1
- package/package.json +63 -60
- package/dist/dist--Uu5bQ_6.mjs.map +0 -1
- package/dist/dist-CiTgmfUw.mjs.map +0 -1
- package/dist/fonts-OW3yAfO5.mjs.map +0 -1
- package/dist/index-9xte4JgL.d.mts.map +0 -1
- package/dist/index-Bv7gxGK1.d.mts.map +0 -1
- package/dist/index-C5sgRLlG.d.mts.map +0 -1
- package/dist/index-C7-p9zwU.d.mts.map +0 -1
- package/dist/index-CRaydvLi.d.mts.map +0 -1
- package/dist/index-D1FqV1eu.d.mts.map +0 -1
- package/dist/preview-D7BGmE1E.mjs +0 -2446
- package/dist/preview-D7BGmE1E.mjs.map +0 -1
- package/dist/preview-engine/chunk-5DZTPUMH.mjs +0 -2568
- package/dist/preview-engine/chunk-NCQHOGZK.mjs +0 -3
- package/dist/preview-engine/chunk-PH3UUX6A.mjs +0 -138
- package/dist/preview-engine/chunk-UPZURPJY.mjs +0 -2227
- package/dist/preview-engine/renderers-DLJOA3BM.mjs +0 -228
- package/dist/program-tFKCWU2j.mjs.map +0 -1
- package/dist/renderer-6_bzbbXt.mjs +0 -5
- package/dist/renderer-8M-9G6F_.mjs +0 -5
- package/dist/renderer-B5OzKvF8.mjs +0 -5
- package/dist/renderer-BBCZ2qbE.mjs +0 -5
- package/dist/renderer-BChbxCux.mjs +0 -5
- package/dist/renderer-BGeMPr8C.mjs +0 -5
- package/dist/renderer-BPQ8Pkjb.mjs +0 -5
- package/dist/renderer-BTRpA3HD.mjs +0 -5
- package/dist/renderer-BVIXKfbC.mjs.map +0 -1
- package/dist/renderer-BVsECSn-.mjs +0 -5
- package/dist/renderer-Bgos68gc.mjs +0 -6
- package/dist/renderer-BjHOvoqO.mjs +0 -5
- package/dist/renderer-BjXMPPlV.mjs +0 -5
- package/dist/renderer-Byobxqkv.mjs +0 -5
- package/dist/renderer-CKrsg3EG.mjs +0 -5
- package/dist/renderer-Cj875NuH.mjs +0 -5
- package/dist/renderer-CnmzJoMv.mjs +0 -5
- package/dist/renderer-CtklDaMg.mjs +0 -5
- package/dist/renderer-D1tK3in_.mjs +0 -5
- package/dist/renderer-D2yc9P61.mjs +0 -5
- package/dist/renderer-D4v-JvSr.mjs +0 -5
- package/dist/renderer-D5yp74NL.mjs +0 -3
- package/dist/renderer-D7WRWDwB.mjs +0 -5
- package/dist/renderer-DGvA0tdB.mjs +0 -5
- package/dist/renderer-DO7v5Sdm.mjs +0 -5
- package/dist/renderer-DRVvt7-V.mjs +0 -5
- package/dist/renderer-DYMCd3jL.mjs +0 -5
- package/dist/renderer-DmHKw-MM.mjs +0 -5
- package/dist/renderer-DoDsuZ6G.mjs +0 -5
- package/dist/renderer-EpgclS70.mjs +0 -5
- package/dist/renderer-GroKiYyK.mjs +0 -5
- package/dist/renderer-MQ5K_xIS.mjs +0 -5
- package/dist/renderer-U43SflML.mjs +0 -5
- package/dist/renderer-UqOmBgCv.mjs +0 -5
- package/dist/renderer-XLULgJM0.mjs +0 -5
- package/dist/renderer-jUKdkmG5.mjs.map +0 -1
- package/dist/renderer-lNjxY1GG.mjs +0 -5
- package/dist/renderer-ukufL7pl.mjs +0 -5
- package/dist/renderer-wb0NCKdF.mjs +0 -5
- package/dist/src-BU6vm9sP-DdTHmCr4.mjs.map +0 -1
- package/dist/src-Dy4gnc6w.mjs.map +0 -1
package/NOTICE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Notice: framefields
|
|
2
2
|
|
|
3
|
-
framefields is licensed under Apache-2.0. It contains no model weights: every vision model downloads on first use from a pinned revision into the local model cache (`~/.cache/framefields/models`) and is verified by size and SHA-256. The licenses below apply to those downloaded weights, not to framefields' code.
|
|
3
|
+
framefields is licensed under Apache-2.0. It contains no model weights or human base assets: every vision model downloads on first use from a pinned revision into the local model cache (`~/.cache/framefields/models`) and is verified by size and SHA-256. The licenses below apply to those downloaded weights, not to framefields' code.
|
|
4
4
|
|
|
5
5
|
## Prompted tracking (SAM)
|
|
6
6
|
|
|
@@ -16,3 +16,7 @@ Before SAM 3 weights are downloaded or run, you must accept Meta's SAM License (
|
|
|
16
16
|
## Depth
|
|
17
17
|
|
|
18
18
|
`comp.vision(clip, { depth: true })` and `withVision({ mode: "depth" })` estimate depth with Depth Anything V2 **Small** (onnx-community export of `depth-anything/Depth-Anything-V2-Small`), whose weights are Apache-2.0. The larger Depth Anything V2 checkpoints are licensed CC-BY-NC-4.0 and are not used.
|
|
19
|
+
|
|
20
|
+
## Alpha matting
|
|
21
|
+
|
|
22
|
+
`comp.vision(clip, { matting: true })` and `VisionRunner.refineMatte` resolve mask edges with ViTMatte **Small** trained on Distinctions-646 (Xenova ONNX export of `hustvl/vitmatte-small-distinctions-646`). Its weights are Apache-2.0 and the ViTMatte code is MIT.
|
package/dist/audio/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../index-C-V6CAhP.mjs";
|
|
2
2
|
import { n as mixAudioTracks } from "../index-BVd6nXd5.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { nt as WebGPUAudioProcessor } from "../index-s2qQ8ifZ.mjs";
|
|
4
4
|
import "../renderer-DKJOon6y.mjs";
|
|
5
|
-
import { a as SfxTrigger, c as softLimit, d as _default$5, f as _default$4, h as _default$2, i as SfxRenderContext, l as _default$7, m as _default$3, n as encodeStereoWav, o as mixSfxInto, p as _default, r as RenderedSfx, s as renderSfx, t as EncodeWavOptions, u as _default$6 } from "../index-
|
|
6
|
-
import { t as _default$1 } from "../renderer-
|
|
5
|
+
import { a as SfxTrigger, c as softLimit, d as _default$5, f as _default$4, h as _default$2, i as SfxRenderContext, l as _default$7, m as _default$3, n as encodeStereoWav, o as mixSfxInto, p as _default, r as RenderedSfx, s as renderSfx, t as EncodeWavOptions, u as _default$6 } from "../index-RILu3ULT.mjs";
|
|
6
|
+
import { t as _default$1 } from "../renderer-DU3f6ZrS.mjs";
|
|
7
7
|
export { EncodeWavOptions, RenderedSfx, SfxRenderContext, SfxTrigger, WebGPUAudioProcessor, _default as audioFadeRenderer, _default$1 as audioSignalExtractorRenderer, _default$2 as compressorRenderer, _default$3 as delayRenderer, encodeStereoWav, mixAudioTracks, mixSfxInto, _default$4 as noiseGateRenderer, _default$5 as parametricEqRenderer, renderSfx, _default$6 as reverbRenderer, softLimit, _default$7 as stereoPanningRenderer };
|
package/dist/audio/index.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import "../chunk-DOL2i2sR.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as renderers_default$1 } from "../renderers-CP8CFWDs-
|
|
4
|
-
import { a as mixAudioTracks } from "../dist-
|
|
5
|
-
import { t as renderers_default$2 } from "../renderer-
|
|
6
|
-
import { t as renderers_default$3 } from "../renderer-
|
|
7
|
-
import { t as renderers_default } from "../renderer-
|
|
8
|
-
import { t as renderers_default$4 } from "../renderer-
|
|
9
|
-
import { t as renderers_default$5 } from "../renderer-
|
|
10
|
-
import { t as renderers_default$6 } from "../renderer-
|
|
2
|
+
import { y as WebGPUAudioProcessor } from "../dist-XqlFM2a8.mjs";
|
|
3
|
+
import { t as renderers_default$1 } from "../renderers-CP8CFWDs-DLjtjrwx.mjs";
|
|
4
|
+
import { a as mixAudioTracks } from "../dist-COOpgG9G.mjs";
|
|
5
|
+
import { t as renderers_default$2 } from "../renderer-CJraQlV-.mjs";
|
|
6
|
+
import { t as renderers_default$3 } from "../renderer-CqT8HsSS.mjs";
|
|
7
|
+
import { t as renderers_default } from "../renderer-BBSIWSry.mjs";
|
|
8
|
+
import { t as renderers_default$4 } from "../renderer-Gj8SrE2W.mjs";
|
|
9
|
+
import { t as renderers_default$5 } from "../renderer-DjJshz9Y.mjs";
|
|
10
|
+
import { t as renderers_default$6 } from "../renderer-BxttZHme.mjs";
|
|
11
11
|
import "../renderer-Co2YqWX0.mjs";
|
|
12
|
-
import { t as renderers_default$7 } from "../renderer-
|
|
12
|
+
import { t as renderers_default$7 } from "../renderer-Cz30EVws.mjs";
|
|
13
13
|
import { i as softLimit, n as mixSfxInto, r as renderSfx, t as encodeStereoWav } from "../audio-DS9Jg2ls.mjs";
|
|
14
14
|
|
|
15
15
|
export { WebGPUAudioProcessor, renderers_default as audioFadeRenderer, renderers_default$1 as audioSignalExtractorRenderer, renderers_default$2 as compressorRenderer, renderers_default$3 as delayRenderer, encodeStereoWav, mixAudioTracks, mixSfxInto, renderers_default$4 as noiseGateRenderer, renderers_default$5 as parametricEqRenderer, renderSfx, renderers_default$6 as reverbRenderer, softLimit, renderers_default$7 as stereoPanningRenderer };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Mt as frameArraySignal } from "./dist-C8XSqfTx.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { n as decodeAudioSource } from "./dist-
|
|
2
|
+
import { Ct as trackAudioPitch, R as ensureDevice, fn as AudioSignalComputePipeline } from "./dist-XqlFM2a8.mjs";
|
|
3
|
+
import { n as decodeAudioSource } from "./dist-COOpgG9G.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/signals/audio.ts
|
|
6
6
|
async function decodeOrThrow(source, purpose) {
|
|
@@ -108,4 +108,4 @@ const AudioSignal = {
|
|
|
108
108
|
|
|
109
109
|
//#endregion
|
|
110
110
|
export { AudioSignal as t };
|
|
111
|
-
//# sourceMappingURL=audio-
|
|
111
|
+
//# sourceMappingURL=audio-6TfPlfl4.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-
|
|
1
|
+
{"version":3,"file":"audio-6TfPlfl4.mjs","names":[],"sources":["../src/signals/audio.ts"],"sourcesContent":["import { decodeAudioSource } from \"@framefields/compositions\";\nimport {\n\ttype FrameSignal,\n\tframeArraySignal,\n\ttype GPUTextureBinding,\n} from \"@framefields/core\";\nimport {\n\ttype AudioPitchTrackConfig,\n\ttype AudioSignalComputeConfig,\n\tAudioSignalComputePipeline,\n\tensureDevice,\n\ttrackAudioPitch,\n} from \"@framefields/webgpu-renderers\";\n\nexport interface AudioSignalOptions extends AudioSignalComputeConfig {\n\tfps?: number;\n\ttargetWidth?: number;\n\tpreviewMode?: \"waveform\" | \"envelope\" | \"beat_markers\" | \"spectrum\";\n}\n\nexport interface ExtractedAudioSignalsBundle {\n\tprimary: FrameSignal<number>;\n\tbeat: FrameSignal<number>;\n\tbass: FrameSignal<number>;\n\tenergy: FrameSignal<number>;\n\tdurationSec: number;\n\tnumFrames: number;\n\tsampleRate: number;\n\ttextureView: unknown;\n\ttexture: unknown;\n\tprimaryBuffer: unknown;\n\tbeatBuffer: unknown;\n\tbassBuffer: unknown;\n\tenergyBuffer: unknown;\n\tseekFrame(frame: number): void;\n}\n\nexport interface AudioPitchOptions extends AudioPitchTrackConfig {\n\tfps?: number;\n}\n\n/** Fundamental frequency per frame, e.g. an engine note (RPM) or a melody line. */\nexport interface AudioPitchSignals {\n\t/** Pitch in Hz; interpolated across unvoiced gaps so it never drops to 0 mid-track. */\n\thz: FrameSignal<number>;\n\t/** 0..1 periodicity of the measured frame, 0 where unvoiced. */\n\tconfidence: FrameSignal<number>;\n\t/** 1 where a pitch was measured, 0 where `hz` is interpolated. */\n\tvoiced: FrameSignal<number>;\n\tsamples: { hz: Float32Array; confidence: Float32Array; voiced: Float32Array };\n\tfps: number;\n\tnumFrames: number;\n\tdurationSec: number;\n}\n\nasync function decodeOrThrow(source: string, purpose: string) {\n\tconst decoded = await decodeAudioSource(source);\n\tif (!decoded || decoded.channels.length === 0) {\n\t\tthrow new Error(`Failed to decode audio source for ${purpose}: ${source}`);\n\t}\n\treturn decoded;\n}\n\nexport const AudioSignal = {\n\tasync extractFromChannels(\n\t\tchannels: Float32Array[],\n\t\tsampleRate: number,\n\t\toptions: AudioSignalOptions = {},\n\t): Promise<ExtractedAudioSignalsBundle> {\n\t\tconst device = await ensureDevice();\n\t\tconst fps = options.fps ?? 24;\n\t\tconst targetWidth = options.targetWidth ?? 512;\n\n\t\tconst extracted = await AudioSignalComputePipeline.extractFeatures(\n\t\t\tdevice,\n\t\t\tchannels,\n\t\t\tsampleRate,\n\t\t\tfps,\n\t\t\toptions,\n\t\t\ttargetWidth,\n\t\t);\n\n\t\tconst samples = extracted.channelSamples ?? {\n\t\t\tprimary: new Float32Array(extracted.numFrames),\n\t\t\tbeat: new Float32Array(extracted.numFrames),\n\t\t\tbass: new Float32Array(extracted.numFrames),\n\t\t\tenergy: new Float32Array(extracted.numFrames),\n\t\t};\n\n\t\tconst primaryBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_primary\",\n\t\t\tchannel: \"primary\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.primaryBuffer,\n\t\t\tstats: extracted.stats.primary,\n\t\t};\n\t\tconst beatBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_beat\",\n\t\t\tchannel: \"beat\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.beatBuffer,\n\t\t\tstats: extracted.stats.beat,\n\t\t};\n\t\tconst bassBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_bass\",\n\t\t\tchannel: \"bass\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.bassBuffer,\n\t\t\tstats: extracted.stats.bass,\n\t\t};\n\t\tconst energyBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_energy\",\n\t\t\tchannel: \"energy\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.energyBuffer,\n\t\t\tstats: extracted.stats.energy,\n\t\t};\n\n\t\tconst primary = frameArraySignal(samples.primary, fps, primaryBinding);\n\t\tconst beat = frameArraySignal(samples.beat, fps, beatBinding);\n\t\tconst bass = frameArraySignal(samples.bass, fps, bassBinding);\n\t\tconst energy = frameArraySignal(samples.energy, fps, energyBinding);\n\n\t\treturn {\n\t\t\tprimary,\n\t\t\tbeat,\n\t\t\tbass,\n\t\t\tenergy,\n\t\t\tdurationSec: extracted.durationSec,\n\t\t\tnumFrames: extracted.numFrames,\n\t\t\tsampleRate,\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tprimaryBuffer: extracted.primaryBuffer,\n\t\t\tbeatBuffer: extracted.beatBuffer,\n\t\t\tbassBuffer: extracted.bassBuffer,\n\t\t\tenergyBuffer: extracted.energyBuffer,\n\t\t\tseekFrame(frame: number) {\n\t\t\t\tprimary.seekFrame?.(frame);\n\t\t\t\tbeat.seekFrame?.(frame);\n\t\t\t\tbass.seekFrame?.(frame);\n\t\t\t\tenergy.seekFrame?.(frame);\n\t\t\t},\n\t\t};\n\t},\n\n\tasync extract(\n\t\tsource: string,\n\t\toptions: AudioSignalOptions = {},\n\t): Promise<ExtractedAudioSignalsBundle> {\n\t\tconst decoded = await decodeOrThrow(source, \"feature extraction\");\n\t\treturn AudioSignal.extractFromChannels(\n\t\t\tdecoded.channels,\n\t\t\tdecoded.sampleRate,\n\t\t\toptions,\n\t\t);\n\t},\n\n\t/** Tracks the fundamental frequency of the downmixed channels on the GPU. */\n\tasync pitchFromChannels(\n\t\tchannels: Float32Array[],\n\t\tsampleRate: number,\n\t\toptions: AudioPitchOptions = {},\n\t): Promise<AudioPitchSignals> {\n\t\tconst device = await ensureDevice();\n\t\tconst fps = options.fps ?? 24;\n\t\tconst track = await trackAudioPitch(\n\t\t\tdevice,\n\t\t\tchannels,\n\t\t\tsampleRate,\n\t\t\tfps,\n\t\t\toptions,\n\t\t);\n\t\treturn {\n\t\t\thz: frameArraySignal(track.hz, fps),\n\t\t\tconfidence: frameArraySignal(track.confidence, fps),\n\t\t\tvoiced: frameArraySignal(track.voiced, fps),\n\t\t\tsamples: {\n\t\t\t\thz: track.hz,\n\t\t\t\tconfidence: track.confidence,\n\t\t\t\tvoiced: track.voiced,\n\t\t\t},\n\t\t\tfps,\n\t\t\tnumFrames: track.numFrames,\n\t\t\tdurationSec: track.durationSec,\n\t\t};\n\t},\n\n\t/** Decodes `source` (audio or video file) and tracks its pitch. */\n\tasync pitch(\n\t\tsource: string,\n\t\toptions: AudioPitchOptions = {},\n\t): Promise<AudioPitchSignals> {\n\t\tconst decoded = await decodeOrThrow(source, \"pitch tracking\");\n\t\treturn AudioSignal.pitchFromChannels(\n\t\t\tdecoded.channels,\n\t\t\tdecoded.sampleRate,\n\t\t\toptions,\n\t\t);\n\t},\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { $ as FrameSignal } from "./index-C-V6CAhP.mjs";
|
|
2
|
-
import { l as AudioPitchTrackConfig, n as NodeRendererPlugin, u as AudioSignalComputeConfig } from "./index-
|
|
2
|
+
import { l as AudioPitchTrackConfig, n as NodeRendererPlugin, u as AudioSignalComputeConfig } from "./index-s2qQ8ifZ.mjs";
|
|
3
3
|
|
|
4
4
|
//#region ../../nodes/node-modulate/dist/renderer.d.mts
|
|
5
5
|
//#region src/renderers/index.d.ts
|
|
@@ -58,4 +58,4 @@ declare const AudioSignal: {
|
|
|
58
58
|
};
|
|
59
59
|
//#endregion
|
|
60
60
|
export { ExtractedAudioSignalsBundle as a, AudioSignalOptions as i, AudioPitchSignals as n, _default as o, AudioSignal as r, AudioPitchOptions as t };
|
|
61
|
-
//# sourceMappingURL=audio-
|
|
61
|
+
//# sourceMappingURL=audio-7oqTUi4G.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-
|
|
1
|
+
{"version":3,"file":"audio-7oqTUi4G.d.mts","names":["_framefields_node_sdk_renderer0","_default","NodeRendererPlugin","Readonly","default"],"sources":["../../../nodes/node-modulate/dist/renderer.d.mts","../src/signals/audio.ts"],"sourcesContent":["import * as _framefields_node_sdk_renderer0 from \"@framefields/node-sdk/renderer\";\n\n//#region src/renderers/index.d.ts\ndeclare const _default: Readonly<_framefields_node_sdk_renderer0.NodeRendererPlugin>;\n//#endregion\nexport { _default as default };\n//# sourceMappingURL=renderer.d.mts.map"],"mappings":";;;;;cAGcC,UAAUE,SAASH;AAHiD;;;UCcjE,kBAAA,SAA2B;;EDX9BC,WAAsE,CAAA,EAAA,MAAA;;;UCiBnE,2BAAA;EANA,OAAA,EAOP,WAPO,CAAmB,MAAA,CAAA;EAMnB,IAAA,EAEV,WAFU,CAAA,MAAA,CAAA;EACP,IAAA,EAEH,WAFG,CAAA,MAAA,CAAA;EACH,MAAA,EAEE,WAFF,CAAA,MAAA,CAAA;EACA,WAAA,EAAA,MAAA;EACE,SAAA,EAAA,MAAA;EAAW,UAAA,EAAA,MAAA;EAaH,WAAA,EAAA,OAAkB;EAKlB,OAAA,EAAA,OAAA;EAEZ,aAAA,EAAA,OAAA;EAEQ,UAAA,EAAA,OAAA;EAEJ,UAAA,EAAA,OAAA;EACO,YAAA,EAAA,OAAA;EAA0B,SAAA,CAAA,KAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;AAAkC,UAZ3D,iBAAA,SAA0B,qBAYiC,CAAA;EAc/D,GAAA,CAAA,EAAA,MAAA;;;AAKD,UA1BK,iBAAA,CA0BL;EAAR;EAoFO,EAAA,EA5GN,WA4GM,CAAA,MAAA,CAAA;EACC;EAAR,UAAA,EA3GS,WA2GT,CAAA,MAAA,CAAA;EAWQ;EAED,MAAA,EAtHF,WAsHE,CAAA,MAAA,CAAA;EACC,OAAA,EAAA;IAAR,EAAA,EAtHY,YAsHZ;IA4BO,UAAA,EAlJ+B,YAkJ/B;IACC,MAAA,EAnJoD,YAmJpD;EAAR,CAAA;EAAO,GAAA,EAAA,MAAA;;;;cArIE;gCAED,8CAED,qBACP,QAAQ;oCAoFD,qBACP,QAAQ;;8BAWA,8CAED,oBACP,QAAQ;;kCA4BD,oBACP,QAAQ"}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
import "../chunk-DOL2i2sR.mjs";
|
|
2
2
|
import { Nt as frameCount } from "../dist-C8XSqfTx.mjs";
|
|
3
|
-
import { t as Composition } from "../src-
|
|
4
|
-
import {
|
|
5
|
-
import "../renderers-CP8CFWDs-
|
|
3
|
+
import { t as Composition } from "../src-CoHAjviq.mjs";
|
|
4
|
+
import { O as describeGpu } from "../dist-XqlFM2a8.mjs";
|
|
5
|
+
import "../renderers-CP8CFWDs-DLjtjrwx.mjs";
|
|
6
6
|
import "../signals-tiho_9fp.mjs";
|
|
7
|
-
import "../renderer-
|
|
7
|
+
import "../renderer-g-0PCNoo.mjs";
|
|
8
8
|
import "../renderer-DGOMfyh8.mjs";
|
|
9
|
-
import "../renderer-
|
|
10
|
-
import "../renderer-
|
|
11
|
-
import "../renderer-
|
|
12
|
-
import "../renderer-
|
|
13
|
-
import "../renderer-
|
|
14
|
-
import "../renderer-
|
|
9
|
+
import "../renderer-CJraQlV-.mjs";
|
|
10
|
+
import "../renderer-CqT8HsSS.mjs";
|
|
11
|
+
import "../renderer-BBSIWSry.mjs";
|
|
12
|
+
import "../renderer-Gj8SrE2W.mjs";
|
|
13
|
+
import "../renderer-DjJshz9Y.mjs";
|
|
14
|
+
import "../renderer-BxttZHme.mjs";
|
|
15
15
|
import "../renderer-Co2YqWX0.mjs";
|
|
16
|
-
import "../renderer-
|
|
17
|
-
import { s as CompositorProgramSchema } from "../program-
|
|
18
|
-
import "../renderer-
|
|
19
|
-
import "../renderer-
|
|
20
|
-
import "../renderer-
|
|
21
|
-
import "../renderer-
|
|
22
|
-
import "../renderer-
|
|
23
|
-
import "../renderer-
|
|
24
|
-
import "../renderer-
|
|
25
|
-
import "../renderer-
|
|
26
|
-
import "../renderer-
|
|
27
|
-
import "../renderer-
|
|
28
|
-
import "../renderer-
|
|
29
|
-
import "../renderer-
|
|
30
|
-
import "../renderer-
|
|
31
|
-
import "../renderer-
|
|
32
|
-
import "../renderer-
|
|
33
|
-
import "../renderer-
|
|
34
|
-
import "../renderer-
|
|
35
|
-
import "../renderer-
|
|
36
|
-
import "../renderer-
|
|
37
|
-
import "../renderer-
|
|
38
|
-
import "../renderer-
|
|
39
|
-
import "../renderer-
|
|
40
|
-
import "../renderer-
|
|
41
|
-
import "../renderer-
|
|
42
|
-
import "../renderer-
|
|
43
|
-
import "../renderer-
|
|
44
|
-
import "../renderer-
|
|
45
|
-
import "../renderer-
|
|
46
|
-
import "../renderer-
|
|
47
|
-
import "../renderer-
|
|
48
|
-
import "../renderer-
|
|
49
|
-
import "../renderer-
|
|
16
|
+
import "../renderer-Cz30EVws.mjs";
|
|
17
|
+
import { s as CompositorProgramSchema } from "../program-CMigyfso.mjs";
|
|
18
|
+
import "../renderer-CC4YBJ8Z.mjs";
|
|
19
|
+
import "../renderer-DOkm0Ycd.mjs";
|
|
20
|
+
import "../renderer-p7tgxP-A.mjs";
|
|
21
|
+
import "../renderer-CQDCIsQm.mjs";
|
|
22
|
+
import "../renderer-COxG2XGf.mjs";
|
|
23
|
+
import "../renderer-BnVwAObV.mjs";
|
|
24
|
+
import "../renderer-BPbVb2Q4.mjs";
|
|
25
|
+
import "../renderer-DmTUIdus.mjs";
|
|
26
|
+
import "../renderer-fabBgwQX.mjs";
|
|
27
|
+
import "../renderer-Bb6cvSgh.mjs";
|
|
28
|
+
import "../renderer-gmHKIbKI.mjs";
|
|
29
|
+
import "../renderer-KfnXDJS0.mjs";
|
|
30
|
+
import "../renderer-BiNA2wF0.mjs";
|
|
31
|
+
import "../renderer-BEKDMxbi.mjs";
|
|
32
|
+
import "../renderer-B2_tuRfl.mjs";
|
|
33
|
+
import "../renderer-N2b6QZ1E.mjs";
|
|
34
|
+
import "../renderer-8gHw3O0P.mjs";
|
|
35
|
+
import "../renderer-B9lzA0PY.mjs";
|
|
36
|
+
import "../renderer-BNiwcI3-.mjs";
|
|
37
|
+
import "../renderer-BXIwDAr_.mjs";
|
|
38
|
+
import "../renderer-Ch5JvJWl.mjs";
|
|
39
|
+
import "../renderer-Q7gDzm8c.mjs";
|
|
40
|
+
import "../renderer-BdppwWC9.mjs";
|
|
41
|
+
import "../renderer-BUWxlA8T.mjs";
|
|
42
|
+
import "../renderer-CbbnBLOB.mjs";
|
|
43
|
+
import "../renderer-B_Hy1W-g.mjs";
|
|
44
|
+
import "../renderer-COWGWtob.mjs";
|
|
45
|
+
import "../renderer-CIycc5O-.mjs";
|
|
46
|
+
import "../renderer-RCiANtRV.mjs";
|
|
47
|
+
import "../renderer-C8E4XsSg.mjs";
|
|
48
|
+
import "../renderer-Dq7AioJa.mjs";
|
|
49
|
+
import "../renderer-Dt4sqNEu.mjs";
|
|
50
50
|
import { t as failedCheck } from "../check-result-DZWx73V8.mjs";
|
|
51
51
|
import { existsSync } from "node:fs";
|
|
52
52
|
import { join } from "node:path";
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
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-
|
|
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-jnk1hPYf.mjs";
|
|
3
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";
|
package/dist/cloud/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as withNamedRender, i as renderCloud, n as FRAMEFIELDS_API_URL, o as resolveGitSource, r as cloudClient, s as toHttps, t as CloudRenderError } from "../cloud-
|
|
1
|
+
import { a as withNamedRender, i as renderCloud, n as FRAMEFIELDS_API_URL, o as resolveGitSource, r as cloudClient, s as toHttps, t as CloudRenderError } from "../cloud-jnk1hPYf.mjs";
|
|
2
2
|
|
|
3
3
|
export { CloudRenderError, FRAMEFIELDS_API_URL, cloudClient, renderCloud, resolveGitSource, toHttps, withNamedRender };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as parseStorage, c as credentialEnvNames, f as hashFile, g as parseAssets, l as credentialsFromEnv, n as Bucket, p as isAssetPath, u as downloadVerified, v as pickRemote, x as readUrl } from "./dist-
|
|
1
|
+
import { _ as parseStorage, c as credentialEnvNames, f as hashFile, g as parseAssets, l as credentialsFromEnv, n as Bucket, p as isAssetPath, u as downloadVerified, v as pickRemote, x as readUrl } from "./dist-f1zkl69f.mjs";
|
|
2
2
|
import { appendFileSync, createWriteStream, existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "node:fs";
|
|
3
3
|
import path, { join, relative, resolve, sep } from "node:path";
|
|
4
4
|
import fs$1 from "node:fs/promises";
|
|
@@ -682,4 +682,4 @@ function sleep(ms, signal) {
|
|
|
682
682
|
|
|
683
683
|
//#endregion
|
|
684
684
|
export { withNamedRender as a, AssetsError as c, runAssets as d, CONFIG_FILE as f, writeConfig as h, renderCloud as i, megabytes as l, readConfig as m, FRAMEFIELDS_API_URL as n, resolveGitSource as o, findRender as p, cloudClient as r, toHttps as s, CloudRenderError as t, pullAssets as u };
|
|
685
|
-
//# sourceMappingURL=cloud-
|
|
685
|
+
//# sourceMappingURL=cloud-jnk1hPYf.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-Cj1TIme8.mjs","names":["path","fs","resolve"],"sources":["../src/cli/config.ts","../src/cli/assets.ts","../src/cloud/git-source.ts","../src/cloud/index.ts"],"sourcesContent":["/**\n * `framefields.json` at the project root: where installed components live,\n * which fonts `framefields add` / `framefields fonts add` installed, and the\n * project's named renders.\n *\n * ```json\n * {\n * \"components\": \"src/components\",\n * \"renders\": {\n * \"film\": {\n * \"title\": \"Launch film\",\n * \"entry\": \"src/film.ts\",\n * \"export\": \"buildFilm\",\n * \"workers\": \"auto\"\n * }\n * }\n * }\n * ```\n *\n * A named render is what `framefields render film --cloud`, `framefields\n * check film`, `renderCloud({ render: \"film\" })` and the dashboard's New\n * render dialog pick, so nobody chooses files and exports by hand.\n *\n * `storage` and `assets` pin media by content on an S3-compatible bucket\n * (`framefields assets`; the format lives in `@framefields/storage`).\n */\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n\ttype AssetManifest,\n\tparseAssets,\n\tparseStorage,\n\ttype StorageConfig,\n} from \"@framefields/storage\";\n\nexport const CONFIG_FILE = \"framefields.json\";\n\n/** One renderable piece of the project: an export of a module, with its defaults. */\nexport interface RenderSpec {\n\t/** The module that builds the composition, relative to the project root. */\n\tentry: string;\n\t/** A Composition, or a function returning one. Default `buildFilm`. */\n\texport?: string;\n\t/** Shown in the dashboard and `framefields renders`. Default: the name. */\n\ttitle?: string;\n\tdescription?: string;\n\t/** Passed to the export when it is a function. */\n\targs?: unknown;\n\t/** When the export returns several compositions, the one to render. */\n\tselect?: string;\n\t/** Cloud workers: 1, a number, or \"auto\" to split long films. Default 1. */\n\tworkers?: number | \"auto\";\n\tmaxWorkers?: number;\n\tcodec?: \"h264\" | \"vp9\";\n\tquality?: \"very_low\" | \"low\" | \"high\" | \"very_high\";\n\t/** Where `framefields render <name> --cloud` writes the video. */\n\toutput?: string;\n}\n\nexport interface ProjectConfig {\n\t/** Components directory, relative to the project root. */\n\tcomponents: string;\n\t/**\n\t * Font files by role (`emoji`), relative to the project root. A role\n\t * set here counts as installed: point it at your own font to use that.\n\t */\n\tfonts?: Partial<Record<string, string>>;\n\t/** Named renders, by name (letters, digits, `-`, `_`, `.`). */\n\trenders?: Record<string, RenderSpec>;\n\t/** Buckets holding the project's assets. */\n\tstorage?: StorageConfig;\n\t/** Files the project needs, by path, pinned by sha256 and size. */\n\tassets?: AssetManifest;\n}\n\nexport const RENDER_NAME = /^[A-Za-z0-9][\\w.-]{0,63}$/;\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\nconst QUALITIES = [\"very_low\", \"low\", \"high\", \"very_high\"];\n\n/**\n * The project's config, or the default it would get: `src/components` when\n * there is a `src`. `saved` is whether the file records a components folder.\n */\nexport function readConfig(cwd: string): {\n\tconfig: ProjectConfig;\n\tsaved: boolean;\n} {\n\tconst file = join(cwd, CONFIG_FILE);\n\tconst fallback = existsSync(join(cwd, \"src\"))\n\t\t? \"src/components\"\n\t\t: \"components\";\n\tif (!existsSync(file))\n\t\treturn { config: { components: fallback }, saved: false };\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(readFileSync(file, \"utf8\"));\n\t} catch (err) {\n\t\tthrow new Error(\n\t\t\t`${CONFIG_FILE} is not valid JSON: ${(err as Error).message}`,\n\t\t);\n\t}\n\tif (!isRecord(raw)) throw new Error(`${CONFIG_FILE} must be a JSON object`);\n\tconst { components, fonts, renders, storage, assets } = raw;\n\tif (components !== undefined && typeof components !== \"string\")\n\t\tthrow new Error(`${CONFIG_FILE}: \"components\" must be a directory path`);\n\tif (\n\t\tfonts !== undefined &&\n\t\t(!isRecord(fonts) ||\n\t\t\tObject.values(fonts).some((v) => typeof v !== \"string\"))\n\t)\n\t\tthrow new Error(\n\t\t\t`${CONFIG_FILE}: \"fonts\" must map roles to font file paths, e.g. { \"emoji\": \"assets/fonts/NotoColorEmoji.ttf\" }`,\n\t\t);\n\tconst parsedStorage =\n\t\tstorage === undefined ? undefined : parseStorage(storage);\n\t// Other keys (a `$schema`, say) survive a rewrite.\n\tconst config = {\n\t\t...raw,\n\t\tcomponents: components ?? fallback,\n\t\t...(renders !== undefined && { renders: parseRenders(renders) }),\n\t\t...(parsedStorage && { storage: parsedStorage }),\n\t\t...(assets !== undefined && {\n\t\t\tassets: parseAssets(assets, parsedStorage),\n\t\t}),\n\t} as ProjectConfig;\n\treturn { config, saved: components !== undefined };\n}\n\nexport function writeConfig(cwd: string, config: ProjectConfig): void {\n\twriteFileSync(\n\t\tjoin(cwd, CONFIG_FILE),\n\t\t`${JSON.stringify(config, null, \"\\t\")}\\n`,\n\t);\n}\n\n/** Validates the `renders` map; errors name the render and field at fault. */\nexport function parseRenders(value: unknown): Record<string, RenderSpec> {\n\tif (!isRecord(value))\n\t\tthrow new Error(\n\t\t\t`${CONFIG_FILE}: \"renders\" must map names to renders, e.g. { \"film\": { \"entry\": \"src/film.ts\" } }`,\n\t\t);\n\tconst out: Record<string, RenderSpec> = {};\n\tfor (const [name, spec] of Object.entries(value)) {\n\t\tconst fail = (message: string) => {\n\t\t\tthrow new Error(`${CONFIG_FILE}: renders.${name} ${message}`);\n\t\t};\n\t\tif (!RENDER_NAME.test(name))\n\t\t\tfail(\"has an invalid name: use letters, digits, -, _ and . (at most 64)\");\n\t\tif (!isRecord(spec)) fail(\"must be an object with an entry\");\n\t\tconst s = spec as Record<string, unknown>;\n\t\tif (!isRelativePath(s.entry))\n\t\t\tfail(\n\t\t\t\t'needs \"entry\": the module path inside the project, e.g. \"src/film.ts\"',\n\t\t\t);\n\t\tif (\n\t\t\ts.export !== undefined &&\n\t\t\t!(typeof s.export === \"string\" && IDENTIFIER.test(s.export))\n\t\t)\n\t\t\tfail('\"export\" must be a JavaScript identifier');\n\t\tfor (const key of [\"title\", \"description\", \"select\"] as const)\n\t\t\tif (s[key] !== undefined && typeof s[key] !== \"string\")\n\t\t\t\tfail(`\"${key}\" must be a string`);\n\t\tif (s.workers !== undefined && s.workers !== \"auto\" && !isCount(s.workers))\n\t\t\tfail('\"workers\" must be \"auto\" or a positive whole number');\n\t\tif (s.maxWorkers !== undefined && !isCount(s.maxWorkers))\n\t\t\tfail('\"maxWorkers\" must be a positive whole number');\n\t\tif (s.codec !== undefined && s.codec !== \"h264\" && s.codec !== \"vp9\")\n\t\t\tfail('\"codec\" must be \"h264\" or \"vp9\"');\n\t\tif (s.quality !== undefined && !QUALITIES.includes(s.quality as string))\n\t\t\tfail(`\"quality\" must be one of ${QUALITIES.join(\", \")}`);\n\t\tif (s.output !== undefined && typeof s.output !== \"string\")\n\t\t\tfail('\"output\" must be a file path');\n\t\tout[name] = s as unknown as RenderSpec;\n\t}\n\treturn out;\n}\n\n/**\n * The named render `name` of the project at `cwd`, or undefined when there\n * is no render by that name (an entry path, say).\n */\nexport function findRender(\n\tcwd: string,\n\tname: string,\n): (RenderSpec & { name: string }) | undefined {\n\tconst spec = readConfig(cwd).config.renders?.[name];\n\treturn spec && { ...spec, name };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isCount(value: unknown): boolean {\n\treturn typeof value === \"number\" && Number.isInteger(value) && value >= 1;\n}\n\nfunction isRelativePath(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\t!value.startsWith(\"/\") &&\n\t\t!value.split(/[/\\\\]/).includes(\"..\")\n\t);\n}\n","/**\n * `framefields assets`: media kept out of git, on an S3-compatible bucket\n * (R2, S3, B2, MinIO), pinned by content in `framefields.json`.\n *\n * add <path...> hash, upload what the bucket lacks, record, gitignore\n * push upload recorded assets the bucket lacks\n * pull download missing assets, verified byte for byte\n * status which assets are here, missing, or changed\n *\n * Reads need no keys when the remote has a `publicUrl` (a custom domain or\n * CDN in front of the bucket); otherwise they're signed with the remote's\n * keys. Cloud renders get signed URLs for private assets from the CLI, so\n * the keys never leave the machine.\n */\nimport { execFileSync } from \"node:child_process\";\nimport {\n\tappendFileSync,\n\texistsSync,\n\treaddirSync,\n\treadFileSync,\n\tstatSync,\n} from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport {\n\ttype AssetEntry,\n\ttype AssetManifest,\n\tBucket,\n\tcredentialEnvNames,\n\tcredentialsFromEnv,\n\tdownloadVerified,\n\thashFile,\n\tisAssetPath,\n\tpickRemote,\n\treadUrl,\n\ttype StorageConfig,\n} from \"@framefields/storage\";\nimport { CONFIG_FILE, readConfig, writeConfig } from \"./config.js\";\n\nexport interface AssetOptions {\n\t/** Project folder (where framefields.json is). */\n\tcwd: string;\n\t/** Where remote keys come from. Default `process.env`. */\n\tenv?: Readonly<Record<string, string | undefined>>;\n\tfetch?: typeof fetch;\n\tlog?: (line: string) => void;\n\tsignal?: AbortSignal;\n}\n\nexport type AssetsErrorCode =\n\t| \"no_storage\"\n\t| \"no_credentials\"\n\t| \"not_uploaded\"\n\t| \"outside_project\"\n\t| \"not_found\";\n\nexport class AssetsError extends Error {\n\toverride name = \"AssetsError\";\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly code: AssetsErrorCode,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\nexport type AssetState = \"ok\" | \"missing\" | \"changed\";\n\n/** Hashes and uploads files (folders: every file in them), and records them. */\nexport async function addAssets(\n\tpaths: string[],\n\toptions: AssetOptions & { remote?: string },\n): Promise<{ path: string; size: number; uploaded: boolean }[]> {\n\tconst { cwd } = options;\n\tconst { config } = readConfig(cwd);\n\tconst { name, remote } = pickRemote(config.storage, options.remote);\n\tconst bucket = openBucket(config.storage, name, options);\n\tconst files = paths.flatMap((p) => expand(cwd, p));\n\tif (files.length === 0)\n\t\tthrow new AssetsError(`No files in ${paths.join(\", \")}.`, \"not_found\");\n\tconst added: { path: string; size: number; uploaded: boolean }[] = [];\n\tconst assets: AssetManifest = { ...config.assets };\n\tfor (const file of files) {\n\t\tconst digest = await hashFile(join(cwd, file));\n\t\tconst uploaded = !(await bucket.has(digest.sha256, digest.size));\n\t\tif (uploaded) await upload(bucket, cwd, file, digest, options.log);\n\t\tconst isDefault = name === pickRemote(config.storage).name;\n\t\tassets[file] = { ...digest, ...(!isDefault && { remote: name }) };\n\t\tadded.push({ path: file, size: digest.size, uploaded });\n\t}\n\twriteConfig(cwd, { ...config, assets: sortKeys(assets) });\n\tignore(cwd, files);\n\tconst tracked = trackedByGit(cwd, files);\n\tif (tracked.length)\n\t\toptions.log?.(\n\t\t\t`Already committed to git: ${tracked.join(\", \")}. Stop tracking them with \\`git rm --cached ${tracked.join(\" \")}\\` (the files stay here).`,\n\t\t);\n\tif (remote.publicUrl === undefined)\n\t\toptions.log?.(\n\t\t\t`${name} has no publicUrl: cloud renders from the CLI sign reads, dashboard renders can't read it.`,\n\t\t);\n\treturn added;\n}\n\n/** Uploads every recorded asset its bucket lacks, from the local file. */\nexport async function pushAssets(\n\toptions: AssetOptions,\n): Promise<{ uploaded: string[]; present: string[] }> {\n\tconst { config } = readConfig(options.cwd);\n\tconst uploaded: string[] = [];\n\tconst present: string[] = [];\n\tconst problems: string[] = [];\n\tfor (const [path, entry] of storedAssets(config.assets)) {\n\t\tconst bucket = openBucket(config.storage, entry.remote, options);\n\t\tif (await bucket.has(entry.sha256, entry.size)) {\n\t\t\tpresent.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tconst state = await localState(options.cwd, path, entry);\n\t\tif (state !== \"ok\") {\n\t\t\tproblems.push(`${path} (${state} here)`);\n\t\t\tcontinue;\n\t\t}\n\t\tawait upload(bucket, options.cwd, path, entry, options.log);\n\t\tuploaded.push(path);\n\t}\n\tif (problems.length)\n\t\tthrow new AssetsError(\n\t\t\t`Not on the bucket, and the local file doesn't match ${CONFIG_FILE}: ${problems.join(\", \")}. Restore the file, or record the new version with \\`framefields assets add\\`.`,\n\t\t\t\"not_uploaded\",\n\t\t);\n\treturn { uploaded, present };\n}\n\n/**\n * Downloads every asset that's missing here. Files changed locally are\n * left alone (and reported) unless `overwrite`.\n */\nexport async function pullAssets(\n\toptions: AssetOptions & { overwrite?: boolean },\n): Promise<{ downloaded: string[]; present: string[]; changed: string[] }> {\n\tconst { config } = readConfig(options.cwd);\n\tconst result = {\n\t\tdownloaded: [] as string[],\n\t\tpresent: [] as string[],\n\t\tchanged: [] as string[],\n\t};\n\tfor (const [path, entry] of Object.entries(config.assets ?? {})) {\n\t\tconst state = await localState(options.cwd, path, entry);\n\t\tif (state === \"ok\") {\n\t\t\tresult.present.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tif (state === \"changed\" && !options.overwrite) {\n\t\t\tresult.changed.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tconst url = await readableUrl(entry, config.storage, options);\n\t\toptions.log?.(`Downloading ${path} (${megabytes(entry.size)})`);\n\t\tawait downloadVerified(url, join(options.cwd, path), entry, {\n\t\t\tfetch: options.fetch,\n\t\t\tsignal: options.signal,\n\t\t});\n\t\tresult.downloaded.push(path);\n\t}\n\treturn result;\n}\n\n/** Each recorded asset's state here: present and matching, missing, or changed. */\nexport async function assetStatus(\n\tcwd: string,\n): Promise<{ path: string; size: number; state: AssetState }[]> {\n\tconst { config } = readConfig(cwd);\n\treturn Promise.all(\n\t\tObject.entries(config.assets ?? {}).map(async ([path, entry]) => ({\n\t\t\tpath,\n\t\t\tsize: entry.size,\n\t\t\tstate: await localState(cwd, path, entry),\n\t\t})),\n\t);\n}\n\n/**\n * Before a cloud render: uploads assets the bucket lacks (when there are\n * keys), checks public ones are reachable, and signs reads of private ones.\n * Returns the signed URLs by sha256, for the render request.\n */\nexport async function prepareCloudAssets(\n\toptions: AssetOptions & { expiresSec?: number },\n): Promise<Record<string, string>> {\n\tconst { config } = readConfig(options.cwd);\n\tconst signed: Record<string, string> = {};\n\tconst missing: string[] = [];\n\tfor (const [path, entry] of storedAssets(config.assets)) {\n\t\tconst { name, remote } = pickRemote(config.storage, entry.remote);\n\t\tconst keys = credentialsFromEnv(name, options.env);\n\t\tif (!keys) {\n\t\t\tif (!remote.publicUrl) throw noCredentials(name, path);\n\t\t\tconst url = readUrl(entry, config.storage) as string;\n\t\t\tif (!(await reachable(url, options.fetch))) missing.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tconst bucket = new Bucket(remote, keys, { fetch: options.fetch });\n\t\tif (!(await bucket.has(entry.sha256, entry.size))) {\n\t\t\tif ((await localState(options.cwd, path, entry)) !== \"ok\") {\n\t\t\t\tmissing.push(path);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait upload(bucket, options.cwd, path, entry, options.log);\n\t\t}\n\t\tif (!remote.publicUrl)\n\t\t\tsigned[entry.sha256] = await bucket.presign(\n\t\t\t\tentry.sha256,\n\t\t\t\toptions.expiresSec ?? 86_400,\n\t\t\t);\n\t}\n\tif (missing.length)\n\t\tthrow new AssetsError(\n\t\t\t`Not on the bucket: ${missing.join(\", \")}. Run \\`framefields assets push\\` from a machine that has them (and the remote's keys).`,\n\t\t\t\"not_uploaded\",\n\t\t);\n\treturn signed;\n}\n\n/** Assets kept on a remote (not pinned to a fixed `url`). */\nfunction storedAssets(\n\tassets: AssetManifest | undefined,\n): [string, AssetEntry][] {\n\treturn Object.entries(assets ?? {}).filter(([, entry]) => !entry.url);\n}\n\nasync function localState(\n\tcwd: string,\n\tpath: string,\n\tentry: AssetEntry,\n): Promise<AssetState> {\n\tconst file = join(cwd, path);\n\tif (!existsSync(file)) return \"missing\";\n\tif (statSync(file).size !== entry.size) return \"changed\";\n\treturn (await hashFile(file)).sha256 === entry.sha256 ? \"ok\" : \"changed\";\n}\n\nasync function readableUrl(\n\tentry: AssetEntry,\n\tstorage: StorageConfig | undefined,\n\toptions: AssetOptions,\n): Promise<string> {\n\tconst url = readUrl(entry, storage);\n\tif (url) return url;\n\treturn openBucket(storage, entry.remote, options).presign(entry.sha256, 3600);\n}\n\nfunction openBucket(\n\tstorage: StorageConfig | undefined,\n\tremoteName: string | undefined,\n\toptions: AssetOptions,\n): Bucket {\n\tconst { name, remote } = pickRemote(storage, remoteName);\n\tconst keys = credentialsFromEnv(name, options.env);\n\tif (!keys) throw noCredentials(name);\n\treturn new Bucket(remote, keys, { fetch: options.fetch });\n}\n\nfunction noCredentials(remote: string, path?: string): AssetsError {\n\tconst [id, secret] = credentialEnvNames(remote);\n\treturn new AssetsError(\n\t\t`${path ? `${path} is on ${remote}, which` : `Remote ${remote}`} needs keys: set ${id} and ${secret} (or AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)${path ? \", or give it a publicUrl\" : \"\"}.`,\n\t\t\"no_credentials\",\n\t);\n}\n\nasync function upload(\n\tbucket: Bucket,\n\tcwd: string,\n\tpath: string,\n\tdigest: { sha256: string; size: number },\n\tlog?: (line: string) => void,\n): Promise<void> {\n\tlog?.(`Uploading ${path} (${megabytes(digest.size)})`);\n\tlet shown = 0;\n\tawait bucket.upload(join(cwd, path), digest, ({ sent, total }) => {\n\t\tconst percent = Math.floor((sent / total) * 10) * 10;\n\t\tif (total > 64e6 && percent > shown && percent < 100) {\n\t\t\tshown = percent;\n\t\t\tlog?.(` ${percent}%`);\n\t\t}\n\t});\n}\n\nasync function reachable(url: string, fetchImpl = fetch): Promise<boolean> {\n\tconst res = await fetchImpl(url, { method: \"HEAD\" }).catch(() => undefined);\n\treturn res?.ok ?? false;\n}\n\n/** Project-relative POSIX paths of `path`, or of every file under it. */\nfunction expand(cwd: string, path: string): string[] {\n\tconst abs = resolve(cwd, path);\n\tconst rel = relative(cwd, abs).split(sep).join(\"/\");\n\tif (!isAssetPath(rel) || rel.startsWith(\"../\"))\n\t\tthrow new AssetsError(`${path} is outside the project.`, \"outside_project\");\n\tif (!existsSync(abs))\n\t\tthrow new AssetsError(`${path} does not exist.`, \"not_found\");\n\tif (!statSync(abs).isDirectory()) return [rel];\n\treturn readdirSync(abs, { withFileTypes: true })\n\t\t.filter((d) => !d.name.startsWith(\".\"))\n\t\t.flatMap((d) => expand(cwd, `${rel}/${d.name}`))\n\t\t.sort();\n}\n\nconst IGNORE_HEADER =\n\t\"# framefields assets: on the bucket, pinned in framefields.json\";\n\n/** Adds the files to .gitignore, under one marked block. */\nfunction ignore(cwd: string, files: string[]): void {\n\tconst file = join(cwd, \".gitignore\");\n\tconst text = existsSync(file) ? readFileSync(file, \"utf8\") : \"\";\n\tconst lines = new Set(text.split(\"\\n\"));\n\tconst fresh = files.map((f) => `/${f}`).filter((l) => !lines.has(l));\n\tif (fresh.length === 0) return;\n\tconst header = lines.has(IGNORE_HEADER) ? [] : [IGNORE_HEADER];\n\tconst lead = text && !text.endsWith(\"\\n\") ? \"\\n\" : \"\";\n\tappendFileSync(file, `${lead}${[...header, ...fresh].join(\"\\n\")}\\n`);\n}\n\nfunction trackedByGit(cwd: string, files: string[]): string[] {\n\ttry {\n\t\treturn execFileSync(\"git\", [\"ls-files\", \"--\", ...files], {\n\t\t\tcwd,\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t})\n\t\t\t.split(\"\\n\")\n\t\t\t.filter(Boolean);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction sortKeys(assets: AssetManifest): AssetManifest {\n\treturn Object.fromEntries(\n\t\tObject.entries(assets).sort(([a], [b]) => a.localeCompare(b)),\n\t);\n}\n\nexport function megabytes(bytes: number): string {\n\treturn `${(bytes / 1e6).toFixed(bytes < 1e7 ? 1 : 0)} MB`;\n}\n\nconst ASSETS_USAGE = `Usage: framefields assets add <path...> [--remote <name>]\n framefields assets push | pull [--overwrite] | status [--json]\n`;\n\n/** The `framefields assets` command. */\nexport async function runAssets(\n\t[sub, ...paths]: string[],\n\toptions: AssetOptions & {\n\t\tremote?: string;\n\t\toverwrite?: boolean;\n\t\tjson?: boolean;\n\t},\n): Promise<number> {\n\tconst log = options.log ?? (() => {});\n\tif (sub === \"add\" && paths.length > 0) {\n\t\tconst added = await addAssets(paths, options);\n\t\tconst sent = added.filter((a) => a.uploaded).length;\n\t\tlog(\n\t\t\t`Recorded ${added.length} asset${added.length === 1 ? \"\" : \"s\"} in ${CONFIG_FILE} (${sent} uploaded, ${added.length - sent} already on the bucket). Commit ${CONFIG_FILE} and .gitignore.`,\n\t\t);\n\t\treturn 0;\n\t}\n\tif (sub === \"push\") {\n\t\tconst { uploaded, present } = await pushAssets(options);\n\t\tlog(\n\t\t\t`Uploaded ${uploaded.length}; ${present.length} already on the bucket.`,\n\t\t);\n\t\treturn 0;\n\t}\n\tif (sub === \"pull\") {\n\t\tconst { downloaded, present, changed } = await pullAssets(options);\n\t\tlog(`Downloaded ${downloaded.length}; ${present.length} already here.`);\n\t\tif (changed.length)\n\t\t\tlog(\n\t\t\t\t`Changed here, left alone: ${changed.join(\", \")}. \\`framefields assets add\\` records them, --overwrite restores them.`,\n\t\t\t);\n\t\treturn changed.length ? 1 : 0;\n\t}\n\tif (sub === \"status\") {\n\t\tconst entries = await assetStatus(options.cwd);\n\t\tif (options.json) log(JSON.stringify({ assets: entries }));\n\t\telse if (entries.length === 0) log(`No assets in ${CONFIG_FILE}.`);\n\t\telse\n\t\t\tfor (const e of entries)\n\t\t\t\tlog(`${e.state.padEnd(8)} ${e.path} (${megabytes(e.size)})`);\n\t\treturn entries.some((e) => e.state !== \"ok\") ? 1 : 0;\n\t}\n\tprocess.stderr.write(ASSETS_USAGE);\n\treturn 2;\n}\n","/**\n * Where a cloud render gets the project from: the git repo the working\n * directory is in, at the commit checked out now. Cloud workers fetch from\n * the remote, so that commit has to be pushed; uncommitted changes are not\n * rendered.\n */\nimport { execFileSync } from \"node:child_process\";\nimport { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface CloudSource {\n\trepo: string;\n\tref?: string;\n\tcommit?: string;\n\t/** The project's folder inside the repo (monorepos), `.` at the root. */\n\tworkdir?: string;\n}\n\nexport interface ResolvedSource {\n\tsource: CloudSource;\n\t/** The entry relative to `source.workdir`, as the worker loads it. */\n\tentry: string;\n\t/** Things that render differently than the user may expect (uncommitted changes). */\n\twarnings: string[];\n}\n\n/** Reads repo, branch, commit and folder from git, and checks the commit is pushed. */\nexport function resolveGitSource(cwd: string, entry: string): ResolvedSource {\n\tconst git = (...args: string[]) =>\n\t\texecFileSync(\"git\", args, {\n\t\t\tcwd,\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t}).trim();\n\tlet root: string;\n\ttry {\n\t\troot = git(\"rev-parse\", \"--show-toplevel\");\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`${cwd} is not in a git repository. Cloud renders fetch the project from git: commit it and push it to a remote first.`,\n\t\t);\n\t}\n\t// git reports the root with symlinks resolved (macOS /var → /private/var).\n\tconst workdir =\n\t\tpath\n\t\t\t.relative(realpathSync(root), realpathSync(cwd))\n\t\t\t.split(path.sep)\n\t\t\t.join(\"/\") || \".\";\n\tconst relEntry = path\n\t\t.relative(cwd, path.resolve(cwd, entry))\n\t\t.split(path.sep)\n\t\t.join(\"/\");\n\tif (relEntry.startsWith(\"../\") || path.isAbsolute(relEntry))\n\t\tthrow new Error(\n\t\t\t`${entry} is outside ${cwd}; run from the project folder that contains it.`,\n\t\t);\n\n\tconst branch = git(\"rev-parse\", \"--abbrev-ref\", \"HEAD\");\n\tconst commit = git(\"rev-parse\", \"HEAD\");\n\tconst remoteName = upstreamRemote(git, branch) ?? \"origin\";\n\tlet remoteUrl: string;\n\ttry {\n\t\tremoteUrl = git(\"remote\", \"get-url\", remoteName);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`The repository has no \"${remoteName}\" remote. Push the project to a git host first.`,\n\t\t);\n\t}\n\tconst pushed = git(\"branch\", \"-r\", \"--contains\", commit);\n\tif (!pushed)\n\t\tthrow new Error(\n\t\t\t`Commit ${commit.slice(0, 7)} is not on ${remoteName}. Push it first (\\`git push\\`): cloud workers fetch the project from the remote.`,\n\t\t);\n\tconst dirty = git(\"status\", \"--porcelain\", \"--untracked-files=no\", \"--\", \".\");\n\treturn {\n\t\tsource: {\n\t\t\trepo: toHttps(remoteUrl),\n\t\t\t...(branch !== \"HEAD\" && { ref: branch }),\n\t\t\tcommit,\n\t\t\tworkdir,\n\t\t},\n\t\tentry: relEntry,\n\t\twarnings: dirty\n\t\t\t? [\n\t\t\t\t\t`Uncommitted changes are not rendered: the cloud renders commit ${commit.slice(0, 7)}.`,\n\t\t\t\t]\n\t\t\t: [],\n\t};\n}\n\nfunction upstreamRemote(\n\tgit: (...args: string[]) => string,\n\tbranch: string,\n): string | undefined {\n\tif (branch === \"HEAD\") return undefined;\n\ttry {\n\t\treturn git(\"config\", `branch.${branch}.remote`) || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** `git@github.com:acme/films.git` → `https://github.com/acme/films.git`; credentials dropped. */\nexport function toHttps(url: string): string {\n\tconst scp = /^[\\w.-]+@([^:/]+):(.+)$/.exec(url);\n\tif (scp) return `https://${scp[1]}/${scp[2]}`;\n\tconst parsed = URL.canParse(url) ? new URL(url) : undefined;\n\tif (parsed && (parsed.protocol === \"ssh:\" || parsed.protocol === \"git:\"))\n\t\treturn `https://${parsed.hostname}${parsed.pathname}`;\n\tif (parsed?.protocol === \"https:\" || parsed?.protocol === \"http:\") {\n\t\tparsed.username = \"\";\n\t\tparsed.password = \"\";\n\t\treturn parsed.toString();\n\t}\n\treturn url;\n}\n","/**\n * Cloud renders on api.framefields.dev: the project renders from git on\n * framefields' GPU workers, billed to the account that owns the API key.\n *\n * ```ts\n * import { renderCloud } from \"framefields/cloud\";\n *\n * const result = await renderCloud({\n * render: \"film\", // a render named in framefields.json\n * outputPath: \"output/film.mp4\",\n * onProgress: (s) => console.log(s.status, s.progress.frames),\n * });\n * ```\n *\n * Without a framefields.json, name the module instead: `entry: \"src/film.ts\"`\n * (and `export`, `workers`, …). Options passed here override the named\n * render's.\n *\n * `workers: \"auto\"` probes the film on one worker first, then splits it into\n * as many chunks as stay efficient: short films stay on one worker, long ones\n * spread out up to `maxWorkers`. `dryRun: true` returns that plan with the\n * estimated cost and renders nothing. Aborting `signal` cancels the render;\n * GPU time already used is charged.\n */\nimport { createWriteStream } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { ReadableStream as WebReadableStream } from \"node:stream/web\";\nimport { AssetsError, prepareCloudAssets } from \"../cli/assets.js\";\nimport { CONFIG_FILE, findRender, readConfig } from \"../cli/config.js\";\nimport { type CloudSource, resolveGitSource } from \"./git-source.js\";\n\nexport { type CloudSource, resolveGitSource, toHttps } from \"./git-source.js\";\n\nexport const FRAMEFIELDS_API_URL = \"https://api.framefields.dev\";\n\nexport interface CloudRenderOptions {\n\t/** A render named in `cwd`'s framefields.json; its fields are the defaults here. */\n\trender?: string;\n\t/** The module that builds the composition, relative to `cwd`. Required without `render`. */\n\tentry?: string;\n\t/** Its export: a Composition, or a function returning one. Default `buildFilm`. */\n\texport?: string;\n\t/** Passed to the export when it is a function. */\n\targs?: unknown;\n\t/** When the export returns several compositions, the one to render. */\n\tselect?: string;\n\t/** 1 (default) renders on one worker; a number or \"auto\" splits the film. */\n\tworkers?: number | \"auto\";\n\t/** Upper bound for \"auto\" (the API caps it too). */\n\tmaxWorkers?: number;\n\tcodec?: \"h264\" | \"vp9\";\n\tquality?: string;\n\t/** Probe and plan only: returns the plan and estimated cost, renders nothing. */\n\tdryRun?: boolean;\n\t/** Download the finished video here. */\n\toutputPath?: string;\n\t/** Project folder. Default `process.cwd()`. */\n\tcwd?: string;\n\t/** Instead of reading repo, branch and commit from git. */\n\tsource?: CloudSource;\n\t/** Default `process.env.FRAMEFIELDS_API_KEY`. */\n\tapiKey?: string;\n\t/** Default `process.env.FRAMEFIELDS_API_URL`, else https://api.framefields.dev. */\n\tapiUrl?: string;\n\t/** Called with every status poll. */\n\tonProgress?: (status: CloudRenderStatus) => void;\n\t/** Called for each warning (uncommitted changes). Default: stderr. */\n\tonWarning?: (message: string) => void;\n\t/** Called as assets upload before the render. Default: stderr. */\n\tonLog?: (message: string) => void;\n\t/** Aborting cancels the cloud render. */\n\tsignal?: AbortSignal;\n\t/** Status poll interval, ms. Default 3000. */\n\tpollMs?: number;\n}\n\nexport type CloudRenderPhase =\n\t| \"probing\"\n\t| \"holding\"\n\t| \"rendering\"\n\t| \"stitching\"\n\t| \"planned\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"cancelled\";\n\nexport interface CloudRenderPlan {\n\tworkers: number;\n\t/** Render time of the whole film on one GPU, seconds. */\n\tworkSec: number;\n\t/** Expected wall time with this plan, seconds. */\n\tetaSec: number;\n\tchunks: { start: number; end: number; workSec: number }[];\n}\n\nexport interface CloudRenderStatus {\n\tid: string;\n\tstatus: CloudRenderPhase;\n\tworkers: number;\n\tplan?: CloudRenderPlan;\n\tprogress: {\n\t\tframes: number;\n\t\ttotalFrames: number | null;\n\t\tetaSec: number | null;\n\t};\n\t/** Charged so far (final once the render ended), USD. */\n\tcostUsd: number;\n\tgpuSeconds: number;\n\t/** The planned render's estimated charge, USD. */\n\testimateUsd?: number;\n\t/** The commit rendered. */\n\tsha?: string;\n\toutput?: { url: string; bytes?: number };\n\terror?: { code: string; message: string };\n}\n\nexport interface CloudRenderResult extends CloudRenderStatus {\n\t/** Where the video was downloaded (`outputPath`). */\n\tfilePath?: string;\n}\n\n/** A cloud render that failed, was cancelled, or was refused by the API. */\nexport class CloudRenderError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly code: string,\n\t\treadonly status?: CloudRenderStatus,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CloudRenderError\";\n\t}\n}\n\nconst DONE = new Set<CloudRenderPhase>([\n\t\"planned\",\n\t\"completed\",\n\t\"failed\",\n\t\"cancelled\",\n]);\n\n/** Starts a cloud render and waits for it; resolves when it completed (or was planned). */\nexport async function renderCloud(\n\toptions: CloudRenderOptions,\n): Promise<CloudRenderResult> {\n\tconst api = cloudClient(options);\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst o = withNamedRender(cwd, options);\n\tconst resolved = options.source\n\t\t? { source: options.source, entry: o.entry, warnings: [] }\n\t\t: resolveGitSource(cwd, o.entry);\n\tconst warn =\n\t\toptions.onWarning ??\n\t\t((m: string) => process.stderr.write(`framefields: ${m}\\n`));\n\tfor (const w of resolved.warnings) warn(w);\n\tconst assets = await cloudAssets(cwd, options);\n\n\tlet status = await api.start({\n\t\tsource: Object.keys(assets).length\n\t\t\t? { ...resolved.source, assets }\n\t\t\t: resolved.source,\n\t\ttarget: {\n\t\t\tentry: resolved.entry,\n\t\t\texport: o.export ?? \"buildFilm\",\n\t\t\t...(o.args !== undefined && { args: o.args }),\n\t\t\t...(o.select && { select: [o.select] }),\n\t\t},\n\t\trender: {\n\t\t\tcodec: o.codec ?? \"h264\",\n\t\t\t...(o.quality && { quality: o.quality }),\n\t\t},\n\t\tworkers: o.workers ?? 1,\n\t\t...(o.maxWorkers && { max_workers: o.maxWorkers }),\n\t\tdry_run: options.dryRun ?? false,\n\t\t...(o.name && { name: o.name }),\n\t\t...(o.title && { title: o.title }),\n\t});\n\toptions.onProgress?.(status);\n\n\ttry {\n\t\twhile (!DONE.has(status.status)) {\n\t\t\tawait sleep(options.pollMs ?? 3000, options.signal);\n\t\t\tstatus = await api.status(status.id);\n\t\t\toptions.onProgress?.(status);\n\t\t}\n\t} catch (err) {\n\t\tif (options.signal?.aborted) {\n\t\t\tconst final = await api.cancel(status.id).catch(() => status);\n\t\t\tthrow new CloudRenderError(\n\t\t\t\t\"The cloud render was cancelled.\",\n\t\t\t\t\"cancelled\",\n\t\t\t\tfinal,\n\t\t\t);\n\t\t}\n\t\tthrow err;\n\t}\n\n\tif (status.status === \"failed\" || status.status === \"cancelled\")\n\t\tthrow new CloudRenderError(\n\t\t\tstatus.error\n\t\t\t\t? `Cloud render ${status.status}: ${status.error.message} (${status.error.code})`\n\t\t\t\t: `Cloud render ${status.status}.`,\n\t\t\tstatus.error?.code ?? status.status,\n\t\t\tstatus,\n\t\t);\n\tif (status.status === \"completed\" && options.outputPath && status.output) {\n\t\tawait download(status.output.url, options.outputPath, options.signal);\n\t\treturn { ...status, filePath: options.outputPath };\n\t}\n\treturn status;\n}\n\n/**\n * Uploads assets the bucket lacks and signs reads of private ones: the\n * workers download each asset framefields.json pins at the commit.\n */\nasync function cloudAssets(\n\tcwd: string,\n\toptions: CloudRenderOptions,\n): Promise<Record<string, string>> {\n\ttry {\n\t\treturn await prepareCloudAssets({\n\t\t\tcwd,\n\t\t\tsignal: options.signal,\n\t\t\tlog:\n\t\t\t\toptions.onLog ??\n\t\t\t\t((m: string) => process.stderr.write(`framefields: ${m}\\n`)),\n\t\t});\n\t} catch (err) {\n\t\tif (err instanceof AssetsError)\n\t\t\tthrow new CloudRenderError(err.message, `assets_${err.code}`);\n\t\tthrow err;\n\t}\n}\n\n/**\n * The options with a named render's fields filled in where the caller left\n * them out, plus the name and title the dashboard shows.\n */\nexport function withNamedRender(\n\tcwd: string,\n\toptions: CloudRenderOptions,\n): CloudRenderOptions & { entry: string; name?: string; title?: string } {\n\tif (!options.render) {\n\t\tif (!options.entry)\n\t\t\tthrow new CloudRenderError(\n\t\t\t\t\"Name a render from framefields.json (render) or a module (entry).\",\n\t\t\t\t\"invalid_request\",\n\t\t\t);\n\t\treturn { ...options, entry: options.entry };\n\t}\n\tconst spec = findRender(cwd, options.render);\n\tif (!spec) {\n\t\tconst names = Object.keys(readConfig(cwd).config.renders ?? {});\n\t\tthrow new CloudRenderError(\n\t\t\tnames.length\n\t\t\t\t? `No render named \"${options.render}\" in ${CONFIG_FILE}. Renders: ${names.join(\", \")}.`\n\t\t\t\t: `No render named \"${options.render}\": ${CONFIG_FILE} has no \"renders\".`,\n\t\t\t\"render_not_found\",\n\t\t);\n\t}\n\tconst defined = Object.fromEntries(\n\t\tObject.entries(options).filter(([, v]) => v !== undefined),\n\t) as CloudRenderOptions;\n\treturn {\n\t\tentry: spec.entry,\n\t\texport: spec.export,\n\t\targs: spec.args,\n\t\tselect: spec.select,\n\t\tworkers: spec.workers,\n\t\tmaxWorkers: spec.maxWorkers,\n\t\tcodec: spec.codec,\n\t\tquality: spec.quality,\n\t\t...defined,\n\t\tname: spec.name,\n\t\ttitle: spec.title ?? spec.name,\n\t} as CloudRenderOptions & { entry: string; name: string; title: string };\n}\n\n/** The API calls behind `renderCloud`, for callers who track renders themselves. */\nexport function cloudClient(\n\toptions: Pick<CloudRenderOptions, \"apiKey\" | \"apiUrl\">,\n) {\n\tconst key = options.apiKey ?? process.env.FRAMEFIELDS_API_KEY;\n\tif (!key)\n\t\tthrow new CloudRenderError(\n\t\t\t\"No API key. Set FRAMEFIELDS_API_KEY (keys at https://framefields.dev/dashboard/keys) or pass apiKey.\",\n\t\t\t\"invalid_api_key\",\n\t\t);\n\tconst base = (\n\t\toptions.apiUrl ??\n\t\tprocess.env.FRAMEFIELDS_API_URL ??\n\t\tFRAMEFIELDS_API_URL\n\t).replace(/\\/+$/, \"\");\n\tconst call = async (method: string, route: string, body?: unknown) => {\n\t\tconst res = await fetch(`${base}/v1/render${route}`, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${key}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\t...(body !== undefined && { body: JSON.stringify(body) }),\n\t\t});\n\t\tconst json = (await res.json().catch(() => ({}))) as ApiStatus & {\n\t\t\terror?: { type?: string; message?: string };\n\t\t};\n\t\tif (!res.ok)\n\t\t\tthrow new CloudRenderError(\n\t\t\t\tjson.error?.message ??\n\t\t\t\t\t`api.framefields.dev answered HTTP ${res.status}`,\n\t\t\t\tjson.error?.type ?? `http_${res.status}`,\n\t\t\t);\n\t\treturn fromApi(json);\n\t};\n\treturn {\n\t\tstart: (body: unknown) => call(\"POST\", \"\", body),\n\t\tstatus: (id: string) => call(\"GET\", `/${encodeURIComponent(id)}`),\n\t\tcancel: (id: string) => call(\"DELETE\", `/${encodeURIComponent(id)}`),\n\t};\n}\n\n/** The API's snake_case status. */\ninterface ApiStatus {\n\tid: string;\n\tstatus: CloudRenderPhase;\n\tworkers?: number;\n\tplan?: {\n\t\tworkers: number;\n\t\twork_sec: number;\n\t\teta_sec: number;\n\t\tchunks: CloudRenderPlan[\"chunks\"];\n\t};\n\tprogress?: {\n\t\tframes?: number;\n\t\ttotal_frames?: number | null;\n\t\teta_sec?: number | null;\n\t};\n\tcost_usd?: number;\n\tgpu_seconds?: number;\n\testimate_usd?: number;\n\tsha?: string;\n\toutput?: { url: string; bytes?: number };\n\terror?: { code: string; message: string };\n}\n\nfunction fromApi(s: ApiStatus): CloudRenderStatus {\n\treturn {\n\t\tid: s.id,\n\t\tstatus: s.status,\n\t\tworkers: s.workers ?? 1,\n\t\t...(s.plan && {\n\t\t\tplan: {\n\t\t\t\tworkers: s.plan.workers,\n\t\t\t\tworkSec: s.plan.work_sec,\n\t\t\t\tetaSec: s.plan.eta_sec,\n\t\t\t\tchunks: s.plan.chunks,\n\t\t\t},\n\t\t}),\n\t\tprogress: {\n\t\t\tframes: s.progress?.frames ?? 0,\n\t\t\ttotalFrames: s.progress?.total_frames ?? null,\n\t\t\tetaSec: s.progress?.eta_sec ?? null,\n\t\t},\n\t\tcostUsd: s.cost_usd ?? 0,\n\t\tgpuSeconds: s.gpu_seconds ?? 0,\n\t\t...(s.estimate_usd !== undefined && { estimateUsd: s.estimate_usd }),\n\t\t...(s.sha && { sha: s.sha }),\n\t\t...(s.output && { output: s.output }),\n\t\t...(s.error && { error: s.error }),\n\t};\n}\n\nasync function download(url: string, file: string, signal?: AbortSignal) {\n\tconst res = await fetch(url, { signal });\n\tif (!res.ok || !res.body)\n\t\tthrow new CloudRenderError(\n\t\t\t`Downloading the render failed: HTTP ${res.status}`,\n\t\t\t\"download_failed\",\n\t\t);\n\tawait fs.mkdir(path.dirname(path.resolve(file)), { recursive: true });\n\tawait pipeline(\n\t\tReadable.fromWeb(res.body as WebReadableStream),\n\t\tcreateWriteStream(file),\n\t);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) return reject(signal.reason);\n\t\tconst timer = setTimeout(resolve, ms);\n\t\tsignal?.addEventListener(\n\t\t\t\"abort\",\n\t\t\t() => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(signal.reason);\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cloud-jnk1hPYf.mjs","names":["path","fs","resolve"],"sources":["../src/cli/config.ts","../src/cli/assets.ts","../src/cloud/git-source.ts","../src/cloud/index.ts"],"sourcesContent":["/**\n * `framefields.json` at the project root: where installed components live,\n * which fonts `framefields add` / `framefields fonts add` installed, and the\n * project's named renders.\n *\n * ```json\n * {\n * \"components\": \"src/components\",\n * \"renders\": {\n * \"film\": {\n * \"title\": \"Launch film\",\n * \"entry\": \"src/film.ts\",\n * \"export\": \"buildFilm\",\n * \"workers\": \"auto\"\n * }\n * }\n * }\n * ```\n *\n * A named render is what `framefields render film --cloud`, `framefields\n * check film`, `renderCloud({ render: \"film\" })` and the dashboard's New\n * render dialog pick, so nobody chooses files and exports by hand.\n *\n * `storage` and `assets` pin media by content on an S3-compatible bucket\n * (`framefields assets`; the format lives in `@framefields/storage`).\n */\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n\ttype AssetManifest,\n\tparseAssets,\n\tparseStorage,\n\ttype StorageConfig,\n} from \"@framefields/storage\";\n\nexport const CONFIG_FILE = \"framefields.json\";\n\n/** One renderable piece of the project: an export of a module, with its defaults. */\nexport interface RenderSpec {\n\t/** The module that builds the composition, relative to the project root. */\n\tentry: string;\n\t/** A Composition, or a function returning one. Default `buildFilm`. */\n\texport?: string;\n\t/** Shown in the dashboard and `framefields renders`. Default: the name. */\n\ttitle?: string;\n\tdescription?: string;\n\t/** Passed to the export when it is a function. */\n\targs?: unknown;\n\t/** When the export returns several compositions, the one to render. */\n\tselect?: string;\n\t/** Cloud workers: 1, a number, or \"auto\" to split long films. Default 1. */\n\tworkers?: number | \"auto\";\n\tmaxWorkers?: number;\n\tcodec?: \"h264\" | \"vp9\";\n\tquality?: \"very_low\" | \"low\" | \"high\" | \"very_high\";\n\t/** Where `framefields render <name> --cloud` writes the video. */\n\toutput?: string;\n}\n\nexport interface ProjectConfig {\n\t/** Components directory, relative to the project root. */\n\tcomponents: string;\n\t/**\n\t * Font files by role (`emoji`), relative to the project root. A role\n\t * set here counts as installed: point it at your own font to use that.\n\t */\n\tfonts?: Partial<Record<string, string>>;\n\t/** Named renders, by name (letters, digits, `-`, `_`, `.`). */\n\trenders?: Record<string, RenderSpec>;\n\t/** Buckets holding the project's assets. */\n\tstorage?: StorageConfig;\n\t/** Files the project needs, by path, pinned by sha256 and size. */\n\tassets?: AssetManifest;\n}\n\nexport const RENDER_NAME = /^[A-Za-z0-9][\\w.-]{0,63}$/;\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\nconst QUALITIES = [\"very_low\", \"low\", \"high\", \"very_high\"];\n\n/**\n * The project's config, or the default it would get: `src/components` when\n * there is a `src`. `saved` is whether the file records a components folder.\n */\nexport function readConfig(cwd: string): {\n\tconfig: ProjectConfig;\n\tsaved: boolean;\n} {\n\tconst file = join(cwd, CONFIG_FILE);\n\tconst fallback = existsSync(join(cwd, \"src\"))\n\t\t? \"src/components\"\n\t\t: \"components\";\n\tif (!existsSync(file))\n\t\treturn { config: { components: fallback }, saved: false };\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(readFileSync(file, \"utf8\"));\n\t} catch (err) {\n\t\tthrow new Error(\n\t\t\t`${CONFIG_FILE} is not valid JSON: ${(err as Error).message}`,\n\t\t);\n\t}\n\tif (!isRecord(raw)) throw new Error(`${CONFIG_FILE} must be a JSON object`);\n\tconst { components, fonts, renders, storage, assets } = raw;\n\tif (components !== undefined && typeof components !== \"string\")\n\t\tthrow new Error(`${CONFIG_FILE}: \"components\" must be a directory path`);\n\tif (\n\t\tfonts !== undefined &&\n\t\t(!isRecord(fonts) ||\n\t\t\tObject.values(fonts).some((v) => typeof v !== \"string\"))\n\t)\n\t\tthrow new Error(\n\t\t\t`${CONFIG_FILE}: \"fonts\" must map roles to font file paths, e.g. { \"emoji\": \"assets/fonts/NotoColorEmoji.ttf\" }`,\n\t\t);\n\tconst parsedStorage =\n\t\tstorage === undefined ? undefined : parseStorage(storage);\n\t// Other keys (a `$schema`, say) survive a rewrite.\n\tconst config = {\n\t\t...raw,\n\t\tcomponents: components ?? fallback,\n\t\t...(renders !== undefined && { renders: parseRenders(renders) }),\n\t\t...(parsedStorage && { storage: parsedStorage }),\n\t\t...(assets !== undefined && {\n\t\t\tassets: parseAssets(assets, parsedStorage),\n\t\t}),\n\t} as ProjectConfig;\n\treturn { config, saved: components !== undefined };\n}\n\nexport function writeConfig(cwd: string, config: ProjectConfig): void {\n\twriteFileSync(\n\t\tjoin(cwd, CONFIG_FILE),\n\t\t`${JSON.stringify(config, null, \"\\t\")}\\n`,\n\t);\n}\n\n/** Validates the `renders` map; errors name the render and field at fault. */\nexport function parseRenders(value: unknown): Record<string, RenderSpec> {\n\tif (!isRecord(value))\n\t\tthrow new Error(\n\t\t\t`${CONFIG_FILE}: \"renders\" must map names to renders, e.g. { \"film\": { \"entry\": \"src/film.ts\" } }`,\n\t\t);\n\tconst out: Record<string, RenderSpec> = {};\n\tfor (const [name, spec] of Object.entries(value)) {\n\t\tconst fail = (message: string) => {\n\t\t\tthrow new Error(`${CONFIG_FILE}: renders.${name} ${message}`);\n\t\t};\n\t\tif (!RENDER_NAME.test(name))\n\t\t\tfail(\"has an invalid name: use letters, digits, -, _ and . (at most 64)\");\n\t\tif (!isRecord(spec)) fail(\"must be an object with an entry\");\n\t\tconst s = spec as Record<string, unknown>;\n\t\tif (!isRelativePath(s.entry))\n\t\t\tfail(\n\t\t\t\t'needs \"entry\": the module path inside the project, e.g. \"src/film.ts\"',\n\t\t\t);\n\t\tif (\n\t\t\ts.export !== undefined &&\n\t\t\t!(typeof s.export === \"string\" && IDENTIFIER.test(s.export))\n\t\t)\n\t\t\tfail('\"export\" must be a JavaScript identifier');\n\t\tfor (const key of [\"title\", \"description\", \"select\"] as const)\n\t\t\tif (s[key] !== undefined && typeof s[key] !== \"string\")\n\t\t\t\tfail(`\"${key}\" must be a string`);\n\t\tif (s.workers !== undefined && s.workers !== \"auto\" && !isCount(s.workers))\n\t\t\tfail('\"workers\" must be \"auto\" or a positive whole number');\n\t\tif (s.maxWorkers !== undefined && !isCount(s.maxWorkers))\n\t\t\tfail('\"maxWorkers\" must be a positive whole number');\n\t\tif (s.codec !== undefined && s.codec !== \"h264\" && s.codec !== \"vp9\")\n\t\t\tfail('\"codec\" must be \"h264\" or \"vp9\"');\n\t\tif (s.quality !== undefined && !QUALITIES.includes(s.quality as string))\n\t\t\tfail(`\"quality\" must be one of ${QUALITIES.join(\", \")}`);\n\t\tif (s.output !== undefined && typeof s.output !== \"string\")\n\t\t\tfail('\"output\" must be a file path');\n\t\tout[name] = s as unknown as RenderSpec;\n\t}\n\treturn out;\n}\n\n/**\n * The named render `name` of the project at `cwd`, or undefined when there\n * is no render by that name (an entry path, say).\n */\nexport function findRender(\n\tcwd: string,\n\tname: string,\n): (RenderSpec & { name: string }) | undefined {\n\tconst spec = readConfig(cwd).config.renders?.[name];\n\treturn spec && { ...spec, name };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isCount(value: unknown): boolean {\n\treturn typeof value === \"number\" && Number.isInteger(value) && value >= 1;\n}\n\nfunction isRelativePath(value: unknown): boolean {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\t!value.startsWith(\"/\") &&\n\t\t!value.split(/[/\\\\]/).includes(\"..\")\n\t);\n}\n","/**\n * `framefields assets`: media kept out of git, on an S3-compatible bucket\n * (R2, S3, B2, MinIO), pinned by content in `framefields.json`.\n *\n * add <path...> hash, upload what the bucket lacks, record, gitignore\n * push upload recorded assets the bucket lacks\n * pull download missing assets, verified byte for byte\n * status which assets are here, missing, or changed\n *\n * Reads need no keys when the remote has a `publicUrl` (a custom domain or\n * CDN in front of the bucket); otherwise they're signed with the remote's\n * keys. Cloud renders get signed URLs for private assets from the CLI, so\n * the keys never leave the machine.\n */\nimport { execFileSync } from \"node:child_process\";\nimport {\n\tappendFileSync,\n\texistsSync,\n\treaddirSync,\n\treadFileSync,\n\tstatSync,\n} from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport {\n\ttype AssetEntry,\n\ttype AssetManifest,\n\tBucket,\n\tcredentialEnvNames,\n\tcredentialsFromEnv,\n\tdownloadVerified,\n\thashFile,\n\tisAssetPath,\n\tpickRemote,\n\treadUrl,\n\ttype StorageConfig,\n} from \"@framefields/storage\";\nimport { CONFIG_FILE, readConfig, writeConfig } from \"./config.js\";\n\nexport interface AssetOptions {\n\t/** Project folder (where framefields.json is). */\n\tcwd: string;\n\t/** Where remote keys come from. Default `process.env`. */\n\tenv?: Readonly<Record<string, string | undefined>>;\n\tfetch?: typeof fetch;\n\tlog?: (line: string) => void;\n\tsignal?: AbortSignal;\n}\n\nexport type AssetsErrorCode =\n\t| \"no_storage\"\n\t| \"no_credentials\"\n\t| \"not_uploaded\"\n\t| \"outside_project\"\n\t| \"not_found\";\n\nexport class AssetsError extends Error {\n\toverride name = \"AssetsError\";\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly code: AssetsErrorCode,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\nexport type AssetState = \"ok\" | \"missing\" | \"changed\";\n\n/** Hashes and uploads files (folders: every file in them), and records them. */\nexport async function addAssets(\n\tpaths: string[],\n\toptions: AssetOptions & { remote?: string },\n): Promise<{ path: string; size: number; uploaded: boolean }[]> {\n\tconst { cwd } = options;\n\tconst { config } = readConfig(cwd);\n\tconst { name, remote } = pickRemote(config.storage, options.remote);\n\tconst bucket = openBucket(config.storage, name, options);\n\tconst files = paths.flatMap((p) => expand(cwd, p));\n\tif (files.length === 0)\n\t\tthrow new AssetsError(`No files in ${paths.join(\", \")}.`, \"not_found\");\n\tconst added: { path: string; size: number; uploaded: boolean }[] = [];\n\tconst assets: AssetManifest = { ...config.assets };\n\tfor (const file of files) {\n\t\tconst digest = await hashFile(join(cwd, file));\n\t\tconst uploaded = !(await bucket.has(digest.sha256, digest.size));\n\t\tif (uploaded) await upload(bucket, cwd, file, digest, options.log);\n\t\tconst isDefault = name === pickRemote(config.storage).name;\n\t\tassets[file] = { ...digest, ...(!isDefault && { remote: name }) };\n\t\tadded.push({ path: file, size: digest.size, uploaded });\n\t}\n\twriteConfig(cwd, { ...config, assets: sortKeys(assets) });\n\tignore(cwd, files);\n\tconst tracked = trackedByGit(cwd, files);\n\tif (tracked.length)\n\t\toptions.log?.(\n\t\t\t`Already committed to git: ${tracked.join(\", \")}. Stop tracking them with \\`git rm --cached ${tracked.join(\" \")}\\` (the files stay here).`,\n\t\t);\n\tif (remote.publicUrl === undefined)\n\t\toptions.log?.(\n\t\t\t`${name} has no publicUrl: cloud renders from the CLI sign reads, dashboard renders can't read it.`,\n\t\t);\n\treturn added;\n}\n\n/** Uploads every recorded asset its bucket lacks, from the local file. */\nexport async function pushAssets(\n\toptions: AssetOptions,\n): Promise<{ uploaded: string[]; present: string[] }> {\n\tconst { config } = readConfig(options.cwd);\n\tconst uploaded: string[] = [];\n\tconst present: string[] = [];\n\tconst problems: string[] = [];\n\tfor (const [path, entry] of storedAssets(config.assets)) {\n\t\tconst bucket = openBucket(config.storage, entry.remote, options);\n\t\tif (await bucket.has(entry.sha256, entry.size)) {\n\t\t\tpresent.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tconst state = await localState(options.cwd, path, entry);\n\t\tif (state !== \"ok\") {\n\t\t\tproblems.push(`${path} (${state} here)`);\n\t\t\tcontinue;\n\t\t}\n\t\tawait upload(bucket, options.cwd, path, entry, options.log);\n\t\tuploaded.push(path);\n\t}\n\tif (problems.length)\n\t\tthrow new AssetsError(\n\t\t\t`Not on the bucket, and the local file doesn't match ${CONFIG_FILE}: ${problems.join(\", \")}. Restore the file, or record the new version with \\`framefields assets add\\`.`,\n\t\t\t\"not_uploaded\",\n\t\t);\n\treturn { uploaded, present };\n}\n\n/**\n * Downloads every asset that's missing here. Files changed locally are\n * left alone (and reported) unless `overwrite`.\n */\nexport async function pullAssets(\n\toptions: AssetOptions & { overwrite?: boolean },\n): Promise<{ downloaded: string[]; present: string[]; changed: string[] }> {\n\tconst { config } = readConfig(options.cwd);\n\tconst result = {\n\t\tdownloaded: [] as string[],\n\t\tpresent: [] as string[],\n\t\tchanged: [] as string[],\n\t};\n\tfor (const [path, entry] of Object.entries(config.assets ?? {})) {\n\t\tconst state = await localState(options.cwd, path, entry);\n\t\tif (state === \"ok\") {\n\t\t\tresult.present.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tif (state === \"changed\" && !options.overwrite) {\n\t\t\tresult.changed.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tconst url = await readableUrl(entry, config.storage, options);\n\t\toptions.log?.(`Downloading ${path} (${megabytes(entry.size)})`);\n\t\tawait downloadVerified(url, join(options.cwd, path), entry, {\n\t\t\tfetch: options.fetch,\n\t\t\tsignal: options.signal,\n\t\t});\n\t\tresult.downloaded.push(path);\n\t}\n\treturn result;\n}\n\n/** Each recorded asset's state here: present and matching, missing, or changed. */\nexport async function assetStatus(\n\tcwd: string,\n): Promise<{ path: string; size: number; state: AssetState }[]> {\n\tconst { config } = readConfig(cwd);\n\treturn Promise.all(\n\t\tObject.entries(config.assets ?? {}).map(async ([path, entry]) => ({\n\t\t\tpath,\n\t\t\tsize: entry.size,\n\t\t\tstate: await localState(cwd, path, entry),\n\t\t})),\n\t);\n}\n\n/**\n * Before a cloud render: uploads assets the bucket lacks (when there are\n * keys), checks public ones are reachable, and signs reads of private ones.\n * Returns the signed URLs by sha256, for the render request.\n */\nexport async function prepareCloudAssets(\n\toptions: AssetOptions & { expiresSec?: number },\n): Promise<Record<string, string>> {\n\tconst { config } = readConfig(options.cwd);\n\tconst signed: Record<string, string> = {};\n\tconst missing: string[] = [];\n\tfor (const [path, entry] of storedAssets(config.assets)) {\n\t\tconst { name, remote } = pickRemote(config.storage, entry.remote);\n\t\tconst keys = credentialsFromEnv(name, options.env);\n\t\tif (!keys) {\n\t\t\tif (!remote.publicUrl) throw noCredentials(name, path);\n\t\t\tconst url = readUrl(entry, config.storage) as string;\n\t\t\tif (!(await reachable(url, options.fetch))) missing.push(path);\n\t\t\tcontinue;\n\t\t}\n\t\tconst bucket = new Bucket(remote, keys, { fetch: options.fetch });\n\t\tif (!(await bucket.has(entry.sha256, entry.size))) {\n\t\t\tif ((await localState(options.cwd, path, entry)) !== \"ok\") {\n\t\t\t\tmissing.push(path);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tawait upload(bucket, options.cwd, path, entry, options.log);\n\t\t}\n\t\tif (!remote.publicUrl)\n\t\t\tsigned[entry.sha256] = await bucket.presign(\n\t\t\t\tentry.sha256,\n\t\t\t\toptions.expiresSec ?? 86_400,\n\t\t\t);\n\t}\n\tif (missing.length)\n\t\tthrow new AssetsError(\n\t\t\t`Not on the bucket: ${missing.join(\", \")}. Run \\`framefields assets push\\` from a machine that has them (and the remote's keys).`,\n\t\t\t\"not_uploaded\",\n\t\t);\n\treturn signed;\n}\n\n/** Assets kept on a remote (not pinned to a fixed `url`). */\nfunction storedAssets(\n\tassets: AssetManifest | undefined,\n): [string, AssetEntry][] {\n\treturn Object.entries(assets ?? {}).filter(([, entry]) => !entry.url);\n}\n\nasync function localState(\n\tcwd: string,\n\tpath: string,\n\tentry: AssetEntry,\n): Promise<AssetState> {\n\tconst file = join(cwd, path);\n\tif (!existsSync(file)) return \"missing\";\n\tif (statSync(file).size !== entry.size) return \"changed\";\n\treturn (await hashFile(file)).sha256 === entry.sha256 ? \"ok\" : \"changed\";\n}\n\nasync function readableUrl(\n\tentry: AssetEntry,\n\tstorage: StorageConfig | undefined,\n\toptions: AssetOptions,\n): Promise<string> {\n\tconst url = readUrl(entry, storage);\n\tif (url) return url;\n\treturn openBucket(storage, entry.remote, options).presign(entry.sha256, 3600);\n}\n\nfunction openBucket(\n\tstorage: StorageConfig | undefined,\n\tremoteName: string | undefined,\n\toptions: AssetOptions,\n): Bucket {\n\tconst { name, remote } = pickRemote(storage, remoteName);\n\tconst keys = credentialsFromEnv(name, options.env);\n\tif (!keys) throw noCredentials(name);\n\treturn new Bucket(remote, keys, { fetch: options.fetch });\n}\n\nfunction noCredentials(remote: string, path?: string): AssetsError {\n\tconst [id, secret] = credentialEnvNames(remote);\n\treturn new AssetsError(\n\t\t`${path ? `${path} is on ${remote}, which` : `Remote ${remote}`} needs keys: set ${id} and ${secret} (or AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)${path ? \", or give it a publicUrl\" : \"\"}.`,\n\t\t\"no_credentials\",\n\t);\n}\n\nasync function upload(\n\tbucket: Bucket,\n\tcwd: string,\n\tpath: string,\n\tdigest: { sha256: string; size: number },\n\tlog?: (line: string) => void,\n): Promise<void> {\n\tlog?.(`Uploading ${path} (${megabytes(digest.size)})`);\n\tlet shown = 0;\n\tawait bucket.upload(join(cwd, path), digest, ({ sent, total }) => {\n\t\tconst percent = Math.floor((sent / total) * 10) * 10;\n\t\tif (total > 64e6 && percent > shown && percent < 100) {\n\t\t\tshown = percent;\n\t\t\tlog?.(` ${percent}%`);\n\t\t}\n\t});\n}\n\nasync function reachable(url: string, fetchImpl = fetch): Promise<boolean> {\n\tconst res = await fetchImpl(url, { method: \"HEAD\" }).catch(() => undefined);\n\treturn res?.ok ?? false;\n}\n\n/** Project-relative POSIX paths of `path`, or of every file under it. */\nfunction expand(cwd: string, path: string): string[] {\n\tconst abs = resolve(cwd, path);\n\tconst rel = relative(cwd, abs).split(sep).join(\"/\");\n\tif (!isAssetPath(rel) || rel.startsWith(\"../\"))\n\t\tthrow new AssetsError(`${path} is outside the project.`, \"outside_project\");\n\tif (!existsSync(abs))\n\t\tthrow new AssetsError(`${path} does not exist.`, \"not_found\");\n\tif (!statSync(abs).isDirectory()) return [rel];\n\treturn readdirSync(abs, { withFileTypes: true })\n\t\t.filter((d) => !d.name.startsWith(\".\"))\n\t\t.flatMap((d) => expand(cwd, `${rel}/${d.name}`))\n\t\t.sort();\n}\n\nconst IGNORE_HEADER =\n\t\"# framefields assets: on the bucket, pinned in framefields.json\";\n\n/** Adds the files to .gitignore, under one marked block. */\nfunction ignore(cwd: string, files: string[]): void {\n\tconst file = join(cwd, \".gitignore\");\n\tconst text = existsSync(file) ? readFileSync(file, \"utf8\") : \"\";\n\tconst lines = new Set(text.split(\"\\n\"));\n\tconst fresh = files.map((f) => `/${f}`).filter((l) => !lines.has(l));\n\tif (fresh.length === 0) return;\n\tconst header = lines.has(IGNORE_HEADER) ? [] : [IGNORE_HEADER];\n\tconst lead = text && !text.endsWith(\"\\n\") ? \"\\n\" : \"\";\n\tappendFileSync(file, `${lead}${[...header, ...fresh].join(\"\\n\")}\\n`);\n}\n\nfunction trackedByGit(cwd: string, files: string[]): string[] {\n\ttry {\n\t\treturn execFileSync(\"git\", [\"ls-files\", \"--\", ...files], {\n\t\t\tcwd,\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t})\n\t\t\t.split(\"\\n\")\n\t\t\t.filter(Boolean);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction sortKeys(assets: AssetManifest): AssetManifest {\n\treturn Object.fromEntries(\n\t\tObject.entries(assets).sort(([a], [b]) => a.localeCompare(b)),\n\t);\n}\n\nexport function megabytes(bytes: number): string {\n\treturn `${(bytes / 1e6).toFixed(bytes < 1e7 ? 1 : 0)} MB`;\n}\n\nconst ASSETS_USAGE = `Usage: framefields assets add <path...> [--remote <name>]\n framefields assets push | pull [--overwrite] | status [--json]\n`;\n\n/** The `framefields assets` command. */\nexport async function runAssets(\n\t[sub, ...paths]: string[],\n\toptions: AssetOptions & {\n\t\tremote?: string;\n\t\toverwrite?: boolean;\n\t\tjson?: boolean;\n\t},\n): Promise<number> {\n\tconst log = options.log ?? (() => {});\n\tif (sub === \"add\" && paths.length > 0) {\n\t\tconst added = await addAssets(paths, options);\n\t\tconst sent = added.filter((a) => a.uploaded).length;\n\t\tlog(\n\t\t\t`Recorded ${added.length} asset${added.length === 1 ? \"\" : \"s\"} in ${CONFIG_FILE} (${sent} uploaded, ${added.length - sent} already on the bucket). Commit ${CONFIG_FILE} and .gitignore.`,\n\t\t);\n\t\treturn 0;\n\t}\n\tif (sub === \"push\") {\n\t\tconst { uploaded, present } = await pushAssets(options);\n\t\tlog(\n\t\t\t`Uploaded ${uploaded.length}; ${present.length} already on the bucket.`,\n\t\t);\n\t\treturn 0;\n\t}\n\tif (sub === \"pull\") {\n\t\tconst { downloaded, present, changed } = await pullAssets(options);\n\t\tlog(`Downloaded ${downloaded.length}; ${present.length} already here.`);\n\t\tif (changed.length)\n\t\t\tlog(\n\t\t\t\t`Changed here, left alone: ${changed.join(\", \")}. \\`framefields assets add\\` records them, --overwrite restores them.`,\n\t\t\t);\n\t\treturn changed.length ? 1 : 0;\n\t}\n\tif (sub === \"status\") {\n\t\tconst entries = await assetStatus(options.cwd);\n\t\tif (options.json) log(JSON.stringify({ assets: entries }));\n\t\telse if (entries.length === 0) log(`No assets in ${CONFIG_FILE}.`);\n\t\telse\n\t\t\tfor (const e of entries)\n\t\t\t\tlog(`${e.state.padEnd(8)} ${e.path} (${megabytes(e.size)})`);\n\t\treturn entries.some((e) => e.state !== \"ok\") ? 1 : 0;\n\t}\n\tprocess.stderr.write(ASSETS_USAGE);\n\treturn 2;\n}\n","/**\n * Where a cloud render gets the project from: the git repo the working\n * directory is in, at the commit checked out now. Cloud workers fetch from\n * the remote, so that commit has to be pushed; uncommitted changes are not\n * rendered.\n */\nimport { execFileSync } from \"node:child_process\";\nimport { realpathSync } from \"node:fs\";\nimport path from \"node:path\";\n\nexport interface CloudSource {\n\trepo: string;\n\tref?: string;\n\tcommit?: string;\n\t/** The project's folder inside the repo (monorepos), `.` at the root. */\n\tworkdir?: string;\n}\n\nexport interface ResolvedSource {\n\tsource: CloudSource;\n\t/** The entry relative to `source.workdir`, as the worker loads it. */\n\tentry: string;\n\t/** Things that render differently than the user may expect (uncommitted changes). */\n\twarnings: string[];\n}\n\n/** Reads repo, branch, commit and folder from git, and checks the commit is pushed. */\nexport function resolveGitSource(cwd: string, entry: string): ResolvedSource {\n\tconst git = (...args: string[]) =>\n\t\texecFileSync(\"git\", args, {\n\t\t\tcwd,\n\t\t\tencoding: \"utf8\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t}).trim();\n\tlet root: string;\n\ttry {\n\t\troot = git(\"rev-parse\", \"--show-toplevel\");\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`${cwd} is not in a git repository. Cloud renders fetch the project from git: commit it and push it to a remote first.`,\n\t\t);\n\t}\n\t// git reports the root with symlinks resolved (macOS /var → /private/var).\n\tconst workdir =\n\t\tpath\n\t\t\t.relative(realpathSync(root), realpathSync(cwd))\n\t\t\t.split(path.sep)\n\t\t\t.join(\"/\") || \".\";\n\tconst relEntry = path\n\t\t.relative(cwd, path.resolve(cwd, entry))\n\t\t.split(path.sep)\n\t\t.join(\"/\");\n\tif (relEntry.startsWith(\"../\") || path.isAbsolute(relEntry))\n\t\tthrow new Error(\n\t\t\t`${entry} is outside ${cwd}; run from the project folder that contains it.`,\n\t\t);\n\n\tconst branch = git(\"rev-parse\", \"--abbrev-ref\", \"HEAD\");\n\tconst commit = git(\"rev-parse\", \"HEAD\");\n\tconst remoteName = upstreamRemote(git, branch) ?? \"origin\";\n\tlet remoteUrl: string;\n\ttry {\n\t\tremoteUrl = git(\"remote\", \"get-url\", remoteName);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`The repository has no \"${remoteName}\" remote. Push the project to a git host first.`,\n\t\t);\n\t}\n\tconst pushed = git(\"branch\", \"-r\", \"--contains\", commit);\n\tif (!pushed)\n\t\tthrow new Error(\n\t\t\t`Commit ${commit.slice(0, 7)} is not on ${remoteName}. Push it first (\\`git push\\`): cloud workers fetch the project from the remote.`,\n\t\t);\n\tconst dirty = git(\"status\", \"--porcelain\", \"--untracked-files=no\", \"--\", \".\");\n\treturn {\n\t\tsource: {\n\t\t\trepo: toHttps(remoteUrl),\n\t\t\t...(branch !== \"HEAD\" && { ref: branch }),\n\t\t\tcommit,\n\t\t\tworkdir,\n\t\t},\n\t\tentry: relEntry,\n\t\twarnings: dirty\n\t\t\t? [\n\t\t\t\t\t`Uncommitted changes are not rendered: the cloud renders commit ${commit.slice(0, 7)}.`,\n\t\t\t\t]\n\t\t\t: [],\n\t};\n}\n\nfunction upstreamRemote(\n\tgit: (...args: string[]) => string,\n\tbranch: string,\n): string | undefined {\n\tif (branch === \"HEAD\") return undefined;\n\ttry {\n\t\treturn git(\"config\", `branch.${branch}.remote`) || undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** `git@github.com:acme/films.git` → `https://github.com/acme/films.git`; credentials dropped. */\nexport function toHttps(url: string): string {\n\tconst scp = /^[\\w.-]+@([^:/]+):(.+)$/.exec(url);\n\tif (scp) return `https://${scp[1]}/${scp[2]}`;\n\tconst parsed = URL.canParse(url) ? new URL(url) : undefined;\n\tif (parsed && (parsed.protocol === \"ssh:\" || parsed.protocol === \"git:\"))\n\t\treturn `https://${parsed.hostname}${parsed.pathname}`;\n\tif (parsed?.protocol === \"https:\" || parsed?.protocol === \"http:\") {\n\t\tparsed.username = \"\";\n\t\tparsed.password = \"\";\n\t\treturn parsed.toString();\n\t}\n\treturn url;\n}\n","/**\n * Cloud renders on api.framefields.dev: the project renders from git on\n * framefields' GPU workers, billed to the account that owns the API key.\n *\n * ```ts\n * import { renderCloud } from \"framefields/cloud\";\n *\n * const result = await renderCloud({\n * render: \"film\", // a render named in framefields.json\n * outputPath: \"output/film.mp4\",\n * onProgress: (s) => console.log(s.status, s.progress.frames),\n * });\n * ```\n *\n * Without a framefields.json, name the module instead: `entry: \"src/film.ts\"`\n * (and `export`, `workers`, …). Options passed here override the named\n * render's.\n *\n * `workers: \"auto\"` probes the film on one worker first, then splits it into\n * as many chunks as stay efficient: short films stay on one worker, long ones\n * spread out up to `maxWorkers`. `dryRun: true` returns that plan with the\n * estimated cost and renders nothing. Aborting `signal` cancels the render;\n * GPU time already used is charged.\n */\nimport { createWriteStream } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { ReadableStream as WebReadableStream } from \"node:stream/web\";\nimport { AssetsError, prepareCloudAssets } from \"../cli/assets.js\";\nimport { CONFIG_FILE, findRender, readConfig } from \"../cli/config.js\";\nimport { type CloudSource, resolveGitSource } from \"./git-source.js\";\n\nexport { type CloudSource, resolveGitSource, toHttps } from \"./git-source.js\";\n\nexport const FRAMEFIELDS_API_URL = \"https://api.framefields.dev\";\n\nexport interface CloudRenderOptions {\n\t/** A render named in `cwd`'s framefields.json; its fields are the defaults here. */\n\trender?: string;\n\t/** The module that builds the composition, relative to `cwd`. Required without `render`. */\n\tentry?: string;\n\t/** Its export: a Composition, or a function returning one. Default `buildFilm`. */\n\texport?: string;\n\t/** Passed to the export when it is a function. */\n\targs?: unknown;\n\t/** When the export returns several compositions, the one to render. */\n\tselect?: string;\n\t/** 1 (default) renders on one worker; a number or \"auto\" splits the film. */\n\tworkers?: number | \"auto\";\n\t/** Upper bound for \"auto\" (the API caps it too). */\n\tmaxWorkers?: number;\n\tcodec?: \"h264\" | \"vp9\";\n\tquality?: string;\n\t/** Probe and plan only: returns the plan and estimated cost, renders nothing. */\n\tdryRun?: boolean;\n\t/** Download the finished video here. */\n\toutputPath?: string;\n\t/** Project folder. Default `process.cwd()`. */\n\tcwd?: string;\n\t/** Instead of reading repo, branch and commit from git. */\n\tsource?: CloudSource;\n\t/** Default `process.env.FRAMEFIELDS_API_KEY`. */\n\tapiKey?: string;\n\t/** Default `process.env.FRAMEFIELDS_API_URL`, else https://api.framefields.dev. */\n\tapiUrl?: string;\n\t/** Called with every status poll. */\n\tonProgress?: (status: CloudRenderStatus) => void;\n\t/** Called for each warning (uncommitted changes). Default: stderr. */\n\tonWarning?: (message: string) => void;\n\t/** Called as assets upload before the render. Default: stderr. */\n\tonLog?: (message: string) => void;\n\t/** Aborting cancels the cloud render. */\n\tsignal?: AbortSignal;\n\t/** Status poll interval, ms. Default 3000. */\n\tpollMs?: number;\n}\n\nexport type CloudRenderPhase =\n\t| \"probing\"\n\t| \"holding\"\n\t| \"rendering\"\n\t| \"stitching\"\n\t| \"planned\"\n\t| \"completed\"\n\t| \"failed\"\n\t| \"cancelled\";\n\nexport interface CloudRenderPlan {\n\tworkers: number;\n\t/** Render time of the whole film on one GPU, seconds. */\n\tworkSec: number;\n\t/** Expected wall time with this plan, seconds. */\n\tetaSec: number;\n\tchunks: { start: number; end: number; workSec: number }[];\n}\n\nexport interface CloudRenderStatus {\n\tid: string;\n\tstatus: CloudRenderPhase;\n\tworkers: number;\n\tplan?: CloudRenderPlan;\n\tprogress: {\n\t\tframes: number;\n\t\ttotalFrames: number | null;\n\t\tetaSec: number | null;\n\t};\n\t/** Charged so far (final once the render ended), USD. */\n\tcostUsd: number;\n\tgpuSeconds: number;\n\t/** The planned render's estimated charge, USD. */\n\testimateUsd?: number;\n\t/** The commit rendered. */\n\tsha?: string;\n\toutput?: { url: string; bytes?: number };\n\terror?: { code: string; message: string };\n}\n\nexport interface CloudRenderResult extends CloudRenderStatus {\n\t/** Where the video was downloaded (`outputPath`). */\n\tfilePath?: string;\n}\n\n/** A cloud render that failed, was cancelled, or was refused by the API. */\nexport class CloudRenderError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly code: string,\n\t\treadonly status?: CloudRenderStatus,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CloudRenderError\";\n\t}\n}\n\nconst DONE = new Set<CloudRenderPhase>([\n\t\"planned\",\n\t\"completed\",\n\t\"failed\",\n\t\"cancelled\",\n]);\n\n/** Starts a cloud render and waits for it; resolves when it completed (or was planned). */\nexport async function renderCloud(\n\toptions: CloudRenderOptions,\n): Promise<CloudRenderResult> {\n\tconst api = cloudClient(options);\n\tconst cwd = options.cwd ?? process.cwd();\n\tconst o = withNamedRender(cwd, options);\n\tconst resolved = options.source\n\t\t? { source: options.source, entry: o.entry, warnings: [] }\n\t\t: resolveGitSource(cwd, o.entry);\n\tconst warn =\n\t\toptions.onWarning ??\n\t\t((m: string) => process.stderr.write(`framefields: ${m}\\n`));\n\tfor (const w of resolved.warnings) warn(w);\n\tconst assets = await cloudAssets(cwd, options);\n\n\tlet status = await api.start({\n\t\tsource: Object.keys(assets).length\n\t\t\t? { ...resolved.source, assets }\n\t\t\t: resolved.source,\n\t\ttarget: {\n\t\t\tentry: resolved.entry,\n\t\t\texport: o.export ?? \"buildFilm\",\n\t\t\t...(o.args !== undefined && { args: o.args }),\n\t\t\t...(o.select && { select: [o.select] }),\n\t\t},\n\t\trender: {\n\t\t\tcodec: o.codec ?? \"h264\",\n\t\t\t...(o.quality && { quality: o.quality }),\n\t\t},\n\t\tworkers: o.workers ?? 1,\n\t\t...(o.maxWorkers && { max_workers: o.maxWorkers }),\n\t\tdry_run: options.dryRun ?? false,\n\t\t...(o.name && { name: o.name }),\n\t\t...(o.title && { title: o.title }),\n\t});\n\toptions.onProgress?.(status);\n\n\ttry {\n\t\twhile (!DONE.has(status.status)) {\n\t\t\tawait sleep(options.pollMs ?? 3000, options.signal);\n\t\t\tstatus = await api.status(status.id);\n\t\t\toptions.onProgress?.(status);\n\t\t}\n\t} catch (err) {\n\t\tif (options.signal?.aborted) {\n\t\t\tconst final = await api.cancel(status.id).catch(() => status);\n\t\t\tthrow new CloudRenderError(\n\t\t\t\t\"The cloud render was cancelled.\",\n\t\t\t\t\"cancelled\",\n\t\t\t\tfinal,\n\t\t\t);\n\t\t}\n\t\tthrow err;\n\t}\n\n\tif (status.status === \"failed\" || status.status === \"cancelled\")\n\t\tthrow new CloudRenderError(\n\t\t\tstatus.error\n\t\t\t\t? `Cloud render ${status.status}: ${status.error.message} (${status.error.code})`\n\t\t\t\t: `Cloud render ${status.status}.`,\n\t\t\tstatus.error?.code ?? status.status,\n\t\t\tstatus,\n\t\t);\n\tif (status.status === \"completed\" && options.outputPath && status.output) {\n\t\tawait download(status.output.url, options.outputPath, options.signal);\n\t\treturn { ...status, filePath: options.outputPath };\n\t}\n\treturn status;\n}\n\n/**\n * Uploads assets the bucket lacks and signs reads of private ones: the\n * workers download each asset framefields.json pins at the commit.\n */\nasync function cloudAssets(\n\tcwd: string,\n\toptions: CloudRenderOptions,\n): Promise<Record<string, string>> {\n\ttry {\n\t\treturn await prepareCloudAssets({\n\t\t\tcwd,\n\t\t\tsignal: options.signal,\n\t\t\tlog:\n\t\t\t\toptions.onLog ??\n\t\t\t\t((m: string) => process.stderr.write(`framefields: ${m}\\n`)),\n\t\t});\n\t} catch (err) {\n\t\tif (err instanceof AssetsError)\n\t\t\tthrow new CloudRenderError(err.message, `assets_${err.code}`);\n\t\tthrow err;\n\t}\n}\n\n/**\n * The options with a named render's fields filled in where the caller left\n * them out, plus the name and title the dashboard shows.\n */\nexport function withNamedRender(\n\tcwd: string,\n\toptions: CloudRenderOptions,\n): CloudRenderOptions & { entry: string; name?: string; title?: string } {\n\tif (!options.render) {\n\t\tif (!options.entry)\n\t\t\tthrow new CloudRenderError(\n\t\t\t\t\"Name a render from framefields.json (render) or a module (entry).\",\n\t\t\t\t\"invalid_request\",\n\t\t\t);\n\t\treturn { ...options, entry: options.entry };\n\t}\n\tconst spec = findRender(cwd, options.render);\n\tif (!spec) {\n\t\tconst names = Object.keys(readConfig(cwd).config.renders ?? {});\n\t\tthrow new CloudRenderError(\n\t\t\tnames.length\n\t\t\t\t? `No render named \"${options.render}\" in ${CONFIG_FILE}. Renders: ${names.join(\", \")}.`\n\t\t\t\t: `No render named \"${options.render}\": ${CONFIG_FILE} has no \"renders\".`,\n\t\t\t\"render_not_found\",\n\t\t);\n\t}\n\tconst defined = Object.fromEntries(\n\t\tObject.entries(options).filter(([, v]) => v !== undefined),\n\t) as CloudRenderOptions;\n\treturn {\n\t\tentry: spec.entry,\n\t\texport: spec.export,\n\t\targs: spec.args,\n\t\tselect: spec.select,\n\t\tworkers: spec.workers,\n\t\tmaxWorkers: spec.maxWorkers,\n\t\tcodec: spec.codec,\n\t\tquality: spec.quality,\n\t\t...defined,\n\t\tname: spec.name,\n\t\ttitle: spec.title ?? spec.name,\n\t} as CloudRenderOptions & { entry: string; name: string; title: string };\n}\n\n/** The API calls behind `renderCloud`, for callers who track renders themselves. */\nexport function cloudClient(\n\toptions: Pick<CloudRenderOptions, \"apiKey\" | \"apiUrl\">,\n) {\n\tconst key = options.apiKey ?? process.env.FRAMEFIELDS_API_KEY;\n\tif (!key)\n\t\tthrow new CloudRenderError(\n\t\t\t\"No API key. Set FRAMEFIELDS_API_KEY (keys at https://framefields.dev/dashboard/keys) or pass apiKey.\",\n\t\t\t\"invalid_api_key\",\n\t\t);\n\tconst base = (\n\t\toptions.apiUrl ??\n\t\tprocess.env.FRAMEFIELDS_API_URL ??\n\t\tFRAMEFIELDS_API_URL\n\t).replace(/\\/+$/, \"\");\n\tconst call = async (method: string, route: string, body?: unknown) => {\n\t\tconst res = await fetch(`${base}/v1/render${route}`, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${key}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\t...(body !== undefined && { body: JSON.stringify(body) }),\n\t\t});\n\t\tconst json = (await res.json().catch(() => ({}))) as ApiStatus & {\n\t\t\terror?: { type?: string; message?: string };\n\t\t};\n\t\tif (!res.ok)\n\t\t\tthrow new CloudRenderError(\n\t\t\t\tjson.error?.message ??\n\t\t\t\t\t`api.framefields.dev answered HTTP ${res.status}`,\n\t\t\t\tjson.error?.type ?? `http_${res.status}`,\n\t\t\t);\n\t\treturn fromApi(json);\n\t};\n\treturn {\n\t\tstart: (body: unknown) => call(\"POST\", \"\", body),\n\t\tstatus: (id: string) => call(\"GET\", `/${encodeURIComponent(id)}`),\n\t\tcancel: (id: string) => call(\"DELETE\", `/${encodeURIComponent(id)}`),\n\t};\n}\n\n/** The API's snake_case status. */\ninterface ApiStatus {\n\tid: string;\n\tstatus: CloudRenderPhase;\n\tworkers?: number;\n\tplan?: {\n\t\tworkers: number;\n\t\twork_sec: number;\n\t\teta_sec: number;\n\t\tchunks: CloudRenderPlan[\"chunks\"];\n\t};\n\tprogress?: {\n\t\tframes?: number;\n\t\ttotal_frames?: number | null;\n\t\teta_sec?: number | null;\n\t};\n\tcost_usd?: number;\n\tgpu_seconds?: number;\n\testimate_usd?: number;\n\tsha?: string;\n\toutput?: { url: string; bytes?: number };\n\terror?: { code: string; message: string };\n}\n\nfunction fromApi(s: ApiStatus): CloudRenderStatus {\n\treturn {\n\t\tid: s.id,\n\t\tstatus: s.status,\n\t\tworkers: s.workers ?? 1,\n\t\t...(s.plan && {\n\t\t\tplan: {\n\t\t\t\tworkers: s.plan.workers,\n\t\t\t\tworkSec: s.plan.work_sec,\n\t\t\t\tetaSec: s.plan.eta_sec,\n\t\t\t\tchunks: s.plan.chunks,\n\t\t\t},\n\t\t}),\n\t\tprogress: {\n\t\t\tframes: s.progress?.frames ?? 0,\n\t\t\ttotalFrames: s.progress?.total_frames ?? null,\n\t\t\tetaSec: s.progress?.eta_sec ?? null,\n\t\t},\n\t\tcostUsd: s.cost_usd ?? 0,\n\t\tgpuSeconds: s.gpu_seconds ?? 0,\n\t\t...(s.estimate_usd !== undefined && { estimateUsd: s.estimate_usd }),\n\t\t...(s.sha && { sha: s.sha }),\n\t\t...(s.output && { output: s.output }),\n\t\t...(s.error && { error: s.error }),\n\t};\n}\n\nasync function download(url: string, file: string, signal?: AbortSignal) {\n\tconst res = await fetch(url, { signal });\n\tif (!res.ok || !res.body)\n\t\tthrow new CloudRenderError(\n\t\t\t`Downloading the render failed: HTTP ${res.status}`,\n\t\t\t\"download_failed\",\n\t\t);\n\tawait fs.mkdir(path.dirname(path.resolve(file)), { recursive: true });\n\tawait pipeline(\n\t\tReadable.fromWeb(res.body as WebReadableStream),\n\t\tcreateWriteStream(file),\n\t);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) return reject(signal.reason);\n\t\tconst timer = setTimeout(resolve, ms);\n\t\tsignal?.addEventListener(\n\t\t\t\"abort\",\n\t\t\t() => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(signal.reason);\n\t\t\t},\n\t\t\t{ once: true },\n\t\t);\n\t});\n}\n"],"mappings":"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"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import "../chunk-DOL2i2sR.mjs";
|
|
2
2
|
import "../index-C-V6CAhP.mjs";
|
|
3
3
|
import "../index-BVd6nXd5.mjs";
|
|
4
|
-
import "../index-
|
|
4
|
+
import "../index-s2qQ8ifZ.mjs";
|
|
5
5
|
import "../renderer-DKJOon6y.mjs";
|
|
6
|
-
import "../index-
|
|
7
|
-
import "../renderer-
|
|
8
|
-
import { $a as
|
|
9
|
-
import "../index-
|
|
10
|
-
import "../audio-
|
|
11
|
-
import "../index-
|
|
12
|
-
import "../index-
|
|
13
|
-
import "../index-
|
|
14
|
-
import "../index-
|
|
15
|
-
import "../index-
|
|
6
|
+
import "../index-RILu3ULT.mjs";
|
|
7
|
+
import "../renderer-DU3f6ZrS.mjs";
|
|
8
|
+
import { $a as springSettleFrames, $i as beats, $r as GlyphUnit, Aa as last, Ai as TargetContext, Ar as BuildContext, Ba as rangeRects, Bi as Vec2, Br as CutoutOptions, Ca as frameSpan, Ci as Rng, Co as wordRanges, Cr as ArcPath, Da as holdFirstKeys, Di as StaggerOrder, Dr as BakeOptions, Ea as hashString, Ei as Spring, Er as AudioLevels, Fa as mix, Fi as ThemeName, Fr as ComponentExtras, Ga as rng, Gi as arcPath, Gr as FontNeed, Ha as resampleBands, Hi as after, Hr as Elevation, Ia as offsetCues, Ii as Track, Ir as ComponentMeta, Ja as scaleFrames, Ji as audioLevelsSchema, Jr as FrameValue, Ka as round, Ki as arrowPaths, Kr as FontRole, La as parseColor, Li as TrackedObjectLike, Lr as Cue, Ma as linePath, Mi as TextLayout, Mr as CanvasSize, Na as lineShift, Ni as Theme, Nr as ComponentDefaults, Oa as inkOn, Oi as SyntaxKind, Or as BakedKey, Pa as luminance, Pi as ThemeInput, Pr as ComponentDefinition, Qa as springKeys, Qi as basePropsSchema, Qr as GlyphProps, Ra as pulseKeys, Ri as UNIT_INDEX, Rr as Cues, Sa as findRange, Si as Rgba, So as wobblePoints, Sr as AnimatableMethods, Ta as hashRng, Ti as SafeInsets, Tr as ArrowGeometry, Ua as resolveMotion, Ui as analyzeChannels, Ur as ElevationLevel, Va as rendererChars, Vi as WordRange, Vr as EaseFn, Wa as resolveTarget, Wi as anchorPoint, Wr as ExtrudedTextOptions, Xa as smoothRelease, Xi as bakeSamples, Xr as GlyphAnimator, Ya as scheduleExpression, Yi as bakeFunction, Yr as FrameWindow, Za as springAt, Zi as bandEdges, Zr as GlyphBox, _a as ellipsePath, _i as PropsOf, _o as valueAt, aa as chain, ai as MOTION_PRESETS, ao as supersede, ba as evaluateGlyphExpression, bi as ResolvedMotion, bo as withDefaults, br as Anchor, ca as cover, ci as MediaOptions, co as textLayout, da as defineTheme, di as MotionPreset, do as toFrames, ea as bind, ei as GrainOptions, eo as springTrack, fa as dist, fi as MotionPresetName, fo as toPathData, ga as elevationStyle, gi as ProjectDefaults, go as typingFrames, ha as elevate, hi as Placement, ho as transparent, i as analyzeAudio, ia as catmullRom, ii as LayerStyleConfig, io as stepExpression, ja as lerp2, ji as TargetNode, jr as BuildResult, ka as isLight, ki as Target, kr as BaseProps, la as defineComponent, li as Metrics, lo as themeFrames, ma as ease$1, mi as ParticleOptions, mo as transformPathData, n as bindComponent, na as boundsOf, ni as Host, no as staggerOffsets, oa as constantExpression, oi as MeasureFn, oo as surfaceFill, pa as drawOnKeys, pi as MotionSize, po as toSeconds, qa as safeArea, qi as ascending, qr as FrameContextLike, r as z, ra as boxPath, ri as KeyBook, ro as staggerRanks, sa as contrastRatio, si as MeasureOptions, so as targetPoint, t as ComponentNode, ta as boilKeys, ti as HandOptions, to as squigglePath, ua as defineMeta, ui as MotionOptions, uo as themes, va as enterAnimation, vi as PulseOptions, vo as windowExpression, vr as targetSchema, wa as glyphAnimator, wi as SAFE_INSETS, wr as ArrowCurve, xa as exitAnimation, xi as ResolvedTarget, xo as within, xr as Animatable, ya as evaluateEase, yi as Rect, yo as withAlpha, yr as AnalyzeOptions, za as quantize, zi as UnitSchedule, zr as CuesOf } from "../index-Dg5BAtDq.mjs";
|
|
9
|
+
import "../index-CYVpYGM-.mjs";
|
|
10
|
+
import "../audio-7oqTUi4G.mjs";
|
|
11
|
+
import "../index-CMhkkc56.mjs";
|
|
12
|
+
import "../index-BHTycml5.mjs";
|
|
13
|
+
import "../index-BcxxxwhV.mjs";
|
|
14
|
+
import "../index-DhL7ckvs.mjs";
|
|
15
|
+
import "../index-Cq8jgdNY.mjs";
|
|
16
16
|
export { AnalyzeOptions, Anchor, Animatable, AnimatableMethods, ArcPath, ArrowCurve, ArrowGeometry, AudioLevels, BakeOptions, BakedKey, BaseProps, BuildContext, BuildResult, CanvasSize, ComponentDefaults, ComponentDefinition, ComponentExtras, ComponentMeta, ComponentNode, Cue, Cues, CuesOf, CutoutOptions, EaseFn, Elevation, ElevationLevel, ExtrudedTextOptions, FontNeed, FontRole, FrameContextLike, FrameValue, FrameWindow, GlyphAnimator, GlyphBox, GlyphProps, GlyphUnit, GrainOptions, HandOptions, Host, KeyBook, LayerStyleConfig, MOTION_PRESETS, MeasureFn, MeasureOptions, MediaOptions, Metrics, MotionOptions, MotionPreset, MotionPresetName, MotionSize, ParticleOptions, Placement, ProjectDefaults, PropsOf, PulseOptions, Rect, ResolvedMotion, ResolvedTarget, Rgba, Rng, SAFE_INSETS, SafeInsets, Spring, StaggerOrder, SyntaxKind, Target, TargetContext, TargetNode, TextLayout, Theme, ThemeInput, ThemeName, Track, TrackedObjectLike, UNIT_INDEX, UnitSchedule, Vec2, WordRange, after, analyzeAudio, analyzeChannels, anchorPoint, arcPath, arrowPaths, ascending, audioLevelsSchema, bakeFunction, bakeSamples, bandEdges, basePropsSchema, beats, bind, bindComponent, boilKeys, boundsOf, boxPath, catmullRom, chain, constantExpression, contrastRatio, cover, defineComponent, defineMeta, defineTheme, dist, drawOnKeys, ease$1 as ease, elevate, elevationStyle, ellipsePath, enterAnimation, evaluateEase, evaluateGlyphExpression, exitAnimation, findRange, frameSpan, glyphAnimator, hashRng, hashString, holdFirstKeys, inkOn, isLight, last, lerp2, linePath, lineShift, luminance, mix, offsetCues, parseColor, pulseKeys, quantize, rangeRects, rendererChars, resampleBands, resolveMotion, resolveTarget, rng, round, safeArea, scaleFrames, scheduleExpression, smoothRelease, springAt, springKeys, springSettleFrames, springTrack, squigglePath, staggerOffsets, staggerRanks, stepExpression, supersede, surfaceFill, targetPoint, targetSchema, textLayout, themeFrames, themes, toFrames, toPathData, toSeconds, transformPathData, transparent, typingFrames, valueAt, windowExpression, withAlpha, withDefaults, within, wobblePoints, wordRanges, z };
|