framefields 2.12.0 → 2.13.1
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/README.md +9 -4
- package/dist/audio/index.d.mts +6 -5
- package/dist/audio/index.mjs +13 -13
- package/dist/{audio-afTBdB3U.d.mts → audio-C4B9p_yq.d.mts} +3 -4
- package/dist/audio-C4B9p_yq.d.mts.map +1 -0
- package/dist/{audio-DHLoNcxD.mjs → audio-DIvi6hTD.mjs} +4 -4
- package/dist/{audio-DHLoNcxD.mjs.map → audio-DIvi6hTD.mjs.map} +1 -1
- package/dist/{audio-KHBadECb.mjs → audio-DS9Jg2ls.mjs} +1 -1
- package/dist/{audio-KHBadECb.mjs.map → audio-DS9Jg2ls.mjs.map} +1 -1
- package/dist/{check-result-Culfu7Nx.mjs → check-result-DZWx73V8.mjs} +1 -1
- package/dist/{check-result-Culfu7Nx.mjs.map → check-result-DZWx73V8.mjs.map} +1 -1
- package/dist/cli/check-worker.mjs +51 -51
- package/dist/cli/check-worker.mjs.map +1 -1
- package/dist/cli/local-worker.d.mts +28 -0
- package/dist/cli/local-worker.d.mts.map +1 -0
- package/dist/cli/local-worker.mjs +83 -0
- package/dist/cli/local-worker.mjs.map +1 -0
- package/dist/cli.mjs +229 -54
- package/dist/cli.mjs.map +1 -1
- package/dist/cloud/index.d.mts +2 -0
- package/dist/cloud/index.d.mts.map +1 -1
- package/dist/cloud/index.mjs +1 -1
- package/dist/{cloud-COid1Ipa.mjs → cloud-Cj1TIme8.mjs} +306 -7
- package/dist/cloud-Cj1TIme8.mjs.map +1 -0
- package/dist/components/index.d.mts +15 -14
- package/dist/components/index.mjs +47 -47
- package/dist/{dist-CySGkG54.mjs → dist-BSKAbyea.mjs} +2 -2
- package/dist/{dist-CySGkG54.mjs.map → dist-BSKAbyea.mjs.map} +1 -1
- package/dist/{dist-BwtxciN4.mjs → dist-B_rSWeOz.mjs} +1 -1
- package/dist/{dist-Bf2_efYP.mjs → dist-C8XSqfTx.mjs} +1 -1
- package/dist/{dist-Bf2_efYP.mjs.map → dist-C8XSqfTx.mjs.map} +1 -1
- package/dist/{dist-BSqeChht.mjs → dist-CCrYOkcc.mjs} +145 -84
- package/dist/dist-CCrYOkcc.mjs.map +1 -0
- package/dist/dist-CiTgmfUw.mjs +502 -0
- package/dist/dist-CiTgmfUw.mjs.map +1 -0
- package/dist/{dist-BIE8fvlv.mjs → dist-DgZpN6IK.mjs} +1 -1
- package/dist/{dist-BIE8fvlv.mjs.map → dist-DgZpN6IK.mjs.map} +1 -1
- package/dist/{dist-B-OPY7Cs.mjs → dist-DtPPPsZV.mjs} +356 -145
- package/dist/dist-DtPPPsZV.mjs.map +1 -0
- package/dist/{dist-2_lT3Dwc.mjs → dist-Kbf-JTry.mjs} +2 -2
- package/dist/{dist-2_lT3Dwc.mjs.map → dist-Kbf-JTry.mjs.map} +1 -1
- package/dist/effects/index.d.mts +6 -6
- package/dist/effects/index.mjs +36 -36
- package/dist/{effects-C8CL9cOq.mjs → effects-B-L3rLs6.mjs} +3 -3
- package/dist/{effects-C8CL9cOq.mjs.map → effects-B-L3rLs6.mjs.map} +1 -1
- package/dist/fonts/index.d.mts +1 -1
- package/dist/fonts/index.mjs +3 -3
- package/dist/{fonts-BQrDjnpV.mjs → fonts-k5ll8NTE.mjs} +2 -2
- package/dist/{fonts-BQrDjnpV.mjs.map → fonts-k5ll8NTE.mjs.map} +1 -1
- package/dist/{gpu-DHa-3Dou.mjs → gpu-D2HT3KcE.mjs} +2 -2
- package/dist/{gpu-DHa-3Dou.mjs.map → gpu-D2HT3KcE.mjs.map} +1 -1
- package/dist/{index-CTv9ZieD.d.mts → index-B08eSpaI.d.mts} +3 -30
- package/dist/index-B08eSpaI.d.mts.map +1 -0
- package/dist/index-BFTtXosj.d.mts +63 -0
- package/dist/index-BFTtXosj.d.mts.map +1 -0
- package/dist/{index-Drk6HC2k.d.mts → index-BGlaws7-.d.mts} +3 -3
- package/dist/{index-Drk6HC2k.d.mts.map → index-BGlaws7-.d.mts.map} +1 -1
- package/dist/{index-CAuNuvIg.d.mts → index-ByhlTwxh.d.mts} +5 -5
- package/dist/{index-CAuNuvIg.d.mts.map → index-ByhlTwxh.d.mts.map} +1 -1
- package/dist/{index-Fliv2Z-w.d.mts → index-C2yaponf.d.mts} +132 -7
- package/dist/index-C2yaponf.d.mts.map +1 -0
- package/dist/{index-BW0Q1ygn.d.mts → index-C5sgRLlG.d.mts} +1 -1
- package/dist/{index-BW0Q1ygn.d.mts.map → index-C5sgRLlG.d.mts.map} +1 -1
- package/dist/{index-CdCrae-I.d.mts → index-CnZhBlob.d.mts} +2 -2
- package/dist/index-CnZhBlob.d.mts.map +1 -0
- package/dist/{index-BNClElng.d.mts → index-CtKUQ2VG.d.mts} +281 -283
- package/dist/index-CtKUQ2VG.d.mts.map +1 -0
- package/dist/{index-WwuuX8ZJ.d.mts → index-DBh3WphX.d.mts} +2 -2
- package/dist/{index-WwuuX8ZJ.d.mts.map → index-DBh3WphX.d.mts.map} +1 -1
- package/dist/{index-gOVtTm-P.d.mts → index-DQ1U3HC3.d.mts} +14 -6
- package/dist/index-DQ1U3HC3.d.mts.map +1 -0
- package/dist/{index-COYNQ_mf.d.mts → index-a6JrbAK0.d.mts} +1 -1
- package/dist/{index-COYNQ_mf.d.mts.map → index-a6JrbAK0.d.mts.map} +1 -1
- package/dist/{index-DQa7mhzq.d.mts → index-rtCXNxGO.d.mts} +2 -2
- package/dist/{index-DQa7mhzq.d.mts.map → index-rtCXNxGO.d.mts.map} +1 -1
- package/dist/index.d.mts +16 -15
- package/dist/index.mjs +58 -58
- package/dist/preview/index.d.mts +5 -4
- package/dist/preview/index.mjs +12 -12
- package/dist/preview-engine/audio.mjs +1 -1
- package/dist/preview-engine/{chunk-FJTURGJV.mjs → chunk-3C2XT64C.mjs} +1 -1
- package/dist/preview-engine/chunk-52X7SURQ.mjs +494 -0
- package/dist/preview-engine/{chunk-4JNIEQS2.mjs → chunk-5ZS46EFB.mjs} +1 -1
- package/dist/preview-engine/{chunk-KBCZKIIQ.mjs → chunk-CYM75INB.mjs} +1 -1
- package/dist/preview-engine/chunk-FZ4RD7HV.mjs +1 -0
- package/dist/preview-engine/chunk-LZNHGH56.mjs +5 -0
- package/dist/preview-engine/{chunk-RGKS6YIA.mjs → chunk-N2VISDTG.mjs} +1 -1
- package/dist/preview-engine/chunk-N3XTDAL6.mjs +2227 -0
- package/dist/preview-engine/{chunk-O75BFM4S.mjs → chunk-NVXFEDJS.mjs} +1 -1
- package/dist/preview-engine/chunk-OBIJIQCZ.mjs +1 -0
- package/dist/preview-engine/{chunk-VUO4K52B.mjs → chunk-PD2HKW2S.mjs} +1 -1
- package/dist/preview-engine/{chunk-HTAHYSCW.mjs → chunk-R4H52Q7S.mjs} +1 -1
- package/dist/preview-engine/{chunk-6O7UDVNL.mjs → chunk-RYSV44B4.mjs} +1 -1
- package/dist/preview-engine/{chunk-TKXOSEIJ.mjs → chunk-SV3ZNZQU.mjs} +1 -1
- package/dist/preview-engine/{chunk-JAUMCOOJ.mjs → chunk-UBY2UYEL.mjs} +1 -1
- package/dist/preview-engine/{chunk-32WC4FRR.mjs → chunk-UE7Y65C3.mjs} +3 -3
- package/dist/preview-engine/{chunk-M4QVCQ3O.mjs → chunk-VMXJZ4KQ.mjs} +1 -1
- package/dist/preview-engine/{chunk-EYKN2VET.mjs → chunk-XCPRRMMW.mjs} +31 -31
- package/dist/preview-engine/components.mjs +1 -1
- package/dist/preview-engine/effects.mjs +1 -1
- package/dist/preview-engine/framefields.mjs +1 -1
- package/dist/preview-engine/player.mjs +5 -5
- package/dist/preview-engine/{renderers-L6GFGHS6.mjs → renderers-AFTUFMQQ.mjs} +1 -1
- package/dist/preview-engine/renderers-DU7KPFVV.mjs +1 -1
- package/dist/preview-engine/{renderers-PREFONJG.mjs → renderers-EPSF5CSQ.mjs} +1 -1
- package/dist/preview-engine/{renderers-R22CDFO4.mjs → renderers-OJWWIVNW.mjs} +1 -1
- package/dist/preview-engine/{renderers-TS32FDV7.mjs → renderers-RHMRWX46.mjs} +1 -1
- package/dist/preview-engine/renderers-VEHYARKY.mjs +1 -0
- package/dist/preview-engine/renderers-VRXAG3FR.mjs +1 -0
- package/dist/preview-engine/renderers-ZHSOWEMQ.mjs +1 -0
- package/dist/preview-engine/renderers-ZMDRNYSS.mjs +1 -0
- package/dist/preview-engine/renderers-ZMMQ7S2A.mjs +228 -0
- package/dist/preview-engine/signals.mjs +1 -1
- package/dist/preview-engine/{src-GPF7RIBU.mjs → src-YXNX4MLK.mjs} +1 -1
- package/dist/{preview-BUtt481A.mjs → preview-lHH8Tv4j.mjs} +323 -35
- package/dist/preview-lHH8Tv4j.mjs.map +1 -0
- package/dist/{program-Cvv_nb9T.mjs → program-BfiB9ttP.mjs} +17 -4
- package/dist/program-BfiB9ttP.mjs.map +1 -0
- package/dist/renderer/index.d.mts +4 -3
- package/dist/renderer/index.mjs +3 -3
- package/dist/renderer-0rLmztAv.mjs +5 -0
- package/dist/{renderer-D3QPNBEj.mjs → renderer-4nsuReW2.mjs} +5 -5
- package/dist/{renderer-D3QPNBEj.mjs.map → renderer-4nsuReW2.mjs.map} +1 -1
- package/dist/{renderer-DO1SZ5xY.mjs → renderer-7xQmXXMH.mjs} +5 -5
- package/dist/{renderer-DO1SZ5xY.mjs.map → renderer-7xQmXXMH.mjs.map} +1 -1
- package/dist/renderer-B0pjOXFY.mjs +5 -0
- package/dist/{renderer-BSsKlcHk.mjs → renderer-B10HDC13.mjs} +5 -5
- package/dist/{renderer-BSsKlcHk.mjs.map → renderer-B10HDC13.mjs.map} +1 -1
- package/dist/{renderer-DaY04IyU.mjs → renderer-B2IUPjhw.mjs} +5 -5
- package/dist/{renderer-DaY04IyU.mjs.map → renderer-B2IUPjhw.mjs.map} +1 -1
- package/dist/{renderer-O4y02xkD.mjs → renderer-B3_GddgJ.mjs} +4 -4
- package/dist/{renderer-O4y02xkD.mjs.map → renderer-B3_GddgJ.mjs.map} +1 -1
- package/dist/{renderer-DQJHjU0L.mjs → renderer-B3un4Pdi.mjs} +5 -5
- package/dist/{renderer-DQJHjU0L.mjs.map → renderer-B3un4Pdi.mjs.map} +1 -1
- package/dist/{renderer-PnnkUWm-.mjs → renderer-B6bK9rXm.mjs} +4 -4
- package/dist/{renderer-PnnkUWm-.mjs.map → renderer-B6bK9rXm.mjs.map} +1 -1
- package/dist/renderer-B7J13reL.mjs +5 -0
- package/dist/{renderer-HXw4cJZx.mjs → renderer-BEhZiOT4.mjs} +3 -3
- package/dist/{renderer-HXw4cJZx.mjs.map → renderer-BEhZiOT4.mjs.map} +1 -1
- package/dist/{renderer-xNOKSN3V.mjs → renderer-BEuXJY-C.mjs} +5 -5
- package/dist/{renderer-xNOKSN3V.mjs.map → renderer-BEuXJY-C.mjs.map} +1 -1
- package/dist/{renderer-IAffbHXx.mjs → renderer-BGchUBW_.mjs} +4 -4
- package/dist/{renderer-IAffbHXx.mjs.map → renderer-BGchUBW_.mjs.map} +1 -1
- package/dist/{renderer-CZClDMgF.mjs → renderer-BIKkxw_Z.mjs} +5 -5
- package/dist/{renderer-CZClDMgF.mjs.map → renderer-BIKkxw_Z.mjs.map} +1 -1
- package/dist/{renderer-BvRM3OZ6.mjs → renderer-BM19iK8v.mjs} +3 -3
- package/dist/{renderer-BvRM3OZ6.mjs.map → renderer-BM19iK8v.mjs.map} +1 -1
- package/dist/{renderer-CtpEzVBn.mjs → renderer-BOlHW3Mi.mjs} +3 -3
- package/dist/{renderer-CtpEzVBn.mjs.map → renderer-BOlHW3Mi.mjs.map} +1 -1
- package/dist/renderer-BPGIKGgl.mjs +5 -0
- package/dist/{renderer-4uZGSmUD.mjs → renderer-BTwuM9u-.mjs} +5 -5
- package/dist/{renderer-4uZGSmUD.mjs.map → renderer-BTwuM9u-.mjs.map} +1 -1
- package/dist/{renderer-DO_zXwMJ.mjs → renderer-BZMh2io2.mjs} +5 -5
- package/dist/{renderer-DO_zXwMJ.mjs.map → renderer-BZMh2io2.mjs.map} +1 -1
- package/dist/{renderer-rKw5_EjG.mjs → renderer-BZX932Lj.mjs} +4 -4
- package/dist/{renderer-rKw5_EjG.mjs.map → renderer-BZX932Lj.mjs.map} +1 -1
- package/dist/{renderer-5fGj_tqN.mjs → renderer-BhcTYhaP.mjs} +6 -6
- package/dist/{renderer-5fGj_tqN.mjs.map → renderer-BhcTYhaP.mjs.map} +1 -1
- package/dist/{renderer-DL3o_lG1.mjs → renderer-BmyFfvVA.mjs} +5 -5
- package/dist/{renderer-DL3o_lG1.mjs.map → renderer-BmyFfvVA.mjs.map} +1 -1
- package/dist/{renderer-DX60Kr20.mjs → renderer-BrEeUw7T.mjs} +3 -3
- package/dist/{renderer-DX60Kr20.mjs.map → renderer-BrEeUw7T.mjs.map} +1 -1
- package/dist/{renderer-Bf7Z7WT5.mjs → renderer-BsrKj6Td.mjs} +4 -4
- package/dist/{renderer-Bf7Z7WT5.mjs.map → renderer-BsrKj6Td.mjs.map} +1 -1
- package/dist/{renderer-BOg8i8eF.mjs → renderer-BuvKGwk3.mjs} +1 -1
- package/dist/{renderer-BOg8i8eF.mjs.map → renderer-BuvKGwk3.mjs.map} +1 -1
- package/dist/renderer-Bv-Artj1.mjs +5 -0
- package/dist/{renderer-_KIBvES8.mjs → renderer-BvBqTAtk.mjs} +5 -5
- package/dist/{renderer-_KIBvES8.mjs.map → renderer-BvBqTAtk.mjs.map} +1 -1
- package/dist/renderer-BvLjbhcL.mjs +5 -0
- package/dist/{renderer-BC_Nse6h.mjs → renderer-Bw-_GZVw.mjs} +4 -4
- package/dist/{renderer-BC_Nse6h.mjs.map → renderer-Bw-_GZVw.mjs.map} +1 -1
- package/dist/{renderer-CLTRTtQ8.mjs → renderer-Bw0O--gW.mjs} +5 -5
- package/dist/{renderer-CLTRTtQ8.mjs.map → renderer-Bw0O--gW.mjs.map} +1 -1
- package/dist/renderer-By6awWaf.mjs +5 -0
- package/dist/{renderer-DsPLMzy1.mjs → renderer-C-3qhk5x.mjs} +2 -2
- package/dist/{renderer-DsPLMzy1.mjs.map → renderer-C-3qhk5x.mjs.map} +1 -1
- package/dist/renderer-C0rvsz7m.mjs +5 -0
- package/dist/{renderer-DP9ScNM6.mjs → renderer-C4hd6Cqi.mjs} +3 -3
- package/dist/{renderer-DP9ScNM6.mjs.map → renderer-C4hd6Cqi.mjs.map} +1 -1
- package/dist/{renderer-B09I95bo.mjs → renderer-C64_B8It.mjs} +3 -3
- package/dist/{renderer-DrL3J9ci.mjs → renderer-C98XwEIr.mjs} +4 -4
- package/dist/{renderer-DrL3J9ci.mjs.map → renderer-C98XwEIr.mjs.map} +1 -1
- package/dist/{renderer-6g1ri445.mjs → renderer-CC22Djgi.mjs} +5 -5
- package/dist/{renderer-6g1ri445.mjs.map → renderer-CC22Djgi.mjs.map} +1 -1
- package/dist/renderer-CDgud_HB.mjs +5 -0
- package/dist/renderer-CDiRF3bG.mjs +6 -0
- package/dist/{renderer-FvvywNvv.mjs → renderer-CHCRcCKw.mjs} +3 -3
- package/dist/{renderer-FvvywNvv.mjs.map → renderer-CHCRcCKw.mjs.map} +1 -1
- package/dist/renderer-CIIEQd4B.mjs +5 -0
- package/dist/renderer-CJblwOA9.mjs +5 -0
- package/dist/renderer-CNMOXtXE.mjs +5 -0
- package/dist/{renderer-D3YbHjRG.mjs → renderer-CO4NGvAh.mjs} +95 -80
- package/dist/renderer-CO4NGvAh.mjs.map +1 -0
- package/dist/{renderer-ByFPmHBC.mjs → renderer-CO9vE3sd.mjs} +4 -4
- package/dist/{renderer-ByFPmHBC.mjs.map → renderer-CO9vE3sd.mjs.map} +1 -1
- package/dist/renderer-COeSeNGg.mjs +5 -0
- package/dist/{renderer-CN-mCIoI.mjs → renderer-CQ4h8n7p.mjs} +5 -5
- package/dist/{renderer-CN-mCIoI.mjs.map → renderer-CQ4h8n7p.mjs.map} +1 -1
- package/dist/{renderer-DEoerd-j.mjs → renderer-CRhEGqW4.mjs} +4 -4
- package/dist/{renderer-DEoerd-j.mjs.map → renderer-CRhEGqW4.mjs.map} +1 -1
- package/dist/{renderer-CiHVnhUk.mjs → renderer-CSu_vYPn.mjs} +5 -5
- package/dist/{renderer-CiHVnhUk.mjs.map → renderer-CSu_vYPn.mjs.map} +1 -1
- package/dist/{renderer-BJEexai1.mjs → renderer-CU6WT5jW.mjs} +5 -5
- package/dist/{renderer-BJEexai1.mjs.map → renderer-CU6WT5jW.mjs.map} +1 -1
- package/dist/renderer-CUfElmtZ.mjs +5 -0
- package/dist/{renderer-BwJ0nXXu.mjs → renderer-CXrnzihz.mjs} +5 -5
- package/dist/{renderer-BwJ0nXXu.mjs.map → renderer-CXrnzihz.mjs.map} +1 -1
- package/dist/renderer-CYh2lFoJ.mjs +5 -0
- package/dist/renderer-CYtVZYMH.mjs +5 -0
- package/dist/{renderer-BwV-o_1b.mjs → renderer-CdXBRdFf.mjs} +4 -4
- package/dist/{renderer-BwV-o_1b.mjs.map → renderer-CdXBRdFf.mjs.map} +1 -1
- package/dist/{renderer-DrK6pyfz.mjs → renderer-Cfx_FCSf.mjs} +5 -5
- package/dist/{renderer-DrK6pyfz.mjs.map → renderer-Cfx_FCSf.mjs.map} +1 -1
- package/dist/renderer-CjxZlkjb.mjs +5 -0
- package/dist/{renderer-CInMMs5x.mjs → renderer-CkTehyRX.mjs} +6 -6
- package/dist/{renderer-CInMMs5x.mjs.map → renderer-CkTehyRX.mjs.map} +1 -1
- package/dist/{renderer-DGXqspB9.mjs → renderer-CldjJmRR.mjs} +3 -3
- package/dist/{renderer-HhJPFidU.mjs → renderer-CoC64eam.mjs} +5 -5
- package/dist/{renderer-HhJPFidU.mjs.map → renderer-CoC64eam.mjs.map} +1 -1
- package/dist/renderer-Cpd6TvTC.mjs +5 -0
- package/dist/{renderer-DLaUT6JZ.mjs → renderer-Cv9CKKWG.mjs} +4 -4
- package/dist/{renderer-DLaUT6JZ.mjs.map → renderer-Cv9CKKWG.mjs.map} +1 -1
- package/dist/renderer-CzgcZXKH.mjs +3 -0
- package/dist/{renderer-DCMoBppL.mjs → renderer-D-GWBoVT.mjs} +3 -3
- package/dist/{renderer-DCMoBppL.mjs.map → renderer-D-GWBoVT.mjs.map} +1 -1
- package/dist/{renderer-C3CGYjrC.mjs → renderer-D-mX1EVA.mjs} +5 -5
- package/dist/{renderer-C3CGYjrC.mjs.map → renderer-D-mX1EVA.mjs.map} +1 -1
- package/dist/{renderer-C2kFIZ4r.mjs → renderer-D0h1hTOo.mjs} +4 -4
- package/dist/{renderer-C2kFIZ4r.mjs.map → renderer-D0h1hTOo.mjs.map} +1 -1
- package/dist/{renderer-C_gR2H3R.mjs → renderer-D0xM67cK.mjs} +3 -3
- package/dist/{renderer-C_gR2H3R.mjs.map → renderer-D0xM67cK.mjs.map} +1 -1
- package/dist/renderer-D3ziOPhX.mjs +5 -0
- package/dist/renderer-D5yp74NL.mjs +3 -0
- package/dist/{renderer-BTd6tFcS.mjs → renderer-DCrKEVjb.mjs} +5 -5
- package/dist/{renderer-BTd6tFcS.mjs.map → renderer-DCrKEVjb.mjs.map} +1 -1
- package/dist/{renderer-Dak_wVh9.mjs → renderer-DGOMfyh8.mjs} +2 -2
- package/dist/{renderer-Dak_wVh9.mjs.map → renderer-DGOMfyh8.mjs.map} +1 -1
- package/dist/renderer-DKJOon6y.d.mts +1 -0
- package/dist/renderer-DL-phtL5.mjs +5 -0
- package/dist/{renderer-uA0UCxjA.mjs → renderer-DNynPM6X.mjs} +4 -4
- package/dist/{renderer-uA0UCxjA.mjs.map → renderer-DNynPM6X.mjs.map} +1 -1
- package/dist/renderer-DSnmYnHg.mjs +5 -0
- package/dist/renderer-DUGfsT-E.mjs +5 -0
- package/dist/renderer-DW5af9x1.mjs +5 -0
- package/dist/{renderer-CMCmljb0.mjs → renderer-DWYmJSrl.mjs} +3 -3
- package/dist/{renderer-CMCmljb0.mjs.map → renderer-DWYmJSrl.mjs.map} +1 -1
- package/dist/renderer-DYMrol1t.mjs +5 -0
- package/dist/{renderer-CGpi8CDT.mjs → renderer-DYeNNc_G.mjs} +4 -4
- package/dist/{renderer-CGpi8CDT.mjs.map → renderer-DYeNNc_G.mjs.map} +1 -1
- package/dist/{renderer-DKFaVaRJ.mjs → renderer-DYlx7VHo.mjs} +4 -4
- package/dist/{renderer-DKFaVaRJ.mjs.map → renderer-DYlx7VHo.mjs.map} +1 -1
- package/dist/{renderer-DZIxduEt.mjs → renderer-D_m6Qbsi.mjs} +3 -3
- package/dist/{renderer-DZIxduEt.mjs.map → renderer-D_m6Qbsi.mjs.map} +1 -1
- package/dist/renderer-DekeUHaz.mjs +5 -0
- package/dist/{renderer-snjhPaP-.mjs → renderer-DhGZ41hQ.mjs} +4 -4
- package/dist/{renderer-snjhPaP-.mjs.map → renderer-DhGZ41hQ.mjs.map} +1 -1
- package/dist/{renderer-BXGuCnCJ.mjs → renderer-DiZkZ0Pr.mjs} +4 -4
- package/dist/{renderer-BXGuCnCJ.mjs.map → renderer-DiZkZ0Pr.mjs.map} +1 -1
- package/dist/{renderer-BBjkX0Vt.mjs → renderer-Dm57W73p.mjs} +3 -3
- package/dist/renderer-Dt5uyJdZ.mjs +5 -0
- package/dist/{renderer-DwH5e3hx.mjs → renderer-DtFZbE1j.mjs} +3 -3
- package/dist/{renderer-Bxiiar50.mjs → renderer-DvHi_wXE.mjs} +4 -4
- package/dist/{renderer-Bxiiar50.mjs.map → renderer-DvHi_wXE.mjs.map} +1 -1
- package/dist/{renderer-DaLy1dFA.mjs → renderer-Dv_iRIyx.mjs} +21 -21
- package/dist/renderer-Dv_iRIyx.mjs.map +1 -0
- package/dist/renderer-DwLQAnaK.mjs +5 -0
- package/dist/{renderer-qVJdxbXB.mjs → renderer-DzON3wDZ.mjs} +4 -4
- package/dist/{renderer-qVJdxbXB.mjs.map → renderer-DzON3wDZ.mjs.map} +1 -1
- package/dist/{renderer-Dj54y3h3.mjs → renderer-GIlQ9lZq.mjs} +3 -3
- package/dist/{renderer-Dj54y3h3.mjs.map → renderer-GIlQ9lZq.mjs.map} +1 -1
- package/dist/{renderer-b0H3oDae.mjs → renderer-HKv5cBdp.mjs} +3 -3
- package/dist/{renderer-b0H3oDae.mjs.map → renderer-HKv5cBdp.mjs.map} +1 -1
- package/dist/renderer-IXQP2CWM.mjs +5 -0
- package/dist/renderer-K-Pkw63O.mjs +5 -0
- package/dist/renderer-MPw2KH9P.mjs +5 -0
- package/dist/{renderer-t1sXDiqm.mjs → renderer-QbSrnPZU.mjs} +3 -3
- package/dist/{renderer-t1sXDiqm.mjs.map → renderer-QbSrnPZU.mjs.map} +1 -1
- package/dist/renderer-RPu8RMav.mjs +5 -0
- package/dist/{renderer-Dp9FQKVP.mjs → renderer-TfeohPxt.mjs} +5 -5
- package/dist/{renderer-Dp9FQKVP.mjs.map → renderer-TfeohPxt.mjs.map} +1 -1
- package/dist/{renderer-BzTj_CeK.mjs → renderer-Y1kjtOto.mjs} +4 -4
- package/dist/{renderer-BzTj_CeK.mjs.map → renderer-Y1kjtOto.mjs.map} +1 -1
- package/dist/{renderer-LrAldCWN.mjs → renderer-YONlI6W-.mjs} +5 -5
- package/dist/{renderer-LrAldCWN.mjs.map → renderer-YONlI6W-.mjs.map} +1 -1
- package/dist/{renderer-tRi3KNoG.mjs → renderer-_J9JcCMR.mjs} +5 -5
- package/dist/{renderer-tRi3KNoG.mjs.map → renderer-_J9JcCMR.mjs.map} +1 -1
- package/dist/renderer-dCqxd5N2.mjs +5 -0
- package/dist/{renderer-CcmxR6Fy.d.mts → renderer-fG8Jy8Rx.d.mts} +2 -2
- package/dist/{renderer-CcmxR6Fy.d.mts.map → renderer-fG8Jy8Rx.d.mts.map} +1 -1
- package/dist/renderer-lhjmE-Fp.mjs +5 -0
- package/dist/{renderer-TiaHrU5z.mjs → renderer-mDBoz0zT.mjs} +5 -5
- package/dist/{renderer-TiaHrU5z.mjs.map → renderer-mDBoz0zT.mjs.map} +1 -1
- package/dist/{renderer-smP1F57W.mjs → renderer-pn52dzZz.mjs} +4 -4
- package/dist/{renderer-smP1F57W.mjs.map → renderer-pn52dzZz.mjs.map} +1 -1
- package/dist/renderer-u9cmBuvM.mjs +5 -0
- package/dist/{renderer-CNpq7rL-.mjs → renderer-uER8kn7f.mjs} +3 -3
- package/dist/{renderer-CNpq7rL-.mjs.map → renderer-uER8kn7f.mjs.map} +1 -1
- package/dist/{renderer-sMFJtt_H.mjs → renderer-uzU6dsdR.mjs} +3 -3
- package/dist/{renderer-sMFJtt_H.mjs.map → renderer-uzU6dsdR.mjs.map} +1 -1
- package/dist/renderer-vH12jcpz.mjs +5 -0
- package/dist/{renderer-oBgCEqaM.mjs → renderer-yNWYqvvq.mjs} +4 -4
- package/dist/{renderer-oBgCEqaM.mjs.map → renderer-yNWYqvvq.mjs.map} +1 -1
- package/dist/{renderer-Dy1xQOTu.mjs → renderer-zLi2qFGT.mjs} +4 -4
- package/dist/{renderer-Dy1xQOTu.mjs.map → renderer-zLi2qFGT.mjs.map} +1 -1
- package/dist/{renderers-CP8CFWDs-DWRjjeUg.mjs → renderers-CP8CFWDs-BufiCyn7.mjs} +4 -4
- package/dist/{renderers-CP8CFWDs-DWRjjeUg.mjs.map → renderers-CP8CFWDs-BufiCyn7.mjs.map} +1 -1
- package/dist/sam/index.d.mts +3 -3
- package/dist/sam/index.mjs +1 -1
- package/dist/signals/index.d.mts +7 -7
- package/dist/signals/index.mjs +8 -8
- package/dist/{signals-BfJ1aqpT.mjs → signals-tiho_9fp.mjs} +4 -4
- package/dist/{signals-BfJ1aqpT.mjs.map → signals-tiho_9fp.mjs.map} +1 -1
- package/dist/{src-BU6vm9sP-DFJ3phW0.mjs → src-BU6vm9sP-DdTHmCr4.mjs} +3 -3
- package/dist/{src-BU6vm9sP-DFJ3phW0.mjs.map → src-BU6vm9sP-DdTHmCr4.mjs.map} +1 -1
- package/dist/{src-D7M8VTzv.mjs → src-DrP7fGJX.mjs} +41 -16
- package/dist/{src-D7M8VTzv.mjs.map → src-DrP7fGJX.mjs.map} +1 -1
- package/dist/storage/index.d.mts +206 -0
- package/dist/storage/index.d.mts.map +1 -0
- package/dist/storage/index.mjs +3 -0
- package/package.json +67 -59
- package/dist/audio-afTBdB3U.d.mts.map +0 -1
- package/dist/cloud-COid1Ipa.mjs.map +0 -1
- package/dist/dist-B-OPY7Cs.mjs.map +0 -1
- package/dist/dist-BSqeChht.mjs.map +0 -1
- package/dist/index-BNClElng.d.mts.map +0 -1
- package/dist/index-CTv9ZieD.d.mts.map +0 -1
- package/dist/index-CdCrae-I.d.mts.map +0 -1
- package/dist/index-Fliv2Z-w.d.mts.map +0 -1
- package/dist/index-gOVtTm-P.d.mts.map +0 -1
- package/dist/preview-BUtt481A.mjs.map +0 -1
- package/dist/preview-engine/chunk-5SLBE2FX.mjs +0 -1
- package/dist/preview-engine/chunk-74J4DJQA.mjs +0 -1
- package/dist/preview-engine/chunk-KIPXBOYG.mjs +0 -1974
- package/dist/preview-engine/chunk-P4Y3PMJF.mjs +0 -1
- package/dist/preview-engine/chunk-SE2C623Z.mjs +0 -5
- package/dist/preview-engine/chunk-UKZVUYB6.mjs +0 -483
- package/dist/preview-engine/renderers-PSBTV2DO.mjs +0 -228
- package/dist/preview-engine/renderers-TEKHQHCL.mjs +0 -1
- package/dist/preview-engine/renderers-U3RLYFCN.mjs +0 -1
- package/dist/preview-engine/renderers-V5HM6PZ2.mjs +0 -1
- package/dist/preview-engine/renderers-ZGX3A3QZ.mjs +0 -1
- package/dist/program-Cvv_nb9T.mjs.map +0 -1
- package/dist/renderer--RJepuOy.mjs +0 -5
- package/dist/renderer-B1U6YRRV.d.mts +0 -117
- package/dist/renderer-B1U6YRRV.d.mts.map +0 -1
- package/dist/renderer-B4NFnaty.mjs +0 -5
- package/dist/renderer-B6g4ts0e.mjs +0 -5
- package/dist/renderer-BGoAr-tl.mjs +0 -5
- package/dist/renderer-BSOdBgdE.mjs +0 -5
- package/dist/renderer-BU6O0fpM.mjs +0 -5
- package/dist/renderer-BZ97iidG.mjs +0 -5
- package/dist/renderer-B_Klh1VT.mjs +0 -5
- package/dist/renderer-BaWQM1y-.mjs +0 -5
- package/dist/renderer-Bc0jvAj0.mjs +0 -5
- package/dist/renderer-Bd-NuU3M.mjs +0 -3
- package/dist/renderer-Bm077kZ6.mjs +0 -5
- package/dist/renderer-BtzE_e_Y.mjs +0 -5
- package/dist/renderer-C225eCAo.mjs +0 -5
- package/dist/renderer-CC4fhNup.mjs +0 -3
- package/dist/renderer-CLXdR4vz.mjs +0 -5
- package/dist/renderer-CszM8B3C.mjs +0 -5
- package/dist/renderer-Ctp8ZYfk.mjs +0 -5
- package/dist/renderer-CxQdSp8I.mjs +0 -5
- package/dist/renderer-D3YbHjRG.mjs.map +0 -1
- package/dist/renderer-D4GMRtDd.mjs +0 -6
- package/dist/renderer-DEsGIvTZ.mjs +0 -5
- package/dist/renderer-DIaUQ0EP.mjs +0 -5
- package/dist/renderer-DLjqcNzQ.mjs +0 -5
- package/dist/renderer-DMuQZa51.mjs +0 -5
- package/dist/renderer-DOgi2aF2.mjs +0 -5
- package/dist/renderer-DSh7cvi4.mjs +0 -5
- package/dist/renderer-DV1LVBBP.mjs +0 -5
- package/dist/renderer-DaLy1dFA.mjs.map +0 -1
- package/dist/renderer-Dhrj2bJz.mjs +0 -5
- package/dist/renderer-DoFUu1R4.mjs +0 -5
- package/dist/renderer-DsydX3cx.mjs +0 -5
- package/dist/renderer-DxVSoeYi.mjs +0 -5
- package/dist/renderer-Nc9bHb0n.mjs +0 -5
- package/dist/renderer-TFaSD2Db.mjs +0 -5
- package/dist/renderer-Z61ctppe.mjs +0 -5
- package/dist/renderer-awXf3sNS.mjs +0 -5
- package/dist/renderer-cHT28oYI.mjs +0 -5
- package/dist/renderer-g7Y3bFot.mjs +0 -5
- package/dist/renderer-qVv0OzVc.mjs +0 -5
- /package/dist/{chunk-W71TSjRM.mjs → chunk-DOL2i2sR.mjs} +0 -0
- /package/dist/{renderer-B6rZUBwE.mjs → renderer-Co2YqWX0.mjs} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
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-CiTgmfUw.mjs";
|
|
2
|
+
import { appendFileSync, createWriteStream, existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
+
import path, { join, relative, resolve, sep } from "node:path";
|
|
3
4
|
import fs$1 from "node:fs/promises";
|
|
4
5
|
import { execFileSync } from "node:child_process";
|
|
5
6
|
import { Readable } from "node:stream";
|
|
@@ -28,6 +29,9 @@ import { pipeline } from "node:stream/promises";
|
|
|
28
29
|
* A named render is what `framefields render film --cloud`, `framefields
|
|
29
30
|
* check film`, `renderCloud({ render: "film" })` and the dashboard's New
|
|
30
31
|
* render dialog pick, so nobody chooses files and exports by hand.
|
|
32
|
+
*
|
|
33
|
+
* `storage` and `assets` pin media by content on an S3-compatible bucket
|
|
34
|
+
* (`framefields assets`; the format lives in `@framefields/storage`).
|
|
31
35
|
*/
|
|
32
36
|
const CONFIG_FILE = "framefields.json";
|
|
33
37
|
const RENDER_NAME = /^[A-Za-z0-9][\w.-]{0,63}$/;
|
|
@@ -56,14 +60,17 @@ function readConfig(cwd) {
|
|
|
56
60
|
throw new Error(`${CONFIG_FILE} is not valid JSON: ${err.message}`);
|
|
57
61
|
}
|
|
58
62
|
if (!isRecord(raw)) throw new Error(`${CONFIG_FILE} must be a JSON object`);
|
|
59
|
-
const { components, fonts, renders } = raw;
|
|
63
|
+
const { components, fonts, renders, storage, assets } = raw;
|
|
60
64
|
if (components !== void 0 && typeof components !== "string") throw new Error(`${CONFIG_FILE}: "components" must be a directory path`);
|
|
61
65
|
if (fonts !== void 0 && (!isRecord(fonts) || Object.values(fonts).some((v) => typeof v !== "string"))) throw new Error(`${CONFIG_FILE}: "fonts" must map roles to font file paths, e.g. { "emoji": "assets/fonts/NotoColorEmoji.ttf" }`);
|
|
66
|
+
const parsedStorage = storage === void 0 ? void 0 : parseStorage(storage);
|
|
62
67
|
return {
|
|
63
68
|
config: {
|
|
64
69
|
...raw,
|
|
65
70
|
components: components ?? fallback,
|
|
66
|
-
...renders !== void 0 && { renders: parseRenders(renders) }
|
|
71
|
+
...renders !== void 0 && { renders: parseRenders(renders) },
|
|
72
|
+
...parsedStorage && { storage: parsedStorage },
|
|
73
|
+
...assets !== void 0 && { assets: parseAssets(assets, parsedStorage) }
|
|
67
74
|
},
|
|
68
75
|
saved: components !== void 0
|
|
69
76
|
};
|
|
@@ -119,6 +126,278 @@ function isRelativePath(value) {
|
|
|
119
126
|
return typeof value === "string" && value.length > 0 && !value.startsWith("/") && !value.split(/[/\\]/).includes("..");
|
|
120
127
|
}
|
|
121
128
|
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/cli/assets.ts
|
|
131
|
+
/**
|
|
132
|
+
* `framefields assets`: media kept out of git, on an S3-compatible bucket
|
|
133
|
+
* (R2, S3, B2, MinIO), pinned by content in `framefields.json`.
|
|
134
|
+
*
|
|
135
|
+
* add <path...> hash, upload what the bucket lacks, record, gitignore
|
|
136
|
+
* push upload recorded assets the bucket lacks
|
|
137
|
+
* pull download missing assets, verified byte for byte
|
|
138
|
+
* status which assets are here, missing, or changed
|
|
139
|
+
*
|
|
140
|
+
* Reads need no keys when the remote has a `publicUrl` (a custom domain or
|
|
141
|
+
* CDN in front of the bucket); otherwise they're signed with the remote's
|
|
142
|
+
* keys. Cloud renders get signed URLs for private assets from the CLI, so
|
|
143
|
+
* the keys never leave the machine.
|
|
144
|
+
*/
|
|
145
|
+
var AssetsError = class extends Error {
|
|
146
|
+
name = "AssetsError";
|
|
147
|
+
constructor(message, code) {
|
|
148
|
+
super(message);
|
|
149
|
+
this.code = code;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
/** Hashes and uploads files (folders: every file in them), and records them. */
|
|
153
|
+
async function addAssets(paths, options) {
|
|
154
|
+
const { cwd } = options;
|
|
155
|
+
const { config } = readConfig(cwd);
|
|
156
|
+
const { name, remote } = pickRemote(config.storage, options.remote);
|
|
157
|
+
const bucket = openBucket(config.storage, name, options);
|
|
158
|
+
const files = paths.flatMap((p) => expand(cwd, p));
|
|
159
|
+
if (files.length === 0) throw new AssetsError(`No files in ${paths.join(", ")}.`, "not_found");
|
|
160
|
+
const added = [];
|
|
161
|
+
const assets = { ...config.assets };
|
|
162
|
+
for (const file of files) {
|
|
163
|
+
const digest = await hashFile(join(cwd, file));
|
|
164
|
+
const uploaded = !await bucket.has(digest.sha256, digest.size);
|
|
165
|
+
if (uploaded) await upload(bucket, cwd, file, digest, options.log);
|
|
166
|
+
const isDefault = name === pickRemote(config.storage).name;
|
|
167
|
+
assets[file] = {
|
|
168
|
+
...digest,
|
|
169
|
+
...!isDefault && { remote: name }
|
|
170
|
+
};
|
|
171
|
+
added.push({
|
|
172
|
+
path: file,
|
|
173
|
+
size: digest.size,
|
|
174
|
+
uploaded
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
writeConfig(cwd, {
|
|
178
|
+
...config,
|
|
179
|
+
assets: sortKeys(assets)
|
|
180
|
+
});
|
|
181
|
+
ignore(cwd, files);
|
|
182
|
+
const tracked = trackedByGit(cwd, files);
|
|
183
|
+
if (tracked.length) options.log?.(`Already committed to git: ${tracked.join(", ")}. Stop tracking them with \`git rm --cached ${tracked.join(" ")}\` (the files stay here).`);
|
|
184
|
+
if (remote.publicUrl === void 0) options.log?.(`${name} has no publicUrl: cloud renders from the CLI sign reads, dashboard renders can't read it.`);
|
|
185
|
+
return added;
|
|
186
|
+
}
|
|
187
|
+
/** Uploads every recorded asset its bucket lacks, from the local file. */
|
|
188
|
+
async function pushAssets(options) {
|
|
189
|
+
const { config } = readConfig(options.cwd);
|
|
190
|
+
const uploaded = [];
|
|
191
|
+
const present = [];
|
|
192
|
+
const problems = [];
|
|
193
|
+
for (const [path$1, entry] of storedAssets(config.assets)) {
|
|
194
|
+
const bucket = openBucket(config.storage, entry.remote, options);
|
|
195
|
+
if (await bucket.has(entry.sha256, entry.size)) {
|
|
196
|
+
present.push(path$1);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const state = await localState(options.cwd, path$1, entry);
|
|
200
|
+
if (state !== "ok") {
|
|
201
|
+
problems.push(`${path$1} (${state} here)`);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
await upload(bucket, options.cwd, path$1, entry, options.log);
|
|
205
|
+
uploaded.push(path$1);
|
|
206
|
+
}
|
|
207
|
+
if (problems.length) throw new AssetsError(`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\`.`, "not_uploaded");
|
|
208
|
+
return {
|
|
209
|
+
uploaded,
|
|
210
|
+
present
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Downloads every asset that's missing here. Files changed locally are
|
|
215
|
+
* left alone (and reported) unless `overwrite`.
|
|
216
|
+
*/
|
|
217
|
+
async function pullAssets(options) {
|
|
218
|
+
const { config } = readConfig(options.cwd);
|
|
219
|
+
const result = {
|
|
220
|
+
downloaded: [],
|
|
221
|
+
present: [],
|
|
222
|
+
changed: []
|
|
223
|
+
};
|
|
224
|
+
for (const [path$1, entry] of Object.entries(config.assets ?? {})) {
|
|
225
|
+
const state = await localState(options.cwd, path$1, entry);
|
|
226
|
+
if (state === "ok") {
|
|
227
|
+
result.present.push(path$1);
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (state === "changed" && !options.overwrite) {
|
|
231
|
+
result.changed.push(path$1);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const url = await readableUrl(entry, config.storage, options);
|
|
235
|
+
options.log?.(`Downloading ${path$1} (${megabytes(entry.size)})`);
|
|
236
|
+
await downloadVerified(url, join(options.cwd, path$1), entry, {
|
|
237
|
+
fetch: options.fetch,
|
|
238
|
+
signal: options.signal
|
|
239
|
+
});
|
|
240
|
+
result.downloaded.push(path$1);
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
/** Each recorded asset's state here: present and matching, missing, or changed. */
|
|
245
|
+
async function assetStatus(cwd) {
|
|
246
|
+
const { config } = readConfig(cwd);
|
|
247
|
+
return Promise.all(Object.entries(config.assets ?? {}).map(async ([path$1, entry]) => ({
|
|
248
|
+
path: path$1,
|
|
249
|
+
size: entry.size,
|
|
250
|
+
state: await localState(cwd, path$1, entry)
|
|
251
|
+
})));
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Before a cloud render: uploads assets the bucket lacks (when there are
|
|
255
|
+
* keys), checks public ones are reachable, and signs reads of private ones.
|
|
256
|
+
* Returns the signed URLs by sha256, for the render request.
|
|
257
|
+
*/
|
|
258
|
+
async function prepareCloudAssets(options) {
|
|
259
|
+
const { config } = readConfig(options.cwd);
|
|
260
|
+
const signed = {};
|
|
261
|
+
const missing = [];
|
|
262
|
+
for (const [path$1, entry] of storedAssets(config.assets)) {
|
|
263
|
+
const { name, remote } = pickRemote(config.storage, entry.remote);
|
|
264
|
+
const keys = credentialsFromEnv(name, options.env);
|
|
265
|
+
if (!keys) {
|
|
266
|
+
if (!remote.publicUrl) throw noCredentials(name, path$1);
|
|
267
|
+
if (!await reachable(readUrl(entry, config.storage), options.fetch)) missing.push(path$1);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const bucket = new Bucket(remote, keys, { fetch: options.fetch });
|
|
271
|
+
if (!await bucket.has(entry.sha256, entry.size)) {
|
|
272
|
+
if (await localState(options.cwd, path$1, entry) !== "ok") {
|
|
273
|
+
missing.push(path$1);
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
await upload(bucket, options.cwd, path$1, entry, options.log);
|
|
277
|
+
}
|
|
278
|
+
if (!remote.publicUrl) signed[entry.sha256] = await bucket.presign(entry.sha256, options.expiresSec ?? 86400);
|
|
279
|
+
}
|
|
280
|
+
if (missing.length) throw new AssetsError(`Not on the bucket: ${missing.join(", ")}. Run \`framefields assets push\` from a machine that has them (and the remote's keys).`, "not_uploaded");
|
|
281
|
+
return signed;
|
|
282
|
+
}
|
|
283
|
+
/** Assets kept on a remote (not pinned to a fixed `url`). */
|
|
284
|
+
function storedAssets(assets) {
|
|
285
|
+
return Object.entries(assets ?? {}).filter(([, entry]) => !entry.url);
|
|
286
|
+
}
|
|
287
|
+
async function localState(cwd, path$1, entry) {
|
|
288
|
+
const file = join(cwd, path$1);
|
|
289
|
+
if (!existsSync(file)) return "missing";
|
|
290
|
+
if (statSync(file).size !== entry.size) return "changed";
|
|
291
|
+
return (await hashFile(file)).sha256 === entry.sha256 ? "ok" : "changed";
|
|
292
|
+
}
|
|
293
|
+
async function readableUrl(entry, storage, options) {
|
|
294
|
+
const url = readUrl(entry, storage);
|
|
295
|
+
if (url) return url;
|
|
296
|
+
return openBucket(storage, entry.remote, options).presign(entry.sha256, 3600);
|
|
297
|
+
}
|
|
298
|
+
function openBucket(storage, remoteName, options) {
|
|
299
|
+
const { name, remote } = pickRemote(storage, remoteName);
|
|
300
|
+
const keys = credentialsFromEnv(name, options.env);
|
|
301
|
+
if (!keys) throw noCredentials(name);
|
|
302
|
+
return new Bucket(remote, keys, { fetch: options.fetch });
|
|
303
|
+
}
|
|
304
|
+
function noCredentials(remote, path$1) {
|
|
305
|
+
const [id, secret] = credentialEnvNames(remote);
|
|
306
|
+
return new AssetsError(`${path$1 ? `${path$1} is on ${remote}, which` : `Remote ${remote}`} needs keys: set ${id} and ${secret} (or AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)${path$1 ? ", or give it a publicUrl" : ""}.`, "no_credentials");
|
|
307
|
+
}
|
|
308
|
+
async function upload(bucket, cwd, path$1, digest, log) {
|
|
309
|
+
log?.(`Uploading ${path$1} (${megabytes(digest.size)})`);
|
|
310
|
+
let shown = 0;
|
|
311
|
+
await bucket.upload(join(cwd, path$1), digest, ({ sent, total }) => {
|
|
312
|
+
const percent = Math.floor(sent / total * 10) * 10;
|
|
313
|
+
if (total > 64e6 && percent > shown && percent < 100) {
|
|
314
|
+
shown = percent;
|
|
315
|
+
log?.(` ${percent}%`);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
async function reachable(url, fetchImpl = fetch) {
|
|
320
|
+
return (await fetchImpl(url, { method: "HEAD" }).catch(() => void 0))?.ok ?? false;
|
|
321
|
+
}
|
|
322
|
+
/** Project-relative POSIX paths of `path`, or of every file under it. */
|
|
323
|
+
function expand(cwd, path$1) {
|
|
324
|
+
const abs = resolve(cwd, path$1);
|
|
325
|
+
const rel = relative(cwd, abs).split(sep).join("/");
|
|
326
|
+
if (!isAssetPath(rel) || rel.startsWith("../")) throw new AssetsError(`${path$1} is outside the project.`, "outside_project");
|
|
327
|
+
if (!existsSync(abs)) throw new AssetsError(`${path$1} does not exist.`, "not_found");
|
|
328
|
+
if (!statSync(abs).isDirectory()) return [rel];
|
|
329
|
+
return readdirSync(abs, { withFileTypes: true }).filter((d) => !d.name.startsWith(".")).flatMap((d) => expand(cwd, `${rel}/${d.name}`)).sort();
|
|
330
|
+
}
|
|
331
|
+
const IGNORE_HEADER = "# framefields assets: on the bucket, pinned in framefields.json";
|
|
332
|
+
/** Adds the files to .gitignore, under one marked block. */
|
|
333
|
+
function ignore(cwd, files) {
|
|
334
|
+
const file = join(cwd, ".gitignore");
|
|
335
|
+
const text = existsSync(file) ? readFileSync(file, "utf8") : "";
|
|
336
|
+
const lines = new Set(text.split("\n"));
|
|
337
|
+
const fresh = files.map((f) => `/${f}`).filter((l) => !lines.has(l));
|
|
338
|
+
if (fresh.length === 0) return;
|
|
339
|
+
const header = lines.has(IGNORE_HEADER) ? [] : [IGNORE_HEADER];
|
|
340
|
+
appendFileSync(file, `${text && !text.endsWith("\n") ? "\n" : ""}${[...header, ...fresh].join("\n")}\n`);
|
|
341
|
+
}
|
|
342
|
+
function trackedByGit(cwd, files) {
|
|
343
|
+
try {
|
|
344
|
+
return execFileSync("git", [
|
|
345
|
+
"ls-files",
|
|
346
|
+
"--",
|
|
347
|
+
...files
|
|
348
|
+
], {
|
|
349
|
+
cwd,
|
|
350
|
+
encoding: "utf8",
|
|
351
|
+
stdio: [
|
|
352
|
+
"ignore",
|
|
353
|
+
"pipe",
|
|
354
|
+
"ignore"
|
|
355
|
+
]
|
|
356
|
+
}).split("\n").filter(Boolean);
|
|
357
|
+
} catch {
|
|
358
|
+
return [];
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function sortKeys(assets) {
|
|
362
|
+
return Object.fromEntries(Object.entries(assets).sort(([a], [b]) => a.localeCompare(b)));
|
|
363
|
+
}
|
|
364
|
+
function megabytes(bytes) {
|
|
365
|
+
return `${(bytes / 1e6).toFixed(bytes < 1e7 ? 1 : 0)} MB`;
|
|
366
|
+
}
|
|
367
|
+
const ASSETS_USAGE = `Usage: framefields assets add <path...> [--remote <name>]
|
|
368
|
+
framefields assets push | pull [--overwrite] | status [--json]
|
|
369
|
+
`;
|
|
370
|
+
/** The `framefields assets` command. */
|
|
371
|
+
async function runAssets([sub, ...paths], options) {
|
|
372
|
+
const log = options.log ?? (() => {});
|
|
373
|
+
if (sub === "add" && paths.length > 0) {
|
|
374
|
+
const added = await addAssets(paths, options);
|
|
375
|
+
const sent = added.filter((a) => a.uploaded).length;
|
|
376
|
+
log(`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.`);
|
|
377
|
+
return 0;
|
|
378
|
+
}
|
|
379
|
+
if (sub === "push") {
|
|
380
|
+
const { uploaded, present } = await pushAssets(options);
|
|
381
|
+
log(`Uploaded ${uploaded.length}; ${present.length} already on the bucket.`);
|
|
382
|
+
return 0;
|
|
383
|
+
}
|
|
384
|
+
if (sub === "pull") {
|
|
385
|
+
const { downloaded, present, changed } = await pullAssets(options);
|
|
386
|
+
log(`Downloaded ${downloaded.length}; ${present.length} already here.`);
|
|
387
|
+
if (changed.length) log(`Changed here, left alone: ${changed.join(", ")}. \`framefields assets add\` records them, --overwrite restores them.`);
|
|
388
|
+
return changed.length ? 1 : 0;
|
|
389
|
+
}
|
|
390
|
+
if (sub === "status") {
|
|
391
|
+
const entries = await assetStatus(options.cwd);
|
|
392
|
+
if (options.json) log(JSON.stringify({ assets: entries }));
|
|
393
|
+
else if (entries.length === 0) log(`No assets in ${CONFIG_FILE}.`);
|
|
394
|
+
else for (const e of entries) log(`${e.state.padEnd(8)} ${e.path} (${megabytes(e.size)})`);
|
|
395
|
+
return entries.some((e) => e.state !== "ok") ? 1 : 0;
|
|
396
|
+
}
|
|
397
|
+
process.stderr.write(ASSETS_USAGE);
|
|
398
|
+
return 2;
|
|
399
|
+
}
|
|
400
|
+
|
|
122
401
|
//#endregion
|
|
123
402
|
//#region src/cloud/git-source.ts
|
|
124
403
|
/**
|
|
@@ -245,8 +524,12 @@ async function renderCloud(options) {
|
|
|
245
524
|
} : resolveGitSource(cwd, o.entry);
|
|
246
525
|
const warn = options.onWarning ?? ((m) => process.stderr.write(`framefields: ${m}\n`));
|
|
247
526
|
for (const w of resolved.warnings) warn(w);
|
|
527
|
+
const assets = await cloudAssets(cwd, options);
|
|
248
528
|
let status = await api.start({
|
|
249
|
-
source:
|
|
529
|
+
source: Object.keys(assets).length ? {
|
|
530
|
+
...resolved.source,
|
|
531
|
+
assets
|
|
532
|
+
} : resolved.source,
|
|
250
533
|
target: {
|
|
251
534
|
entry: resolved.entry,
|
|
252
535
|
export: o.export ?? "buildFilm",
|
|
@@ -285,6 +568,22 @@ async function renderCloud(options) {
|
|
|
285
568
|
return status;
|
|
286
569
|
}
|
|
287
570
|
/**
|
|
571
|
+
* Uploads assets the bucket lacks and signs reads of private ones: the
|
|
572
|
+
* workers download each asset framefields.json pins at the commit.
|
|
573
|
+
*/
|
|
574
|
+
async function cloudAssets(cwd, options) {
|
|
575
|
+
try {
|
|
576
|
+
return await prepareCloudAssets({
|
|
577
|
+
cwd,
|
|
578
|
+
signal: options.signal,
|
|
579
|
+
log: options.onLog ?? ((m) => process.stderr.write(`framefields: ${m}\n`))
|
|
580
|
+
});
|
|
581
|
+
} catch (err) {
|
|
582
|
+
if (err instanceof AssetsError) throw new CloudRenderError(err.message, `assets_${err.code}`);
|
|
583
|
+
throw err;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
288
587
|
* The options with a named render's fields filled in where the caller left
|
|
289
588
|
* them out, plus the name and title the dashboard shows.
|
|
290
589
|
*/
|
|
@@ -382,5 +681,5 @@ function sleep(ms, signal) {
|
|
|
382
681
|
}
|
|
383
682
|
|
|
384
683
|
//#endregion
|
|
385
|
-
export { withNamedRender as a,
|
|
386
|
-
//# sourceMappingURL=cloud-
|
|
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-Cj1TIme8.mjs.map
|
|
@@ -0,0 +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,15 +1,16 @@
|
|
|
1
|
-
import "../chunk-
|
|
2
|
-
import "../index-
|
|
3
|
-
import "../index-
|
|
4
|
-
import "../index-
|
|
5
|
-
import "../renderer-
|
|
6
|
-
import "../
|
|
7
|
-
import
|
|
8
|
-
import "../index-
|
|
9
|
-
import "../
|
|
10
|
-
import "../
|
|
11
|
-
import "../index-
|
|
12
|
-
import "../index-
|
|
13
|
-
import "../index-
|
|
14
|
-
import "../index-
|
|
1
|
+
import "../chunk-DOL2i2sR.mjs";
|
|
2
|
+
import "../index-a6JrbAK0.mjs";
|
|
3
|
+
import "../index-BFTtXosj.mjs";
|
|
4
|
+
import "../index-C2yaponf.mjs";
|
|
5
|
+
import "../renderer-DKJOon6y.mjs";
|
|
6
|
+
import "../index-B08eSpaI.mjs";
|
|
7
|
+
import "../renderer-fG8Jy8Rx.mjs";
|
|
8
|
+
import { $a as withDefaults, $i as exitAnimation, $n as Animatable, $r as ResolvedTarget, Aa as springKeys, Ai as basePropsSchema, Ar as GlyphProps, Ba as targetSchema, Bi as cover, Br as MediaOptions, Ca as rng, Ci as arcPath, Cr as FontNeed, Da as scheduleExpression, Di as bakeFunction, Dr as FrameWindow, Ea as scaleFrames, Ei as audioLevelsSchema, Er as FrameValue, Fa as staggerRanks, Fi as boxPath, Fr as KeyBook, Ga as toPathData, Gi as drawOnKeys, Gr as MotionSize, Ha as themeFrames, Hi as defineMeta, Hr as MotionOptions, Ia as stepExpression, Ii as catmullRom, Ir as LayerStyleConfig, Ja as transparent, Ji as elevationStyle, Jr as ProjectDefaults, Ka as toSeconds, Ki as ease$1, Kr as ParticleOptions, La as supersede, Li as chain, Lr as MOTION_PRESETS, Ma as springTrack, Mi as bind, Mr as GrainOptions, Na as squigglePath, Ni as boilKeys, Nr as HandOptions, Oa as smoothRelease, Oi as bakeSamples, Or as GlyphAnimator, Pa as staggerOffsets, Pi as boundsOf, Pr as Host, Qa as withAlpha, Qi as evaluateGlyphExpression, Qn as Anchor, Qr as ResolvedMotion, Ra as surfaceFill, Ri as constantExpression, Rr as MeasureFn, Sa as resolveTarget, Si as anchorPoint, Sr as ExtrudedTextOptions, Ta as safeArea, Ti as ascending, Tr as FrameContextLike, Ua as themes, Ui as defineTheme, Ur as MotionPreset, Va as textLayout, Vi as defineComponent, Vr as Metrics, Wa as toFrames, Wi as dist, Wr as MotionPresetName, Xa as valueAt, Xi as enterAnimation, Xr as PulseOptions, Ya as typingFrames, Yi as ellipsePath, Yr as PropsOf, Za as windowExpression, Zi as evaluateEase, Zn as AnalyzeOptions, Zr as Rect, _a as quantize, _i as UnitSchedule, _r as CuesOf, aa as holdFirstKeys, ai as StaggerOrder, ar as BakeOptions, ba as resampleBands, bi as after, br as Elevation, ca as last, ci as TargetContext, cr as BuildContext, da as lineShift, di as Theme, dr as ComponentDefaults, ea as findRange, ei as Rgba, eo as within, er as AnimatableMethods, fa as luminance, fi as ThemeInput, fr as ComponentDefinition, ga as pulseKeys, gi as UNIT_INDEX, gr as Cues, ha as parseColor, hi as TrackedObjectLike, hr as Cue, i as analyzeAudio, ia as hashString, ii as Spring, ir as AudioLevels, ja as springSettleFrames, ji as beats, jr as GlyphUnit, ka as springAt, ki as bandEdges, kr as GlyphBox, la as lerp2, li as TargetNode, lr as BuildResult, ma as offsetCues, mi as Track, mr as ComponentMeta, n as bindComponent, na as glyphAnimator, ni as SAFE_INSETS, no as wordRanges, nr as ArrowCurve, oa as inkOn, oi as SyntaxKind, or as BakedKey, pa as mix, pi as ThemeName, pr as ComponentExtras, qa as transformPathData, qi as elevate, qr as Placement, r as z, ra as hashRng, ri as SafeInsets, rr as ArrowGeometry, sa as isLight, si as Target, sr as BaseProps, t as ComponentNode, ta as frameSpan, ti as Rng, to as wobblePoints, tr as ArcPath, ua as linePath, ui as TextLayout, ur as CanvasSize, va as rangeRects, vi as Vec2, vr as CutoutOptions, wa as round, wi as arrowPaths, wr as FontRole, xa as resolveMotion, xi as analyzeChannels, xr as ElevationLevel, ya as rendererChars, yi as WordRange, yr as EaseFn, za as targetPoint, zi as contrastRatio, zr as MeasureOptions } from "../index-CtKUQ2VG.mjs";
|
|
9
|
+
import "../index-BGlaws7-.mjs";
|
|
10
|
+
import "../audio-C4B9p_yq.mjs";
|
|
11
|
+
import "../index-DBh3WphX.mjs";
|
|
12
|
+
import "../index-rtCXNxGO.mjs";
|
|
13
|
+
import "../index-ByhlTwxh.mjs";
|
|
14
|
+
import "../index-DQ1U3HC3.mjs";
|
|
15
|
+
import "../index-CnZhBlob.mjs";
|
|
15
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 };
|