@koda-sl/baker-cli 0.489.0 → 0.490.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/README.md +169 -7
- package/dist/{account-Z65CPOWE.js → account-3H6BZO5H.js} +2 -2
- package/dist/account-IKFDY52P.js +138 -0
- package/dist/account-IKFDY52P.js.map +1 -0
- package/dist/account-assets-LKZVWZAR.js +289 -0
- package/dist/account-assets-LKZVWZAR.js.map +1 -0
- package/dist/account-level-UJOZDVXY.js +608 -0
- package/dist/account-level-UJOZDVXY.js.map +1 -0
- package/dist/{account-writes-4N2MA2ZR.js → account-writes-AE5IJGGW.js} +2 -2
- package/dist/{accounts-UA2ZWRN4.js → accounts-K4INATCW.js} +2 -2
- package/dist/{activities-IQPJPP4B.js → activities-T253KK4Q.js} +4 -4
- package/dist/{ad-group-writes-EUTMPBMK.js → ad-group-writes-VRSBI2Z2.js} +2 -2
- package/dist/{ad-groups-OVPAI5RM.js → ad-groups-IEBVEAMS.js} +6 -6
- package/dist/{ad-writes-DACTYFEO.js → ad-writes-ALV4KFPZ.js} +2 -2
- package/dist/{ads-L65JIKCD.js → ads-CQZHD7FC.js} +7 -7
- package/dist/{ads-G6AS5L7G.js → ads-QIKZ6O2N.js} +5 -5
- package/dist/{ads-HXX2IAFF.js → ads-ZEY72UBN.js} +14 -13
- package/dist/ads-ZEY72UBN.js.map +1 -0
- package/dist/{adsets-LPN6WFGF.js → adsets-5H3MOT3D.js} +15 -14
- package/dist/{adsets-LPN6WFGF.js.map → adsets-5H3MOT3D.js.map} +1 -1
- package/dist/{analytics-QKP3A5F3.js → analytics-ALOZ7ZZ4.js} +1 -1
- package/dist/asset-writes-L5TMKIZC.js +47 -0
- package/dist/audience-writes-X52VG35Y.js +324 -0
- package/dist/audience-writes-X52VG35Y.js.map +1 -0
- package/dist/{audiences-RPLVMO4H.js → audiences-AAZH56WD.js} +2 -2
- package/dist/{audiences-XEZHACKH.js → audiences-X3RLGOVM.js} +12 -6
- package/dist/audiences-X3RLGOVM.js.map +1 -0
- package/dist/{avatars-MXTI74VC.js → avatars-YSFFRHDK.js} +1 -1
- package/dist/{brief-BN4UGUXF.js → brief-7S6XCJIA.js} +15 -15
- package/dist/{businesses-PRRYPR7H.js → businesses-H3HIDQX6.js} +2 -2
- package/dist/{campaign-writes-BAFB5E7A.js → campaign-writes-7ZF57KLH.js} +3 -3
- package/dist/campaign-writes-7ZF57KLH.js.map +1 -0
- package/dist/{campaign-writes-U5LTDTYK.js → campaign-writes-U5PUVSMT.js} +2 -2
- package/dist/{campaigns-4SOLY7OR.js → campaigns-AV6G3AUU.js} +32 -15
- package/dist/campaigns-AV6G3AUU.js.map +1 -0
- package/dist/{campaigns-TFEQTSO3.js → campaigns-JEIKY2M4.js} +6 -6
- package/dist/{campaigns-NR6TNQFN.js → campaigns-VTRMKSAT.js} +5 -5
- package/dist/{canvas-GJAQAVS6.js → canvas-SVJEQO4V.js} +13 -13
- package/dist/{catalog-USZL4SGX.js → catalog-S32MX453.js} +5 -5
- package/dist/{catalogs-A7XMEEEP.js → catalogs-OCVXZLIF.js} +2 -2
- package/dist/catalogs-RXJTZTVX.js +778 -0
- package/dist/catalogs-RXJTZTVX.js.map +1 -0
- package/dist/{chatgpt-4PEWDJKP.js → chatgpt-QVF2FD3E.js} +12 -12
- package/dist/{chats-INN2OHSH.js → chats-QG72JB6Y.js} +22 -8
- package/dist/chats-QG72JB6Y.js.map +1 -0
- package/dist/{check-MMJGFFZS.js → check-SLNHVYGS.js} +4 -4
- package/dist/{chunk-7RBJ2Z7Z.js → chunk-2C7AHPM4.js} +25 -6
- package/dist/chunk-2C7AHPM4.js.map +1 -0
- package/dist/{chunk-KPYDTIAI.js → chunk-2WZI36D3.js} +2 -2
- package/dist/{chunk-FUKDI2UK.js → chunk-3W6G6ARX.js} +2 -2
- package/dist/{chunk-JWSEPW7F.js → chunk-46GWHUKN.js} +2 -2
- package/dist/{chunk-3TZVZXM6.js → chunk-4KJMLYCD.js} +6 -6
- package/dist/{chunk-6JWEGFM5.js → chunk-5C35OW7L.js} +38 -7
- package/dist/chunk-5C35OW7L.js.map +1 -0
- package/dist/chunk-5GQCN2QZ.js +391 -0
- package/dist/chunk-5GQCN2QZ.js.map +1 -0
- package/dist/{chunk-KIGGMKAE.js → chunk-65Y3RCWP.js} +4 -2
- package/dist/chunk-65Y3RCWP.js.map +1 -0
- package/dist/{chunk-R3EKM2P2.js → chunk-6NCJGU6I.js} +5 -5
- package/dist/chunk-A4MVVPJ2.js +4204 -0
- package/dist/chunk-A4MVVPJ2.js.map +1 -0
- package/dist/{chunk-LPXSM2DI.js → chunk-AO45BX6Q.js} +3 -3
- package/dist/{chunk-3UXMQ3K2.js → chunk-AQM4JH62.js} +2 -2
- package/dist/chunk-AQM4JH62.js.map +1 -0
- package/dist/{chunk-NPMAATZG.js → chunk-C7NWUCLQ.js} +2 -2
- package/dist/chunk-CP4P6YKM.js +287 -0
- package/dist/chunk-CP4P6YKM.js.map +1 -0
- package/dist/{chunk-OWA7ZLC4.js → chunk-D4CKCNGW.js} +4 -4
- package/dist/{chunk-H5HDZ7IC.js → chunk-DCBZ5CHZ.js} +4 -4
- package/dist/{chunk-C6EYCD5J.js → chunk-FVHJCERJ.js} +5 -5
- package/dist/{chunk-BITS62MF.js → chunk-G6XKD7QE.js} +2 -2
- package/dist/{chunk-QE3JEJXF.js → chunk-GSZZLW5Q.js} +4 -4
- package/dist/chunk-HLVRHBKL.js +1078 -0
- package/dist/chunk-HLVRHBKL.js.map +1 -0
- package/dist/{chunk-TPANP5A2.js → chunk-JKJQWRLO.js} +2 -2
- package/dist/{chunk-62JQQUAU.js → chunk-JQH5VG6F.js} +2 -2
- package/dist/{chunk-6WXV5GTA.js → chunk-JVH5A3XC.js} +2 -2
- package/dist/{chunk-AVNSH2JE.js → chunk-KOXDXSKN.js} +7 -7
- package/dist/{chunk-2XRMPSEV.js → chunk-LXQB4ZGE.js} +2 -2
- package/dist/{chunk-ZL23HA4N.js → chunk-M6PN3VH6.js} +2 -2
- package/dist/{chunk-TZEVD4Q6.js → chunk-P5FRWPG7.js} +2 -2
- package/dist/{chunk-CSZFZKVX.js → chunk-PQJXIY64.js} +5 -5
- package/dist/{chunk-OP7DNHD2.js → chunk-QTOZ32SU.js} +27 -1
- package/dist/chunk-QTOZ32SU.js.map +1 -0
- package/dist/chunk-SVAB6KV5.js +219 -0
- package/dist/chunk-SVAB6KV5.js.map +1 -0
- package/dist/{chunk-LBO2YAZY.js → chunk-UNX6BS4U.js} +15 -15
- package/dist/{chunk-UWXDNVS5.js → chunk-ZJSGGJ5R.js} +2 -2
- package/dist/cli.js +20 -20
- package/dist/{connect-WBGCBBFJ.js → connect-S54TJ6OV.js} +3 -3
- package/dist/{conversion-writes-JU7Q2MUO.js → conversion-writes-ECZBVY7D.js} +2 -2
- package/dist/{conversions-3ISBR3TS.js → conversions-5QCSCRLI.js} +3 -3
- package/dist/copy-writes-D2RTHAL6.js +167 -0
- package/dist/copy-writes-D2RTHAL6.js.map +1 -0
- package/dist/{creatives-VQO2TKE3.js → creatives-5I3G5YP3.js} +2 -2
- package/dist/{creatives-YJ3CXZQC.js → creatives-MZ6ICNSY.js} +5 -4
- package/dist/{creatives-YJ3CXZQC.js.map → creatives-MZ6ICNSY.js.map} +1 -1
- package/dist/{creatives-S5QUWUL6.js → creatives-PCAGWPW3.js} +10 -10
- package/dist/{critique-5LCG5TYF.js → critique-NRHUPIWF.js} +7 -7
- package/dist/{custom-conversions-YRYE65PU.js → custom-conversions-FIP6ZS34.js} +5 -3
- package/dist/{custom-conversions-YRYE65PU.js.map → custom-conversions-FIP6ZS34.js.map} +1 -1
- package/dist/{draft-Y2QJE2NM.js → draft-34CGWUVA.js} +2 -2
- package/dist/{draft-GPN3HOAG.js → draft-4P3YO67N.js} +9 -5
- package/dist/draft-4P3YO67N.js.map +1 -0
- package/dist/{draft-EWDOIXSH.js → draft-L45PGCYZ.js} +7 -3
- package/dist/draft-L45PGCYZ.js.map +1 -0
- package/dist/engine/index.js +4 -4
- package/dist/{experiment-G3FQVAJU.js → experiment-7N4QFRWV.js} +4 -4
- package/dist/{feedback-CAOZPGTT.js → feedback-O3H42V4I.js} +10 -10
- package/dist/{feedback-record-EXV5H6OS.js → feedback-record-FAPN2GBS.js} +12 -12
- package/dist/{find-EVY4XEIQ.js → find-FSQAEGGF.js} +4 -4
- package/dist/{flows-Z7355RMD.js → flows-T22B77J3.js} +3 -3
- package/dist/{funnel-2B3JXJPX.js → funnel-7OA33VRP.js} +5 -5
- package/dist/{ga4-2BL5YAYN.js → ga4-LPDIBNYP.js} +1 -1
- package/dist/{google-7STODZQR.js → google-5ESVO76E.js} +5 -5
- package/dist/{gsc-UU3T2C6B.js → gsc-FIZTQX3N.js} +1 -1
- package/dist/{history-IQ33J5PB.js → history-QKDYBSYM.js} +2 -2
- package/dist/{icon-GB7UH5RF.js → icon-CSVAZ7NE.js} +4 -4
- package/dist/{ideas-F6CIGTVU.js → ideas-JQT422P7.js} +4 -4
- package/dist/{images-WCKTD6Z2.js → images-WBNWK2ZH.js} +6 -6
- package/dist/{insights-4HT2NAYP.js → insights-YWVJMATY.js} +4 -3
- package/dist/{insights-4HT2NAYP.js.map → insights-YWVJMATY.js.map} +1 -1
- package/dist/{inspiration-XQYHBJY2.js → inspiration-IX5N724J.js} +1 -1
- package/dist/instant-experiences-NQ2GWIWL.js +257 -0
- package/dist/instant-experiences-NQ2GWIWL.js.map +1 -0
- package/dist/{landing-WUILAWDS.js → landing-Y6QCTXCZ.js} +2 -2
- package/dist/leads-THI37ZMD.js +537 -0
- package/dist/leads-THI37ZMD.js.map +1 -0
- package/dist/{learn-CC6Q5IK2.js → learn-3BDZUWDT.js} +5 -5
- package/dist/{linkedin-XKVPSCLV.js → linkedin-UGMAFSGO.js} +2 -2
- package/dist/{locations-YA7NZY44.js → locations-HM56X2MK.js} +2 -2
- package/dist/locations-HM56X2MK.js.map +1 -0
- package/dist/{logo-YSNUUT33.js → logo-VHXH4J6A.js} +3 -3
- package/dist/{make-ED7HBLH3.js → make-W2PYZXYF.js} +39 -39
- package/dist/media-H6B7VDON.js +18 -0
- package/dist/media-H6B7VDON.js.map +1 -0
- package/dist/{media-sources-PEHUMH7C.js → media-sources-EZKAJNVD.js} +1 -1
- package/dist/meta-YHDTGJQ6.js +122 -0
- package/dist/meta-YHDTGJQ6.js.map +1 -0
- package/dist/{options-6FCNFWUF.js → options-NSCZSQ5P.js} +3 -3
- package/dist/page-photos-CXRG4AXV.js +115 -0
- package/dist/page-photos-CXRG4AXV.js.map +1 -0
- package/dist/{pages-FTI44OSH.js → pages-PTWRXAZT.js} +2 -2
- package/dist/{pixels-6IUB3Y3H.js → pixels-MYT3TCHZ.js} +2 -2
- package/dist/{pixels-MBKR4XPX.js → pixels-ZZCQUS3J.js} +2 -2
- package/dist/{preview-V4YBD45S.js → preview-XOXAAPMQ.js} +73 -27
- package/dist/preview-XOXAAPMQ.js.map +1 -0
- package/dist/{rerun-A2XHGFZS.js → rerun-5THJLQQJ.js} +18 -18
- package/dist/{research-BLDY5UWH.js → research-JHDWWFL7.js} +1 -1
- package/dist/rule-writes-6ZCAJDYZ.js +522 -0
- package/dist/rule-writes-6ZCAJDYZ.js.map +1 -0
- package/dist/rules-BMYOY2BM.js +216 -0
- package/dist/rules-BMYOY2BM.js.map +1 -0
- package/dist/{rules-SK5DFFPY.js → rules-YLLFDZEM.js} +3 -3
- package/dist/{rules-add-YQNYSME7.js → rules-add-U2GU4AGP.js} +4 -4
- package/dist/{run-KBN5K7LE.js → run-V5YQB6TH.js} +18 -18
- package/dist/{scaffold-ad-6BN5LWQH.js → scaffold-ad-H4GJOKAW.js} +12 -12
- package/dist/{scaffold-static-ad-VVZRAWBR.js → scaffold-static-ad-2YIFHCTL.js} +25 -25
- package/dist/{scaffold-video-LFIYI4GP.js → scaffold-video-3EJLKR2O.js} +14 -14
- package/dist/{select-QBU6ED4K.js → select-I22NPSIW.js} +9 -9
- package/dist/{set-prompt-TL64CRBQ.js → set-prompt-S75OMQ7L.js} +8 -8
- package/dist/{shared-NDRFKAH7.js → shared-3IBNDEFL.js} +2 -2
- package/dist/{sources-RMNFV4CA.js → sources-VA23PDND.js} +1 -1
- package/dist/{stale-ITFCPOER.js → stale-MHTU2NQJ.js} +8 -8
- package/dist/{stats-RCLQE4HJ.js → stats-ZAGJH4AD.js} +1 -1
- package/dist/{stock-ECRBD7RP.js → stock-6SHHLSKG.js} +5 -5
- package/dist/studies-4NIV4D5Y.js +249 -0
- package/dist/studies-4NIV4D5Y.js.map +1 -0
- package/dist/{studio-MARZ22J2.js → studio-ZLCGXFAN.js} +1 -1
- package/dist/study-writes-L2AA2PGL.js +467 -0
- package/dist/study-writes-L2AA2PGL.js.map +1 -0
- package/dist/{sync-definition-C6ROLKJ4.js → sync-definition-2EBSQA6A.js} +11 -11
- package/dist/{tag-manager-G3LBQZUL.js → tag-manager-3CJ66GKJ.js} +1 -1
- package/dist/targeting-LNDQV4EK.js +759 -0
- package/dist/targeting-LNDQV4EK.js.map +1 -0
- package/dist/{testimonials-YMMA5YWL.js → testimonials-GR6TIS5S.js} +2 -2
- package/dist/{translate-OXVIMYHE.js → translate-GEFUP6KQ.js} +18 -18
- package/dist/{validate-ZS2M5Q3V.js → validate-NOWIOAHE.js} +11 -11
- package/dist/{videos-I6YXFBFT.js → videos-XMTDEHEJ.js} +1 -1
- package/dist/{viewer-check-7ZG7KHEN.js → viewer-check-U4XZMMS7.js} +6 -6
- package/dist/viewer-check-U4XZMMS7.js.map +1 -0
- package/dist/{winning-ads-ABN5OULS.js → winning-ads-QOAYIR5U.js} +1 -1
- package/dist/{write-commands-HCQI4Y27.js → write-commands-PEJBTME6.js} +485 -57
- package/dist/write-commands-PEJBTME6.js.map +1 -0
- package/dist/{x-WK2VQDPF.js → x-VCSMV7T5.js} +4 -4
- package/package.json +1 -1
- package/dist/account-7LUQWY6Q.js +0 -49
- package/dist/account-7LUQWY6Q.js.map +0 -1
- package/dist/ads-HXX2IAFF.js.map +0 -1
- package/dist/audiences-XEZHACKH.js.map +0 -1
- package/dist/campaign-writes-BAFB5E7A.js.map +0 -1
- package/dist/campaigns-4SOLY7OR.js.map +0 -1
- package/dist/chats-INN2OHSH.js.map +0 -1
- package/dist/chunk-3UXMQ3K2.js.map +0 -1
- package/dist/chunk-6JWEGFM5.js.map +0 -1
- package/dist/chunk-7RBJ2Z7Z.js.map +0 -1
- package/dist/chunk-GOJXKIFQ.js +0 -1605
- package/dist/chunk-GOJXKIFQ.js.map +0 -1
- package/dist/chunk-KIGGMKAE.js.map +0 -1
- package/dist/chunk-OP7DNHD2.js.map +0 -1
- package/dist/draft-EWDOIXSH.js.map +0 -1
- package/dist/draft-GPN3HOAG.js.map +0 -1
- package/dist/leads-2XOSAYP4.js +0 -293
- package/dist/leads-2XOSAYP4.js.map +0 -1
- package/dist/locations-YA7NZY44.js.map +0 -1
- package/dist/media-ES2UBGYW.js +0 -15
- package/dist/media-ES2UBGYW.js.map +0 -1
- package/dist/meta-AOIPEDV5.js +0 -69
- package/dist/meta-AOIPEDV5.js.map +0 -1
- package/dist/preview-V4YBD45S.js.map +0 -1
- package/dist/write-commands-HCQI4Y27.js.map +0 -1
- /package/dist/{account-Z65CPOWE.js.map → account-3H6BZO5H.js.map} +0 -0
- /package/dist/{account-writes-4N2MA2ZR.js.map → account-writes-AE5IJGGW.js.map} +0 -0
- /package/dist/{accounts-UA2ZWRN4.js.map → accounts-K4INATCW.js.map} +0 -0
- /package/dist/{activities-IQPJPP4B.js.map → activities-T253KK4Q.js.map} +0 -0
- /package/dist/{ad-group-writes-EUTMPBMK.js.map → ad-group-writes-VRSBI2Z2.js.map} +0 -0
- /package/dist/{ad-groups-OVPAI5RM.js.map → ad-groups-IEBVEAMS.js.map} +0 -0
- /package/dist/{ad-writes-DACTYFEO.js.map → ad-writes-ALV4KFPZ.js.map} +0 -0
- /package/dist/{ads-L65JIKCD.js.map → ads-CQZHD7FC.js.map} +0 -0
- /package/dist/{ads-G6AS5L7G.js.map → ads-QIKZ6O2N.js.map} +0 -0
- /package/dist/{analytics-QKP3A5F3.js.map → analytics-ALOZ7ZZ4.js.map} +0 -0
- /package/dist/{connect-WBGCBBFJ.js.map → asset-writes-L5TMKIZC.js.map} +0 -0
- /package/dist/{audiences-RPLVMO4H.js.map → audiences-AAZH56WD.js.map} +0 -0
- /package/dist/{avatars-MXTI74VC.js.map → avatars-YSFFRHDK.js.map} +0 -0
- /package/dist/{brief-BN4UGUXF.js.map → brief-7S6XCJIA.js.map} +0 -0
- /package/dist/{businesses-PRRYPR7H.js.map → businesses-H3HIDQX6.js.map} +0 -0
- /package/dist/{campaign-writes-U5LTDTYK.js.map → campaign-writes-U5PUVSMT.js.map} +0 -0
- /package/dist/{campaigns-TFEQTSO3.js.map → campaigns-JEIKY2M4.js.map} +0 -0
- /package/dist/{campaigns-NR6TNQFN.js.map → campaigns-VTRMKSAT.js.map} +0 -0
- /package/dist/{canvas-GJAQAVS6.js.map → canvas-SVJEQO4V.js.map} +0 -0
- /package/dist/{catalog-USZL4SGX.js.map → catalog-S32MX453.js.map} +0 -0
- /package/dist/{catalogs-A7XMEEEP.js.map → catalogs-OCVXZLIF.js.map} +0 -0
- /package/dist/{chatgpt-4PEWDJKP.js.map → chatgpt-QVF2FD3E.js.map} +0 -0
- /package/dist/{check-MMJGFFZS.js.map → check-SLNHVYGS.js.map} +0 -0
- /package/dist/{chunk-KPYDTIAI.js.map → chunk-2WZI36D3.js.map} +0 -0
- /package/dist/{chunk-FUKDI2UK.js.map → chunk-3W6G6ARX.js.map} +0 -0
- /package/dist/{chunk-JWSEPW7F.js.map → chunk-46GWHUKN.js.map} +0 -0
- /package/dist/{chunk-3TZVZXM6.js.map → chunk-4KJMLYCD.js.map} +0 -0
- /package/dist/{chunk-R3EKM2P2.js.map → chunk-6NCJGU6I.js.map} +0 -0
- /package/dist/{chunk-LPXSM2DI.js.map → chunk-AO45BX6Q.js.map} +0 -0
- /package/dist/{chunk-NPMAATZG.js.map → chunk-C7NWUCLQ.js.map} +0 -0
- /package/dist/{chunk-OWA7ZLC4.js.map → chunk-D4CKCNGW.js.map} +0 -0
- /package/dist/{chunk-H5HDZ7IC.js.map → chunk-DCBZ5CHZ.js.map} +0 -0
- /package/dist/{chunk-C6EYCD5J.js.map → chunk-FVHJCERJ.js.map} +0 -0
- /package/dist/{chunk-BITS62MF.js.map → chunk-G6XKD7QE.js.map} +0 -0
- /package/dist/{chunk-QE3JEJXF.js.map → chunk-GSZZLW5Q.js.map} +0 -0
- /package/dist/{chunk-TPANP5A2.js.map → chunk-JKJQWRLO.js.map} +0 -0
- /package/dist/{chunk-62JQQUAU.js.map → chunk-JQH5VG6F.js.map} +0 -0
- /package/dist/{chunk-6WXV5GTA.js.map → chunk-JVH5A3XC.js.map} +0 -0
- /package/dist/{chunk-AVNSH2JE.js.map → chunk-KOXDXSKN.js.map} +0 -0
- /package/dist/{chunk-2XRMPSEV.js.map → chunk-LXQB4ZGE.js.map} +0 -0
- /package/dist/{chunk-ZL23HA4N.js.map → chunk-M6PN3VH6.js.map} +0 -0
- /package/dist/{chunk-TZEVD4Q6.js.map → chunk-P5FRWPG7.js.map} +0 -0
- /package/dist/{chunk-CSZFZKVX.js.map → chunk-PQJXIY64.js.map} +0 -0
- /package/dist/{chunk-LBO2YAZY.js.map → chunk-UNX6BS4U.js.map} +0 -0
- /package/dist/{chunk-UWXDNVS5.js.map → chunk-ZJSGGJ5R.js.map} +0 -0
- /package/dist/{ideas-F6CIGTVU.js.map → connect-S54TJ6OV.js.map} +0 -0
- /package/dist/{conversion-writes-JU7Q2MUO.js.map → conversion-writes-ECZBVY7D.js.map} +0 -0
- /package/dist/{conversions-3ISBR3TS.js.map → conversions-5QCSCRLI.js.map} +0 -0
- /package/dist/{creatives-VQO2TKE3.js.map → creatives-5I3G5YP3.js.map} +0 -0
- /package/dist/{creatives-S5QUWUL6.js.map → creatives-PCAGWPW3.js.map} +0 -0
- /package/dist/{critique-5LCG5TYF.js.map → critique-NRHUPIWF.js.map} +0 -0
- /package/dist/{draft-Y2QJE2NM.js.map → draft-34CGWUVA.js.map} +0 -0
- /package/dist/{experiment-G3FQVAJU.js.map → experiment-7N4QFRWV.js.map} +0 -0
- /package/dist/{feedback-CAOZPGTT.js.map → feedback-O3H42V4I.js.map} +0 -0
- /package/dist/{feedback-record-EXV5H6OS.js.map → feedback-record-FAPN2GBS.js.map} +0 -0
- /package/dist/{find-EVY4XEIQ.js.map → find-FSQAEGGF.js.map} +0 -0
- /package/dist/{flows-Z7355RMD.js.map → flows-T22B77J3.js.map} +0 -0
- /package/dist/{funnel-2B3JXJPX.js.map → funnel-7OA33VRP.js.map} +0 -0
- /package/dist/{ga4-2BL5YAYN.js.map → ga4-LPDIBNYP.js.map} +0 -0
- /package/dist/{google-7STODZQR.js.map → google-5ESVO76E.js.map} +0 -0
- /package/dist/{gsc-UU3T2C6B.js.map → gsc-FIZTQX3N.js.map} +0 -0
- /package/dist/{history-IQ33J5PB.js.map → history-QKDYBSYM.js.map} +0 -0
- /package/dist/{icon-GB7UH5RF.js.map → icon-CSVAZ7NE.js.map} +0 -0
- /package/dist/{logo-YSNUUT33.js.map → ideas-JQT422P7.js.map} +0 -0
- /package/dist/{images-WCKTD6Z2.js.map → images-WBNWK2ZH.js.map} +0 -0
- /package/dist/{inspiration-XQYHBJY2.js.map → inspiration-IX5N724J.js.map} +0 -0
- /package/dist/{landing-WUILAWDS.js.map → landing-Y6QCTXCZ.js.map} +0 -0
- /package/dist/{learn-CC6Q5IK2.js.map → learn-3BDZUWDT.js.map} +0 -0
- /package/dist/{linkedin-XKVPSCLV.js.map → linkedin-UGMAFSGO.js.map} +0 -0
- /package/dist/{run-KBN5K7LE.js.map → logo-VHXH4J6A.js.map} +0 -0
- /package/dist/{make-ED7HBLH3.js.map → make-W2PYZXYF.js.map} +0 -0
- /package/dist/{media-sources-PEHUMH7C.js.map → media-sources-EZKAJNVD.js.map} +0 -0
- /package/dist/{options-6FCNFWUF.js.map → options-NSCZSQ5P.js.map} +0 -0
- /package/dist/{pages-FTI44OSH.js.map → pages-PTWRXAZT.js.map} +0 -0
- /package/dist/{pixels-6IUB3Y3H.js.map → pixels-MYT3TCHZ.js.map} +0 -0
- /package/dist/{pixels-MBKR4XPX.js.map → pixels-ZZCQUS3J.js.map} +0 -0
- /package/dist/{rerun-A2XHGFZS.js.map → rerun-5THJLQQJ.js.map} +0 -0
- /package/dist/{research-BLDY5UWH.js.map → research-JHDWWFL7.js.map} +0 -0
- /package/dist/{rules-SK5DFFPY.js.map → rules-YLLFDZEM.js.map} +0 -0
- /package/dist/{rules-add-YQNYSME7.js.map → rules-add-U2GU4AGP.js.map} +0 -0
- /package/dist/{shared-NDRFKAH7.js.map → run-V5YQB6TH.js.map} +0 -0
- /package/dist/{scaffold-ad-6BN5LWQH.js.map → scaffold-ad-H4GJOKAW.js.map} +0 -0
- /package/dist/{scaffold-static-ad-VVZRAWBR.js.map → scaffold-static-ad-2YIFHCTL.js.map} +0 -0
- /package/dist/{scaffold-video-LFIYI4GP.js.map → scaffold-video-3EJLKR2O.js.map} +0 -0
- /package/dist/{select-QBU6ED4K.js.map → select-I22NPSIW.js.map} +0 -0
- /package/dist/{set-prompt-TL64CRBQ.js.map → set-prompt-S75OMQ7L.js.map} +0 -0
- /package/dist/{sync-definition-C6ROLKJ4.js.map → shared-3IBNDEFL.js.map} +0 -0
- /package/dist/{sources-RMNFV4CA.js.map → sources-VA23PDND.js.map} +0 -0
- /package/dist/{stale-ITFCPOER.js.map → stale-MHTU2NQJ.js.map} +0 -0
- /package/dist/{stats-RCLQE4HJ.js.map → stats-ZAGJH4AD.js.map} +0 -0
- /package/dist/{stock-ECRBD7RP.js.map → stock-6SHHLSKG.js.map} +0 -0
- /package/dist/{studio-MARZ22J2.js.map → studio-ZLCGXFAN.js.map} +0 -0
- /package/dist/{viewer-check-7ZG7KHEN.js.map → sync-definition-2EBSQA6A.js.map} +0 -0
- /package/dist/{tag-manager-G3LBQZUL.js.map → tag-manager-3CJ66GKJ.js.map} +0 -0
- /package/dist/{testimonials-YMMA5YWL.js.map → testimonials-GR6TIS5S.js.map} +0 -0
- /package/dist/{translate-OXVIMYHE.js.map → translate-GEFUP6KQ.js.map} +0 -0
- /package/dist/{validate-ZS2M5Q3V.js.map → validate-NOWIOAHE.js.map} +0 -0
- /package/dist/{videos-I6YXFBFT.js.map → videos-XMTDEHEJ.js.map} +0 -0
- /package/dist/{winning-ads-ABN5OULS.js.map → winning-ads-QOAYIR5U.js.map} +0 -0
- /package/dist/{x-WK2VQDPF.js.map → x-VCSMV7T5.js.map} +0 -0
package/dist/leads-2XOSAYP4.js
DELETED
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
bareAccountId,
|
|
3
|
-
loadJsonFileArg,
|
|
4
|
-
mergePayload,
|
|
5
|
-
stageOp
|
|
6
|
-
} from "./chunk-6JWEGFM5.js";
|
|
7
|
-
import {
|
|
8
|
-
isMetaLeadAdsRefusal
|
|
9
|
-
} from "./chunk-GOJXKIFQ.js";
|
|
10
|
-
import {
|
|
11
|
-
csvOrJson,
|
|
12
|
-
handleMetaError
|
|
13
|
-
} from "./chunk-OP7DNHD2.js";
|
|
14
|
-
import "./chunk-SFJW2KED.js";
|
|
15
|
-
import "./chunk-4NZ47VXO.js";
|
|
16
|
-
import "./chunk-D5FY4FAK.js";
|
|
17
|
-
import "./chunk-FNA277HP.js";
|
|
18
|
-
import {
|
|
19
|
-
writeAdsJson,
|
|
20
|
-
writeAdsOutput,
|
|
21
|
-
writeJsonEnvelope
|
|
22
|
-
} from "./chunk-SWL4AAPP.js";
|
|
23
|
-
import "./chunk-5WMTPYKT.js";
|
|
24
|
-
import "./chunk-23H4ZJRP.js";
|
|
25
|
-
import "./chunk-DWX44QL6.js";
|
|
26
|
-
import "./chunk-2FSEESJU.js";
|
|
27
|
-
import "./chunk-CVBKW75S.js";
|
|
28
|
-
import "./chunk-BLAHHMPF.js";
|
|
29
|
-
import "./chunk-XQIOCIDO.js";
|
|
30
|
-
import {
|
|
31
|
-
ApiError,
|
|
32
|
-
apiGet
|
|
33
|
-
} from "./chunk-XDZVBX6L.js";
|
|
34
|
-
import "./chunk-N5O67GK5.js";
|
|
35
|
-
import "./chunk-EE72SSB2.js";
|
|
36
|
-
import {
|
|
37
|
-
registerSchema
|
|
38
|
-
} from "./chunk-WNSE7N75.js";
|
|
39
|
-
import "./chunk-YQSBHWOI.js";
|
|
40
|
-
|
|
41
|
-
// src/commands/ads/meta/leads.ts
|
|
42
|
-
import { defineCommand } from "citty";
|
|
43
|
-
registerSchema({
|
|
44
|
-
command: "ads.meta.lead-forms",
|
|
45
|
-
description: "List the instant (lead) forms on a Facebook Page, with how many leads each has collected. Start here: a lead is fetched by form id. Use a Page from `baker ads meta pages` with hasPageAccessToken: true.",
|
|
46
|
-
args: {
|
|
47
|
-
"page-id": {
|
|
48
|
-
type: "string",
|
|
49
|
-
description: "Facebook Page ID \u2014 from `baker ads meta pages` with hasPageAccessToken: true",
|
|
50
|
-
required: true
|
|
51
|
-
},
|
|
52
|
-
full: { type: "boolean", description: "Include each form's questions", required: false },
|
|
53
|
-
output: { type: "string", description: "json|csv", required: false, default: "json" }
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
registerSchema({
|
|
57
|
-
command: "ads.meta.lead-forms.create",
|
|
58
|
-
description: "Start here to stage a Page-owned Meta Instant Form. The form is created only when this Session publishes. Use the returned meta_temp_* ref as --lead-form on a creative in the same Session.",
|
|
59
|
-
args: {
|
|
60
|
-
"account-id": { type: "string", description: "Selected Meta ad account, act_<id>", required: true },
|
|
61
|
-
"page-id": {
|
|
62
|
-
type: "string",
|
|
63
|
-
description: "Facebook Page that owns the form \u2014 choose one with this account in promotingAccountIds and hasPageAccessToken: true from `baker ads meta pages`",
|
|
64
|
-
required: true
|
|
65
|
-
},
|
|
66
|
-
name: { type: "string", description: "Form name", required: true },
|
|
67
|
-
questions: {
|
|
68
|
-
type: "string",
|
|
69
|
-
description: "Comma-separated Meta fields, e.g. FULL_NAME,EMAIL,PHONE",
|
|
70
|
-
required: true
|
|
71
|
-
},
|
|
72
|
-
"privacy-policy-url": { type: "string", description: "Public HTTPS privacy policy", required: true },
|
|
73
|
-
"follow-up-url": { type: "string", description: "Public HTTPS link after submission", required: true },
|
|
74
|
-
"optimized-for-quality": {
|
|
75
|
-
type: "boolean",
|
|
76
|
-
description: "Ask Meta to optimize form leads for quality",
|
|
77
|
-
required: false
|
|
78
|
-
},
|
|
79
|
-
file: {
|
|
80
|
-
type: "string",
|
|
81
|
-
description: "JSON file with full form payload, including thankYou and custom questions",
|
|
82
|
-
required: false
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
registerSchema({
|
|
87
|
-
command: "ads.meta.leads",
|
|
88
|
-
description: "Read the leads an instant form collected. Contact details (email, phone) come back masked; pass --full only when the raw values are genuinely needed, e.g. handing them to a CRM.",
|
|
89
|
-
args: {
|
|
90
|
-
"form-id": { type: "string", description: "Instant form ID \u2014 from `baker ads meta lead-forms`", required: false },
|
|
91
|
-
"ad-id": { type: "string", description: "Read the leads of one ad instead of a whole form", required: false },
|
|
92
|
-
since: { type: "string", description: "Earliest submission date, YYYY-MM-DD", required: false },
|
|
93
|
-
until: { type: "string", description: "Latest submission date, YYYY-MM-DD (inclusive)", required: false },
|
|
94
|
-
limit: { type: "string", description: "Leads per page (default 100, max 500)", required: false },
|
|
95
|
-
after: {
|
|
96
|
-
type: "string",
|
|
97
|
-
description: "Cursor from a previous call's nextCursor \u2014 fetches the following page",
|
|
98
|
-
required: false
|
|
99
|
-
},
|
|
100
|
-
full: { type: "boolean", description: "Return raw contact details instead of masked ones", required: false },
|
|
101
|
-
output: { type: "string", description: "json|csv", required: false, default: "json" }
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
var LEAD_FORMS_CAP = 500;
|
|
105
|
-
function leadFormHints(forms) {
|
|
106
|
-
if (forms.length === 0) {
|
|
107
|
-
return ["This Page has NO instant forms. Nothing to read leads from \u2014 the form has to be created first."];
|
|
108
|
-
}
|
|
109
|
-
if (forms.length >= LEAD_FORMS_CAP) {
|
|
110
|
-
return [
|
|
111
|
-
`PARTIAL LIST \u2014 this Page has at least ${LEAD_FORMS_CAP} instant forms and only the first ${LEAD_FORMS_CAP} came back. Do not describe this as every form on the Page.`
|
|
112
|
-
];
|
|
113
|
-
}
|
|
114
|
-
const empty = forms.filter((form) => (form.leads_count ?? 0) === 0);
|
|
115
|
-
if (empty.length === forms.length) {
|
|
116
|
-
return [
|
|
117
|
-
"Every form on this Page has collected 0 leads. That is a real, readable answer \u2014 the connection works. Do not retry and do not report it as a permissions problem."
|
|
118
|
-
];
|
|
119
|
-
}
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
122
|
-
function handleLeadsError(err) {
|
|
123
|
-
if (err instanceof ApiError && err.code === "FORBIDDEN" && isMetaLeadAdsRefusal(err.message)) {
|
|
124
|
-
writeAdsJson({
|
|
125
|
-
ok: false,
|
|
126
|
-
error: {
|
|
127
|
-
code: err.code,
|
|
128
|
-
message: err.message,
|
|
129
|
-
fix: { action: "reject", explanation: err.message },
|
|
130
|
-
retryable: false
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
process.exit(1);
|
|
134
|
-
}
|
|
135
|
-
handleMetaError(err);
|
|
136
|
-
}
|
|
137
|
-
function leadPageHints(page, full) {
|
|
138
|
-
const hints = [];
|
|
139
|
-
if (page.nextCursor) {
|
|
140
|
-
hints.push(
|
|
141
|
-
`PARTIAL PAGE \u2014 more leads exist. This is ${page.leads.length} of an unknown larger number; do NOT report it as a total. Fetch the next page with \`--after ${page.nextCursor}\` (repeat until no nextCursor), or narrow the window with --since/--until.`
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
if (!full) {
|
|
145
|
-
hints.push(
|
|
146
|
-
"Answers that give contact details (email, phone, any question asking for one) are masked. Report on them as they are; pass --full only when the raw values have to leave Baker (a CRM hand-off), and never paste them into the chat otherwise."
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
hints.push(...page.hints ?? []);
|
|
150
|
-
return hints;
|
|
151
|
-
}
|
|
152
|
-
var leadFormsCreateCommand = defineCommand({
|
|
153
|
-
meta: {
|
|
154
|
-
name: "create",
|
|
155
|
-
description: `Stage a Meta Instant Form on a Facebook Page. The form appears in review and is created only when the Session publishes.
|
|
156
|
-
Choose a Page with this account in promotingAccountIds and hasPageAccessToken: true from \`baker ads meta pages\`.
|
|
157
|
-
Example: baker ads meta lead-forms create --account-id act_123 --page-id 456 --name "Free audit" --questions FULL_NAME,EMAIL,PHONE --privacy-policy-url https://example.com/privacy --follow-up-url https://example.com`
|
|
158
|
-
},
|
|
159
|
-
args: {
|
|
160
|
-
"account-id": { type: "string", description: "Selected Meta ad account" },
|
|
161
|
-
"page-id": { type: "string", description: "Facebook Page ID" },
|
|
162
|
-
name: { type: "string", description: "Form name" },
|
|
163
|
-
questions: { type: "string", description: "FULL_NAME,EMAIL,PHONE or other Meta fields" },
|
|
164
|
-
"privacy-policy-url": { type: "string", description: "HTTPS privacy policy" },
|
|
165
|
-
"follow-up-url": { type: "string", description: "HTTPS thank-you link" },
|
|
166
|
-
"optimized-for-quality": { type: "boolean", description: "Optimize form leads for quality" },
|
|
167
|
-
file: { type: "string", description: "JSON form payload; flags override file keys" }
|
|
168
|
-
},
|
|
169
|
-
run: async ({ args }) => {
|
|
170
|
-
const accountId = bareAccountId(args);
|
|
171
|
-
const payload = mergePayload(loadJsonFileArg(args.file), {
|
|
172
|
-
page_id: args["page-id"],
|
|
173
|
-
name: args.name,
|
|
174
|
-
questions: typeof args.questions === "string" ? args.questions.split(",").map((type) => ({ type: type.trim().toUpperCase() })) : void 0,
|
|
175
|
-
privacyPolicyUrl: args["privacy-policy-url"],
|
|
176
|
-
followUpActionUrl: args["follow-up-url"],
|
|
177
|
-
optimizedForQuality: args["optimized-for-quality"]
|
|
178
|
-
});
|
|
179
|
-
await stageOp({ kind: "leadForm.create", accountId, payload });
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
var leadFormsListArgs = {
|
|
183
|
-
"page-id": { type: "string", description: "Facebook Page ID" },
|
|
184
|
-
full: { type: "boolean", description: "Include each form's questions" },
|
|
185
|
-
output: { type: "string", description: "Output format", default: "json" }
|
|
186
|
-
};
|
|
187
|
-
var leadFormsListCommand = defineCommand({
|
|
188
|
-
meta: {
|
|
189
|
-
name: "list",
|
|
190
|
-
description: "List the Instant Forms on a Facebook Page, with lead counts. Choose a Page with hasPageAccessToken: true from `baker ads meta pages`. Pass --full to include questions."
|
|
191
|
-
},
|
|
192
|
-
args: leadFormsListArgs,
|
|
193
|
-
run: async ({ args }) => {
|
|
194
|
-
try {
|
|
195
|
-
const pageId = args["page-id"];
|
|
196
|
-
if (!pageId) {
|
|
197
|
-
handleLeadsError(
|
|
198
|
-
new Error(
|
|
199
|
-
"--page-id is required. Run `baker ads meta pages` and choose a Page with hasPageAccessToken: true."
|
|
200
|
-
)
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
const params = { "page-id": pageId };
|
|
204
|
-
if (args.full) params.full = "true";
|
|
205
|
-
const data = await apiGet("/api/ads/meta/lead-forms", params);
|
|
206
|
-
const fmt = csvOrJson(args);
|
|
207
|
-
if (fmt !== "json") {
|
|
208
|
-
writeAdsOutput(data, fmt);
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
const hints = leadFormHints(data);
|
|
212
|
-
writeJsonEnvelope(hints.length > 0 ? { ok: true, data, hints } : { ok: true, data });
|
|
213
|
-
} catch (err) {
|
|
214
|
-
handleLeadsError(err);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
var leadFormsCommand = defineCommand({
|
|
219
|
-
meta: {
|
|
220
|
-
name: "lead-forms",
|
|
221
|
-
description: `List Instant Forms on a Facebook Page or stage a new one.
|
|
222
|
-
Examples:
|
|
223
|
-
baker ads meta lead-forms --page-id 100635183117758
|
|
224
|
-
baker ads meta lead-forms --page-id 100635183117758 --full
|
|
225
|
-
baker ads meta lead-forms create --account-id act_123 --page-id 555 --file form.json`
|
|
226
|
-
},
|
|
227
|
-
args: leadFormsListArgs,
|
|
228
|
-
subCommands: { list: leadFormsListCommand, create: leadFormsCreateCommand },
|
|
229
|
-
default: "list"
|
|
230
|
-
});
|
|
231
|
-
var leadsCommand = defineCommand({
|
|
232
|
-
meta: {
|
|
233
|
-
name: "leads",
|
|
234
|
-
description: `Read the leads an instant form collected. Every question comes back; email and phone answers are MASKED unless you pass --full, so you can report on what a form is collecting without moving contact details around.
|
|
235
|
-
|
|
236
|
-
Examples:
|
|
237
|
-
baker ads meta leads --form-id 987654321
|
|
238
|
-
baker ads meta leads --form-id 987654321 --since 2026-08-01 --until 2026-08-31
|
|
239
|
-
baker ads meta leads --ad-id 6123456789 --limit 50
|
|
240
|
-
baker ads meta leads --form-id 987654321 --after <nextCursor> # the next page
|
|
241
|
-
baker ads meta leads --form-id 987654321 --full # raw contact details \u2014 only when handing leads over
|
|
242
|
-
|
|
243
|
-
Results are PAGED. A response carrying \`nextCursor\` is not the whole set \u2014 follow it before reporting any total.`
|
|
244
|
-
},
|
|
245
|
-
args: {
|
|
246
|
-
"form-id": { type: "string", description: "Instant form ID (from `baker ads meta lead-forms`)" },
|
|
247
|
-
"ad-id": { type: "string", description: "Read one ad's leads instead of a whole form" },
|
|
248
|
-
since: { type: "string", description: "Earliest submission date, YYYY-MM-DD" },
|
|
249
|
-
until: { type: "string", description: "Latest submission date, YYYY-MM-DD (inclusive)" },
|
|
250
|
-
limit: { type: "string", description: "Leads per page (default 100, max 500)" },
|
|
251
|
-
after: { type: "string", description: "Cursor from a previous call's nextCursor" },
|
|
252
|
-
full: { type: "boolean", description: "Return raw contact details instead of masked ones" },
|
|
253
|
-
output: { type: "string", description: "Output format", default: "json" }
|
|
254
|
-
},
|
|
255
|
-
run: async ({ args }) => {
|
|
256
|
-
try {
|
|
257
|
-
const formId = args["form-id"];
|
|
258
|
-
const adId = args["ad-id"];
|
|
259
|
-
if (!formId && !adId) {
|
|
260
|
-
handleLeadsError(new Error("Pass --form-id (from `baker ads meta lead-forms`) or --ad-id."));
|
|
261
|
-
}
|
|
262
|
-
const params = {};
|
|
263
|
-
if (formId) params["form-id"] = formId;
|
|
264
|
-
if (adId) params["ad-id"] = adId;
|
|
265
|
-
if (args.since) params.since = args.since;
|
|
266
|
-
if (args.until) params.until = args.until;
|
|
267
|
-
if (args.limit) params.limit = String(args.limit);
|
|
268
|
-
if (args.after) params.after = String(args.after);
|
|
269
|
-
if (args.full) params.full = "true";
|
|
270
|
-
const page = await apiGet("/api/ads/meta/leads", params);
|
|
271
|
-
const fmt = csvOrJson(args);
|
|
272
|
-
if (fmt !== "json") {
|
|
273
|
-
writeAdsOutput(page.leads, fmt);
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
writeJsonEnvelope({
|
|
277
|
-
ok: true,
|
|
278
|
-
data: page.leads,
|
|
279
|
-
...page.nextCursor ? { nextCursor: page.nextCursor } : {},
|
|
280
|
-
hints: leadPageHints(page, args.full === true)
|
|
281
|
-
});
|
|
282
|
-
} catch (err) {
|
|
283
|
-
handleLeadsError(err);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
export {
|
|
288
|
-
leadFormHints,
|
|
289
|
-
leadFormsCommand,
|
|
290
|
-
leadPageHints,
|
|
291
|
-
leadsCommand
|
|
292
|
-
};
|
|
293
|
-
//# sourceMappingURL=leads-2XOSAYP4.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/meta/leads.ts"],"sourcesContent":["import { isMetaLeadAdsRefusal } from \"@baker/api/ads-meta\";\nimport { defineCommand } from \"citty\";\nimport { ApiError, apiGet } from \"../../../client.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { writeAdsJson, writeAdsOutput, writeJsonEnvelope } from \"../output.ts\";\nimport { csvOrJson, handleMetaError } from \"./shared.ts\";\nimport { bareAccountId, loadJsonFileArg, mergePayload, stageOp } from \"./write-shared.ts\";\n\n/** An instant form attached to a Facebook Page. */\nexport interface MetaLeadForm {\n id: string;\n name?: string;\n status?: string;\n locale?: string;\n leads_count?: number;\n created_time?: string;\n}\n\n/** One page of leads plus the cursor that continues it. */\nexport interface MetaLeadPage {\n leads: MetaLead[];\n /** Present only while Meta says another page exists. */\n nextCursor?: string;\n /** What the backend says about this page (every answer masked when it could not tell contact questions apart). */\n hints?: string[];\n}\n\n/** One lead, already shaped by the backend (contact values masked unless --full). */\nexport interface MetaLead {\n id: string;\n created_time?: string;\n ad_id?: string;\n ad_name?: string;\n adset_id?: string;\n adset_name?: string;\n campaign_id?: string;\n campaign_name?: string;\n form_id?: string;\n is_organic?: boolean;\n platform?: string;\n answers: Record<string, string>;\n}\n\nregisterSchema({\n command: \"ads.meta.lead-forms\",\n description:\n \"List the instant (lead) forms on a Facebook Page, with how many leads each has collected. Start here: a lead is fetched by form id. Use a Page from `baker ads meta pages` with hasPageAccessToken: true.\",\n args: {\n \"page-id\": {\n type: \"string\",\n description: \"Facebook Page ID — from `baker ads meta pages` with hasPageAccessToken: true\",\n required: true,\n },\n full: { type: \"boolean\", description: \"Include each form's questions\", required: false },\n output: { type: \"string\", description: \"json|csv\", required: false, default: \"json\" },\n },\n});\n\nregisterSchema({\n command: \"ads.meta.lead-forms.create\",\n description:\n \"Start here to stage a Page-owned Meta Instant Form. The form is created only when this Session publishes. Use the returned meta_temp_* ref as --lead-form on a creative in the same Session.\",\n args: {\n \"account-id\": { type: \"string\", description: \"Selected Meta ad account, act_<id>\", required: true },\n \"page-id\": {\n type: \"string\",\n description:\n \"Facebook Page that owns the form — choose one with this account in promotingAccountIds and hasPageAccessToken: true from `baker ads meta pages`\",\n required: true,\n },\n name: { type: \"string\", description: \"Form name\", required: true },\n questions: {\n type: \"string\",\n description: \"Comma-separated Meta fields, e.g. FULL_NAME,EMAIL,PHONE\",\n required: true,\n },\n \"privacy-policy-url\": { type: \"string\", description: \"Public HTTPS privacy policy\", required: true },\n \"follow-up-url\": { type: \"string\", description: \"Public HTTPS link after submission\", required: true },\n \"optimized-for-quality\": {\n type: \"boolean\",\n description: \"Ask Meta to optimize form leads for quality\",\n required: false,\n },\n file: {\n type: \"string\",\n description: \"JSON file with full form payload, including thankYou and custom questions\",\n required: false,\n },\n },\n});\n\nregisterSchema({\n command: \"ads.meta.leads\",\n description:\n \"Read the leads an instant form collected. Contact details (email, phone) come back masked; pass --full only when the raw values are genuinely needed, e.g. handing them to a CRM.\",\n args: {\n \"form-id\": { type: \"string\", description: \"Instant form ID — from `baker ads meta lead-forms`\", required: false },\n \"ad-id\": { type: \"string\", description: \"Read the leads of one ad instead of a whole form\", required: false },\n since: { type: \"string\", description: \"Earliest submission date, YYYY-MM-DD\", required: false },\n until: { type: \"string\", description: \"Latest submission date, YYYY-MM-DD (inclusive)\", required: false },\n limit: { type: \"string\", description: \"Leads per page (default 100, max 500)\", required: false },\n after: {\n type: \"string\",\n description: \"Cursor from a previous call's nextCursor — fetches the following page\",\n required: false,\n },\n full: { type: \"boolean\", description: \"Return raw contact details instead of masked ones\", required: false },\n output: { type: \"string\", description: \"json|csv\", required: false, default: \"json\" },\n },\n});\n\n/**\n * A form that exists but has never collected anything is the single most common\n * thing to misread here — it looks identical to a permissions problem in the\n * output, and the remedies are opposite. Say which it is.\n */\n/** The backend drains instant forms up to this many; see `META_LEAD_FORMS_MAX`. */\nconst LEAD_FORMS_CAP = 500;\n\nexport function leadFormHints(forms: MetaLeadForm[]): string[] {\n if (forms.length === 0) {\n return [\"This Page has NO instant forms. Nothing to read leads from — the form has to be created first.\"];\n }\n if (forms.length >= LEAD_FORMS_CAP) {\n return [\n `PARTIAL LIST — this Page has at least ${LEAD_FORMS_CAP} instant forms and only the first ${LEAD_FORMS_CAP} came back. Do not describe this as every form on the Page.`,\n ];\n }\n const empty = forms.filter((form) => (form.leads_count ?? 0) === 0);\n if (empty.length === forms.length) {\n return [\n \"Every form on this Page has collected 0 leads. That is a real, readable answer — the connection works. Do not retry and do not report it as a permissions problem.\",\n ];\n }\n return [];\n}\n\n/**\n * A `FORBIDDEN` that Baker itself produced is already conclusive, so it must not\n * collect the generic ambiguous-403 remedy.\n *\n * `metaForbiddenFix` exists for Meta's own 403, which covers two causes with\n * opposite fixes and can only be told apart by testing the blast radius. Pasting\n * that after *\"this needs switching on by the Baker team\"* would hand the agent\n * a paragraph suggesting a reconnect right underneath a sentence saying a\n * reconnect cannot help — and the agent would pass it on, costing the client a\n * pointless round trip through their Meta login. Everything that is genuinely\n * Meta's still goes through the normal handler.\n */\nfunction handleLeadsError(err: unknown): never {\n if (err instanceof ApiError && err.code === \"FORBIDDEN\" && isMetaLeadAdsRefusal(err.message)) {\n writeAdsJson({\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n fix: { action: \"reject\", explanation: err.message },\n retryable: false,\n },\n });\n process.exit(1);\n }\n handleMetaError(err);\n}\n\n/**\n * What the agent has to know before it reports a number.\n *\n * Counting is what this command is mostly used for, so a page that is full is\n * the dangerous case: without a word, 100 rows read as \"100 leads\" and the\n * client is told something false. The cursor is the remedy, and it has to be\n * named in the same breath as the warning.\n */\nexport function leadPageHints(page: MetaLeadPage, full: boolean): string[] {\n const hints: string[] = [];\n if (page.nextCursor) {\n hints.push(\n `PARTIAL PAGE — more leads exist. This is ${page.leads.length} of an unknown larger number; do NOT report it as a total. Fetch the next page with \\`--after ${page.nextCursor}\\` (repeat until no nextCursor), or narrow the window with --since/--until.`,\n );\n }\n if (!full) {\n hints.push(\n \"Answers that give contact details (email, phone, any question asking for one) are masked. Report on them as they are; pass --full only when the raw values have to leave Baker (a CRM hand-off), and never paste them into the chat otherwise.\",\n );\n }\n hints.push(...(page.hints ?? []));\n return hints;\n}\n\nconst leadFormsCreateCommand = defineCommand({\n meta: {\n name: \"create\",\n description: `Stage a Meta Instant Form on a Facebook Page. The form appears in review and is created only when the Session publishes.\nChoose a Page with this account in promotingAccountIds and hasPageAccessToken: true from \\`baker ads meta pages\\`.\nExample: baker ads meta lead-forms create --account-id act_123 --page-id 456 --name \"Free audit\" --questions FULL_NAME,EMAIL,PHONE --privacy-policy-url https://example.com/privacy --follow-up-url https://example.com`,\n },\n args: {\n \"account-id\": { type: \"string\", description: \"Selected Meta ad account\" },\n \"page-id\": { type: \"string\", description: \"Facebook Page ID\" },\n name: { type: \"string\", description: \"Form name\" },\n questions: { type: \"string\", description: \"FULL_NAME,EMAIL,PHONE or other Meta fields\" },\n \"privacy-policy-url\": { type: \"string\", description: \"HTTPS privacy policy\" },\n \"follow-up-url\": { type: \"string\", description: \"HTTPS thank-you link\" },\n \"optimized-for-quality\": { type: \"boolean\", description: \"Optimize form leads for quality\" },\n file: { type: \"string\", description: \"JSON form payload; flags override file keys\" },\n },\n run: async ({ args }) => {\n const accountId = bareAccountId(args as Record<string, unknown>);\n const payload = mergePayload(loadJsonFileArg(args.file), {\n page_id: args[\"page-id\"],\n name: args.name,\n questions:\n typeof args.questions === \"string\"\n ? args.questions.split(\",\").map((type) => ({ type: type.trim().toUpperCase() }))\n : undefined,\n privacyPolicyUrl: args[\"privacy-policy-url\"],\n followUpActionUrl: args[\"follow-up-url\"],\n optimizedForQuality: args[\"optimized-for-quality\"],\n });\n await stageOp({ kind: \"leadForm.create\", accountId, payload });\n },\n});\n\nconst leadFormsListArgs = {\n \"page-id\": { type: \"string\", description: \"Facebook Page ID\" },\n full: { type: \"boolean\", description: \"Include each form's questions\" },\n output: { type: \"string\", description: \"Output format\", default: \"json\" },\n} as const;\n\nconst leadFormsListCommand = defineCommand({\n meta: {\n name: \"list\",\n description:\n \"List the Instant Forms on a Facebook Page, with lead counts. Choose a Page with hasPageAccessToken: true from `baker ads meta pages`. Pass --full to include questions.\",\n },\n args: leadFormsListArgs,\n run: async ({ args }) => {\n try {\n const pageId = args[\"page-id\"] as string | undefined;\n if (!pageId) {\n handleLeadsError(\n new Error(\n \"--page-id is required. Run `baker ads meta pages` and choose a Page with hasPageAccessToken: true.\",\n ),\n );\n }\n const params: Record<string, string> = { \"page-id\": pageId };\n if (args.full) params.full = \"true\";\n const data = await apiGet<MetaLeadForm[]>(\"/api/ads/meta/lead-forms\", params);\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(data as unknown as Array<Record<string, unknown>>, fmt);\n return;\n }\n const hints = leadFormHints(data);\n writeJsonEnvelope(hints.length > 0 ? { ok: true, data, hints } : { ok: true, data });\n } catch (err) {\n handleLeadsError(err);\n }\n },\n});\n\nexport const leadFormsCommand = defineCommand({\n meta: {\n name: \"lead-forms\",\n description: `List Instant Forms on a Facebook Page or stage a new one.\nExamples:\n baker ads meta lead-forms --page-id 100635183117758\n baker ads meta lead-forms --page-id 100635183117758 --full\n baker ads meta lead-forms create --account-id act_123 --page-id 555 --file form.json`,\n },\n args: leadFormsListArgs,\n subCommands: { list: leadFormsListCommand, create: leadFormsCreateCommand },\n default: \"list\",\n});\n\nexport const leadsCommand = defineCommand({\n meta: {\n name: \"leads\",\n description: `Read the leads an instant form collected. Every question comes back; email and phone answers are MASKED unless you pass --full, so you can report on what a form is collecting without moving contact details around.\n\nExamples:\n baker ads meta leads --form-id 987654321\n baker ads meta leads --form-id 987654321 --since 2026-08-01 --until 2026-08-31\n baker ads meta leads --ad-id 6123456789 --limit 50\n baker ads meta leads --form-id 987654321 --after <nextCursor> # the next page\n baker ads meta leads --form-id 987654321 --full # raw contact details — only when handing leads over\n\nResults are PAGED. A response carrying \\`nextCursor\\` is not the whole set — follow it before reporting any total.`,\n },\n args: {\n \"form-id\": { type: \"string\", description: \"Instant form ID (from `baker ads meta lead-forms`)\" },\n \"ad-id\": { type: \"string\", description: \"Read one ad's leads instead of a whole form\" },\n since: { type: \"string\", description: \"Earliest submission date, YYYY-MM-DD\" },\n until: { type: \"string\", description: \"Latest submission date, YYYY-MM-DD (inclusive)\" },\n limit: { type: \"string\", description: \"Leads per page (default 100, max 500)\" },\n after: { type: \"string\", description: \"Cursor from a previous call's nextCursor\" },\n full: { type: \"boolean\", description: \"Return raw contact details instead of masked ones\" },\n output: { type: \"string\", description: \"Output format\", default: \"json\" },\n },\n run: async ({ args }) => {\n try {\n const formId = args[\"form-id\"] as string | undefined;\n const adId = args[\"ad-id\"] as string | undefined;\n if (!formId && !adId) {\n handleLeadsError(new Error(\"Pass --form-id (from `baker ads meta lead-forms`) or --ad-id.\"));\n }\n const params: Record<string, string> = {};\n if (formId) params[\"form-id\"] = formId;\n if (adId) params[\"ad-id\"] = adId;\n if (args.since) params.since = args.since as string;\n if (args.until) params.until = args.until as string;\n if (args.limit) params.limit = String(args.limit);\n if (args.after) params.after = String(args.after);\n if (args.full) params.full = \"true\";\n const page = await apiGet<MetaLeadPage>(\"/api/ads/meta/leads\", params);\n const fmt = csvOrJson(args);\n if (fmt !== \"json\") {\n writeAdsOutput(page.leads as unknown as Array<Record<string, unknown>>, fmt);\n return;\n }\n writeJsonEnvelope({\n ok: true,\n data: page.leads,\n ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),\n hints: leadPageHints(page, args.full === true),\n });\n } catch (err) {\n handleLeadsError(err);\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/chatgpt/locations.ts"],"sourcesContent":["import type { ChatgptAdsLocation } from \"@baker/api/ads-chatgpt\";\nimport { defineCommand } from \"citty\";\nimport { apiGet } from \"../../../client.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { CHATGPT_ADS_REFERENCE, runChatgptRead } from \"./shared.ts\";\n\nconst ARGS = {\n query: { type: \"positional\", description: \"The place to look for, e.g. Madrid\", required: true },\n limit: { type: \"string\", description: \"At most this many matches (default 20, max 100)\", required: false },\n} as const;\n\nregisterSchema({\n command: \"ads.chatgpt.locations\",\n description:\n \"Places ChatGPT Ads can target, found by name: each row's id is what `campaigns create|update --location-ids` takes. Countries go in --countries as two-letter codes instead.\",\n args: {\n query: { type: \"string\", description: \"The place to look for, e.g. Madrid\", required: true },\n limit: { type: \"string\", description: \"At most this many matches (default 20, max 100)\", required: false },\n },\n});\n\nexport const locationsCommand = defineCommand({\n meta: {\n name: \"locations\",\n description: `Find the id of a region, city, market or postcode to target or exclude — countries use --countries codes instead.\n\nExamples:\n baker ads chatgpt locations Madrid\n baker ads chatgpt locations \"Comunidad Valenciana\" --limit 5`,\n },\n args: ARGS,\n run: async ({ args }) => {\n await runChatgptRead(\n `${CHATGPT_ADS_REFERENCE.overview}`,\n () =>\n apiGet<ChatgptAdsLocation[]>(\"/api/ads/chatgpt/locations\", {\n q: String(args.query),\n ...(typeof args.limit === \"string\" && args.limit ? { limit: args.limit } : {}),\n }),\n locationHints,\n );\n },\n});\n\nexport function locationHints(places: readonly ChatgptAdsLocation[]): string[] {\n if (places.length === 0) {\n return [\"No place matched. Try the local or English name, or a broader area.\"];\n }\n const unserved = [...new Set(places.filter((place) => !place.served).map((place) => place.countryCode))];\n return [\n \"Target one with `campaigns create|update --location-ids <id>` (or exclude it with `--excluded-location-ids`) — the id, not the name.\",\n ...(unserved.length > 0\n ? [\n `ChatGPT Ads did not serve in ${unserved.join(\", \")} when Baker last checked (served: false): a campaign targeting those places is refused at publish.`,\n ]\n : []),\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;AACA,SAAS,qBAAqB;AAK9B,IAAM,OAAO;AAAA,EACX,OAAO,EAAE,MAAM,cAAc,aAAa,sCAAsC,UAAU,KAAK;AAAA,EAC/F,OAAO,EAAE,MAAM,UAAU,aAAa,mDAAmD,UAAU,MAAM;AAC3G;AAEA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,OAAO,EAAE,MAAM,UAAU,aAAa,sCAAsC,UAAU,KAAK;AAAA,IAC3F,OAAO,EAAE,MAAM,UAAU,aAAa,mDAAmD,UAAU,MAAM;AAAA,EAC3G;AACF,CAAC;AAEM,IAAM,mBAAmB,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf;AAAA,EACA,MAAM;AAAA,EACN,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,UAAM;AAAA,MACJ,GAAG,sBAAsB,QAAQ;AAAA,MACjC,MACE,OAA6B,8BAA8B;AAAA,QACzD,GAAG,OAAO,KAAK,KAAK;AAAA,QACpB,GAAI,OAAO,KAAK,UAAU,YAAY,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,MAC9E,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAEM,SAAS,cAAc,QAAiD;AAC7E,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,CAAC,qEAAqE;AAAA,EAC/E;AACA,QAAM,WAAW,CAAC,GAAG,IAAI,IAAI,OAAO,OAAO,CAAC,UAAU,CAAC,MAAM,MAAM,EAAE,IAAI,CAAC,UAAU,MAAM,WAAW,CAAC,CAAC;AACvG,SAAO;AAAA,IACL;AAAA,IACA,GAAI,SAAS,SAAS,IAClB;AAAA,MACE,gCAAgC,SAAS,KAAK,IAAI,CAAC;AAAA,IACrD,IACA,CAAC;AAAA,EACP;AACF;","names":[]}
|
package/dist/media-ES2UBGYW.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import "./chunk-YQSBHWOI.js";
|
|
2
|
-
|
|
3
|
-
// src/commands/ads/meta/media.ts
|
|
4
|
-
import { defineCommand } from "citty";
|
|
5
|
-
var metaMediaCommand = defineCommand({
|
|
6
|
-
meta: {
|
|
7
|
-
name: "media",
|
|
8
|
-
description: "Stage Baker library media uploads to Meta so creatives can reference them. Subcommand: upload. Publishes an ad-image hash or video id a creative binds via --image-ref/--video-ref."
|
|
9
|
-
},
|
|
10
|
-
subCommands: { upload: () => import("./write-commands-HCQI4Y27.js").then((m) => m.mediaUploadCommand) }
|
|
11
|
-
});
|
|
12
|
-
export {
|
|
13
|
-
metaMediaCommand
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=media-ES2UBGYW.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/meta/media.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\n\nexport const metaMediaCommand = defineCommand({\n meta: {\n name: \"media\",\n description:\n \"Stage Baker library media uploads to Meta so creatives can reference them. Subcommand: upload. Publishes an ad-image hash or video id a creative binds via --image-ref/--video-ref.\",\n },\n subCommands: { upload: () => import(\"./write-commands.ts\").then((m) => m.mediaUploadCommand) },\n});\n"],"mappings":";;;AAAA,SAAS,qBAAqB;AAEvB,IAAM,mBAAmB,cAAc;AAAA,EAC5C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,aAAa,EAAE,QAAQ,MAAM,OAAO,8BAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,kBAAkB,EAAE;AAC/F,CAAC;","names":[]}
|
package/dist/meta-AOIPEDV5.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import "./chunk-YQSBHWOI.js";
|
|
2
|
-
|
|
3
|
-
// src/commands/ads/meta/index.ts
|
|
4
|
-
import { defineCommand } from "citty";
|
|
5
|
-
var metaCommand = defineCommand({
|
|
6
|
-
meta: {
|
|
7
|
-
name: "meta",
|
|
8
|
-
description: `Meta Marketing API \u2014 AI-first command surface (Facebook + Instagram ads).
|
|
9
|
-
|
|
10
|
-
Discovery:
|
|
11
|
-
baker ads meta accounts \u2014 accounts in this company's connected scope
|
|
12
|
-
baker ads meta businesses \u2014 Business Manager IDs
|
|
13
|
-
baker ads meta pages \u2014 Facebook Pages the selected ad accounts can promote (an ad's identity)
|
|
14
|
-
baker ads meta lead-forms --page-id 100635183117758 \u2014 instant (lead) forms on a Page, with lead counts
|
|
15
|
-
baker ads meta lead-forms create --account-id act_123 --page-id 555 --file form.json \u2014 stage a new form
|
|
16
|
-
baker ads meta leads --form-id 987654321 \u2014 the leads one form collected (contact details masked)
|
|
17
|
-
|
|
18
|
-
Snapshot a running account (default = ACTIVE only):
|
|
19
|
-
baker ads meta campaigns --account-id act_123
|
|
20
|
-
baker ads meta adsets --campaign-id 6123
|
|
21
|
-
baker ads meta ads --adset-id 6123
|
|
22
|
-
baker ads meta campaigns --account-id act_123 --all-statuses \u2014 include paused, archived
|
|
23
|
-
|
|
24
|
-
Drill in:
|
|
25
|
-
baker ads meta account --account-id act_123 \u2014 currency, balance, business
|
|
26
|
-
baker ads meta creatives --creative-id 9988 \u2014 single creative detail
|
|
27
|
-
baker ads meta audiences --account-id act_123
|
|
28
|
-
baker ads meta custom-conversions --account-id act_123 \u2014 the marketer's own conversions ("my conversions")
|
|
29
|
-
baker ads meta pixels --account-id act_123 \u2014 pixel list
|
|
30
|
-
baker ads meta pixels --pixel-id 9988 --stats --days 7 \u2014 firing health
|
|
31
|
-
|
|
32
|
-
Performance (the workhorse):
|
|
33
|
-
baker ads meta insights --object act_123 \u2014 defaults: level=account, intent=baseline, last_7d
|
|
34
|
-
baker ads meta insights --object act_123 --intent revenue --date-preset last_28d
|
|
35
|
-
baker ads meta insights --object act_123 --level ad --intent ranking \u2014 flag creatives to refresh
|
|
36
|
-
baker ads meta insights --object act_123 --level adset --breakdowns publisher_platform,age \u2014 placement \xD7 age
|
|
37
|
-
baker ads meta insights --object act_123 --level ad --since 2026-01-01 --until 2026-03-31 \u2014 auto-async
|
|
38
|
-
baker ads meta insights --list-intents
|
|
39
|
-
|
|
40
|
-
Audit & review:
|
|
41
|
-
baker ads meta activities --account-id act_123 --days 14
|
|
42
|
-
baker ads meta preview --creative-id 9988 --ad-format MOBILE_FEED_STANDARD --out-file /tmp/p.html
|
|
43
|
-
Full guide: __tooling__/docs/tools/baker/ads-meta.md`
|
|
44
|
-
},
|
|
45
|
-
subCommands: {
|
|
46
|
-
accounts: () => import("./accounts-UA2ZWRN4.js").then((m) => m.accountsCommand),
|
|
47
|
-
account: () => import("./account-7LUQWY6Q.js").then((m) => m.accountCommand),
|
|
48
|
-
businesses: () => import("./businesses-PRRYPR7H.js").then((m) => m.businessesCommand),
|
|
49
|
-
pages: () => import("./pages-FTI44OSH.js").then((m) => m.pagesCommand),
|
|
50
|
-
"lead-forms": () => import("./leads-2XOSAYP4.js").then((m) => m.leadFormsCommand),
|
|
51
|
-
leads: () => import("./leads-2XOSAYP4.js").then((m) => m.leadsCommand),
|
|
52
|
-
campaigns: () => import("./campaigns-4SOLY7OR.js").then((m) => m.campaignsCommand),
|
|
53
|
-
adsets: () => import("./adsets-LPN6WFGF.js").then((m) => m.adsetsCommand),
|
|
54
|
-
ads: () => import("./ads-HXX2IAFF.js").then((m) => m.adsListCommand),
|
|
55
|
-
creatives: () => import("./creatives-YJ3CXZQC.js").then((m) => m.creativesCommand),
|
|
56
|
-
audiences: () => import("./audiences-XEZHACKH.js").then((m) => m.audiencesCommand),
|
|
57
|
-
"custom-conversions": () => import("./custom-conversions-YRYE65PU.js").then((m) => m.customConversionsCommand),
|
|
58
|
-
pixels: () => import("./pixels-MBKR4XPX.js").then((m) => m.pixelsCommand),
|
|
59
|
-
activities: () => import("./activities-IQPJPP4B.js").then((m) => m.activitiesCommand),
|
|
60
|
-
insights: () => import("./insights-4HT2NAYP.js").then((m) => m.insightsCommand),
|
|
61
|
-
preview: () => import("./preview-V4YBD45S.js").then((m) => m.previewCommand),
|
|
62
|
-
media: () => import("./media-ES2UBGYW.js").then((m) => m.metaMediaCommand),
|
|
63
|
-
draft: () => import("./draft-EWDOIXSH.js").then((m) => m.metaDraftCommand)
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
export {
|
|
67
|
-
metaCommand
|
|
68
|
-
};
|
|
69
|
-
//# sourceMappingURL=meta-AOIPEDV5.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/meta/index.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\n\n/**\n * Meta Ads command surface — curated for AI agents, not 1:1 with the Marketing API.\n *\n * The HTTP backend exposes more endpoints (catalogs, studies, ad-images, labels,\n * high-demand-periods, currency lookup). They're intentionally not surfaced as\n * CLI commands because AI agents rarely need them in isolation. Hit them via\n * curl against the API if you need them.\n *\n * Default behaviors that matter:\n * - Listings (campaigns/adsets/ads) filter to ACTIVE — pass --all-statuses to widen.\n * - Insights filter out non-delivered rows (impressions=0) and sort by spend desc.\n * - Insights pick a smart field bundle via --intent (baseline|revenue|funnel|ranking|video|identity).\n * - Heavy insights queries auto-fall to async (poll loop hidden).\n * - Attribution defaults to 7d_click,1d_view — the only windows still working as of Jan 2026.\n */\nexport const metaCommand = defineCommand({\n meta: {\n name: \"meta\",\n description: `Meta Marketing API — AI-first command surface (Facebook + Instagram ads).\n\nDiscovery:\n baker ads meta accounts — accounts in this company's connected scope\n baker ads meta businesses — Business Manager IDs\n baker ads meta pages — Facebook Pages the selected ad accounts can promote (an ad's identity)\n baker ads meta lead-forms --page-id 100635183117758 — instant (lead) forms on a Page, with lead counts\n baker ads meta lead-forms create --account-id act_123 --page-id 555 --file form.json — stage a new form\n baker ads meta leads --form-id 987654321 — the leads one form collected (contact details masked)\n\nSnapshot a running account (default = ACTIVE only):\n baker ads meta campaigns --account-id act_123\n baker ads meta adsets --campaign-id 6123\n baker ads meta ads --adset-id 6123\n baker ads meta campaigns --account-id act_123 --all-statuses — include paused, archived\n\nDrill in:\n baker ads meta account --account-id act_123 — currency, balance, business\n baker ads meta creatives --creative-id 9988 — single creative detail\n baker ads meta audiences --account-id act_123\n baker ads meta custom-conversions --account-id act_123 — the marketer's own conversions (\"my conversions\")\n baker ads meta pixels --account-id act_123 — pixel list\n baker ads meta pixels --pixel-id 9988 --stats --days 7 — firing health\n\nPerformance (the workhorse):\n baker ads meta insights --object act_123 — defaults: level=account, intent=baseline, last_7d\n baker ads meta insights --object act_123 --intent revenue --date-preset last_28d\n baker ads meta insights --object act_123 --level ad --intent ranking — flag creatives to refresh\n baker ads meta insights --object act_123 --level adset --breakdowns publisher_platform,age — placement × age\n baker ads meta insights --object act_123 --level ad --since 2026-01-01 --until 2026-03-31 — auto-async\n baker ads meta insights --list-intents\n\nAudit & review:\n baker ads meta activities --account-id act_123 --days 14\n baker ads meta preview --creative-id 9988 --ad-format MOBILE_FEED_STANDARD --out-file /tmp/p.html\nFull guide: __tooling__/docs/tools/baker/ads-meta.md`,\n },\n subCommands: {\n accounts: () => import(\"./accounts.ts\").then((m) => m.accountsCommand),\n account: () => import(\"./account.ts\").then((m) => m.accountCommand),\n businesses: () => import(\"./businesses.ts\").then((m) => m.businessesCommand),\n pages: () => import(\"./pages.ts\").then((m) => m.pagesCommand),\n \"lead-forms\": () => import(\"./leads.ts\").then((m) => m.leadFormsCommand),\n leads: () => import(\"./leads.ts\").then((m) => m.leadsCommand),\n campaigns: () => import(\"./campaigns.ts\").then((m) => m.campaignsCommand),\n adsets: () => import(\"./adsets.ts\").then((m) => m.adsetsCommand),\n ads: () => import(\"./ads.ts\").then((m) => m.adsListCommand),\n creatives: () => import(\"./creatives.ts\").then((m) => m.creativesCommand),\n audiences: () => import(\"./audiences.ts\").then((m) => m.audiencesCommand),\n \"custom-conversions\": () => import(\"./custom-conversions.ts\").then((m) => m.customConversionsCommand),\n pixels: () => import(\"./pixels.ts\").then((m) => m.pixelsCommand),\n activities: () => import(\"./activities.ts\").then((m) => m.activitiesCommand),\n insights: () => import(\"./insights.ts\").then((m) => m.insightsCommand),\n preview: () => import(\"./preview.ts\").then((m) => m.previewCommand),\n media: () => import(\"./media.ts\").then((m) => m.metaMediaCommand),\n draft: () => import(\"./draft.ts\").then((m) => m.metaDraftCommand),\n },\n});\n"],"mappings":";;;AAAA,SAAS,qBAAqB;AAiBvB,IAAM,cAAc,cAAc;AAAA,EACvC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoCf;AAAA,EACA,aAAa;AAAA,IACX,UAAU,MAAM,OAAO,wBAAe,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe;AAAA,IACrE,SAAS,MAAM,OAAO,uBAAc,EAAE,KAAK,CAAC,MAAM,EAAE,cAAc;AAAA,IAClE,YAAY,MAAM,OAAO,0BAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,iBAAiB;AAAA,IAC3E,OAAO,MAAM,OAAO,qBAAY,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY;AAAA,IAC5D,cAAc,MAAM,OAAO,qBAAY,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IACvE,OAAO,MAAM,OAAO,qBAAY,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY;AAAA,IAC5D,WAAW,MAAM,OAAO,yBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IACxE,QAAQ,MAAM,OAAO,sBAAa,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa;AAAA,IAC/D,KAAK,MAAM,OAAO,mBAAU,EAAE,KAAK,CAAC,MAAM,EAAE,cAAc;AAAA,IAC1D,WAAW,MAAM,OAAO,yBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IACxE,WAAW,MAAM,OAAO,yBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IACxE,sBAAsB,MAAM,OAAO,kCAAyB,EAAE,KAAK,CAAC,MAAM,EAAE,wBAAwB;AAAA,IACpG,QAAQ,MAAM,OAAO,sBAAa,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa;AAAA,IAC/D,YAAY,MAAM,OAAO,0BAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,iBAAiB;AAAA,IAC3E,UAAU,MAAM,OAAO,wBAAe,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe;AAAA,IACrE,SAAS,MAAM,OAAO,uBAAc,EAAE,KAAK,CAAC,MAAM,EAAE,cAAc;AAAA,IAClE,OAAO,MAAM,OAAO,qBAAY,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,IAChE,OAAO,MAAM,OAAO,qBAAY,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB;AAAA,EAClE;AACF,CAAC;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/ads/meta/preview.ts"],"sourcesContent":["import { writeFileSync } from \"node:fs\";\nimport {\n FACEBOOK_PREVIEW_FORMATS,\n INSTAGRAM_PREVIEW_FORMATS,\n PLATFORM_SCOPED_POSITIONS,\n previewFormatForPosition,\n} from \"@baker/api/ads-meta\";\nimport { defineCommand } from \"citty\";\nimport { NO_CACHE_ARG } from \"../../../cache-flag.ts\";\nimport { apiPost } from \"../../../client.ts\";\nimport { writeAdsJson, writeJsonEnvelope } from \"../output.ts\";\nimport { handleMetaError } from \"./shared.ts\";\n\nconst VALID_AD_FORMATS = [\n \"DESKTOP_FEED_STANDARD\",\n \"MOBILE_FEED_STANDARD\",\n \"MOBILE_FEED_BASIC\",\n \"RIGHT_COLUMN_STANDARD\",\n \"MOBILE_FULLWIDTH\",\n \"MOBILE_INTERSTITIAL\",\n \"MOBILE_BANNER\",\n \"MOBILE_MEDIUM_RECTANGLE\",\n \"MOBILE_NATIVE\",\n \"FACEBOOK_STORY_MOBILE\",\n \"FACEBOOK_REELS_MOBILE\",\n \"INSTAGRAM_STORY\",\n \"INSTAGRAM_REELS\",\n \"INSTAGRAM_REELS_OVERLAY\",\n \"INSTAGRAM_STANDARD\",\n \"INSTAGRAM_EXPLORE_CONTEXTUAL\",\n \"INSTAGRAM_EXPLORE_GRID_HOME\",\n \"INSTAGRAM_SEARCH_CHAIN\",\n \"INSTAGRAM_SHOP\",\n \"INSTAGRAM_PROFILE_FEED\",\n \"INSTREAM_VIDEO_DESKTOP\",\n \"INSTREAM_VIDEO_MOBILE\",\n \"FACEBOOK_REELS_BANNER\",\n \"FACEBOOK_REELS_STICKER\",\n \"MESSENGER_MOBILE_INBOX_MEDIA\",\n \"MESSENGER_MOBILE_STORY_MEDIA\",\n \"AUDIENCE_NETWORK_OUTSTREAM_VIDEO\",\n \"AUDIENCE_NETWORK_INSTREAM_VIDEO_MOBILE\",\n \"AUDIENCE_NETWORK_REWARDED_VIDEO\",\n \"INSTANT_ARTICLE_STANDARD\",\n \"MARKETPLACE_MOBILE\",\n \"BIZ_DISCO_FEED_MOBILE\",\n];\n\n/** A bad flag is not a network failure — mislabelling it invites a retry of the same doomed call. */\nfunction failPreviewValidation(message: string): never {\n writeAdsJson({ ok: false, error: { code: \"VALIDATION_ERROR\", message } });\n process.exit(1);\n}\n\n/**\n * Preview is the free way to see what Meta actually renders for a creative in a\n * given surface — the check that turns \"this placement must be showing a still\"\n * from a claim into an observation. It was being used by guessing format names,\n * so both doors are open now: the Meta `ad_format` enum via `--ad-format`, and\n * the `platform_position` an insights breakdown reports via `--placement`.\n */\nfunction resolvePlacement(position: string, platform: unknown): string {\n const platformArg = typeof platform === \"string\" ? platform.toLowerCase() : undefined;\n if (platformArg && platformArg !== \"facebook\" && platformArg !== \"instagram\") {\n failPreviewValidation(\"--platform must be facebook or instagram\");\n }\n const format = previewFormatForPosition(position, platformArg);\n if (format) {\n return format;\n }\n if (PLATFORM_SCOPED_POSITIONS.has(position) && !platformArg) {\n failPreviewValidation(\n `--placement ${position} names a different surface on Facebook and on Instagram — add --platform facebook or --platform instagram (the breakdown row's publisher_platform)`,\n );\n }\n failPreviewValidation(\n `No Meta preview format is published for placement \"${position}\". Meta does not document one for every placement (facebook_notification and facebook_profile_feed among them), so this placement cannot be previewed — report it as unverified rather than inferring what it renders. Pass the platform_position exactly as the insights breakdown spelled it: targeting names a few surfaces differently (story, reels, explore_home) and those names never appear in a breakdown. Previewable placements: ${listPlacements()}`,\n );\n}\n\nfunction listPlacements(): string {\n const facebook = Object.keys(FACEBOOK_PREVIEW_FORMATS).join(\", \");\n const instagram = Object.keys(INSTAGRAM_PREVIEW_FORMATS).join(\", \");\n return `facebook — ${facebook}; instagram — ${instagram}`;\n}\n\nexport const previewCommand = defineCommand({\n meta: {\n name: \"preview\",\n description: `Generate a Meta-hosted preview iframe for a creative or ad. Returns iframe HTML which you\ncan embed or save to a file. The iframe URL contains a short-lived access token — treat as secret.\n\nStart here when you need to know what a creative looks like in one specific placement — this is\nMeta's own renderer, so it settles \"does my video show as a still image there?\" without guessing.\nPass the placement straight from an insights breakdown with --placement (a platform_position value),\nor a Meta ad_format with --ad-format. Run --list-formats to see both sets.\n\nExamples:\n baker ads meta preview --creative-id 6123 --ad-format MOBILE_FEED_STANDARD\n baker ads meta preview --creative-id 6123 --placement facebook_reels_overlay --platform facebook\n baker ads meta preview --ad-id 9988 --ad-format INSTAGRAM_REELS --out-file /tmp/preview.html\n baker ads meta preview --account-id act_123 --creative '{\"object_story_spec\":{...}}' --ad-format MOBILE_FEED_STANDARD`,\n },\n args: {\n \"creative-id\": { type: \"string\", description: \"Existing creative ID\" },\n \"ad-id\": { type: \"string\", description: \"Existing ad ID\" },\n \"account-id\": { type: \"string\", description: \"Required when previewing an unpublished --creative spec\" },\n creative: { type: \"string\", description: \"JSON spec of an unpublished creative (e.g. object_story_spec)\" },\n \"ad-format\": { type: \"string\", description: \"Meta ad_format enum value (--list-formats to see them)\" },\n placement: {\n type: \"string\",\n description:\n \"platform_position from an insights breakdown (e.g. facebook_reels_overlay) — resolved to an ad_format\",\n },\n platform: { type: \"string\", description: \"facebook|instagram — required for --placement feed, which both report\" },\n \"list-formats\": { type: \"boolean\", description: \"Print the ad_format values and placement mappings, then exit\" },\n \"out-file\": { type: \"string\", description: \"Save iframe HTML to this path\" },\n \"no-cache\": NO_CACHE_ARG,\n },\n run: async ({ args }) => {\n if (args[\"list-formats\"]) {\n writeAdsJson({\n ok: true,\n data: {\n adFormats: VALID_AD_FORMATS,\n placements: { facebook: FACEBOOK_PREVIEW_FORMATS, instagram: INSTAGRAM_PREVIEW_FORMATS },\n },\n });\n return;\n }\n\n const placement = args.placement as string | undefined;\n const adFormat = placement ? resolvePlacement(placement, args.platform) : (args[\"ad-format\"] as string);\n if (!adFormat) {\n failPreviewValidation(\"pass --ad-format or --placement (see --list-formats)\");\n }\n if (!VALID_AD_FORMATS.includes(adFormat)) {\n failPreviewValidation(\n `Invalid --ad-format \"${adFormat}\". Meta publishes no complete ad_format enum, so this is the set we know: ${VALID_AD_FORMATS.join(\", \")}. To preview a placement you saw in an insights breakdown, pass --placement <platform_position> instead of guessing a format name.`,\n );\n }\n const body: Record<string, unknown> = { adFormat };\n if (args[\"creative-id\"]) body.creativeId = args[\"creative-id\"];\n if (args[\"ad-id\"]) body.adId = args[\"ad-id\"];\n if (args[\"account-id\"]) body.accountId = args[\"account-id\"];\n if (args.creative) body.creative = args.creative;\n if (args[\"no-cache\"]) body.skipCache = true;\n\n try {\n const data = await apiPost<Array<{ body: string }>>(\"/api/ads/meta/preview\", body);\n const html = data.map((d) => d.body).join(\"\\n\");\n const hints = placement\n ? [\n `Rendered ${placement} as ad_format ${adFormat}. Open the iframe to SEE it — Meta does not document what it renders for a creative a placement cannot take, so a preview you looked at is the evidence, and anything you did not look at stays unverified.`,\n ]\n : [];\n if (args[\"out-file\"]) {\n const summary = { ok: true as const, data: { file: args[\"out-file\"], rows: data.length, adFormat } };\n writeFileSync(args[\"out-file\"] as string, html, \"utf-8\");\n writeJsonEnvelope(hints.length > 0 ? { ...summary, hints } : summary);\n return;\n }\n writeJsonEnvelope(hints.length > 0 ? { ok: true, data, hints } : { ok: true, data });\n } catch (err) {\n handleMetaError(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAO9B,SAAS,qBAAqB;AAM9B,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,SAAS,sBAAsB,SAAwB;AACrD,eAAa,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,oBAAoB,QAAQ,EAAE,CAAC;AACxE,UAAQ,KAAK,CAAC;AAChB;AASA,SAAS,iBAAiB,UAAkB,UAA2B;AACrE,QAAM,cAAc,OAAO,aAAa,WAAW,SAAS,YAAY,IAAI;AAC5E,MAAI,eAAe,gBAAgB,cAAc,gBAAgB,aAAa;AAC5E,0BAAsB,0CAA0C;AAAA,EAClE;AACA,QAAM,SAAS,yBAAyB,UAAU,WAAW;AAC7D,MAAI,QAAQ;AACV,WAAO;AAAA,EACT;AACA,MAAI,0BAA0B,IAAI,QAAQ,KAAK,CAAC,aAAa;AAC3D;AAAA,MACE,eAAe,QAAQ;AAAA,IACzB;AAAA,EACF;AACA;AAAA,IACE,sDAAsD,QAAQ,qbAAgb,eAAe,CAAC;AAAA,EAChgB;AACF;AAEA,SAAS,iBAAyB;AAChC,QAAM,WAAW,OAAO,KAAK,wBAAwB,EAAE,KAAK,IAAI;AAChE,QAAM,YAAY,OAAO,KAAK,yBAAyB,EAAE,KAAK,IAAI;AAClE,SAAO,mBAAc,QAAQ,sBAAiB,SAAS;AACzD;AAEO,IAAM,iBAAiB,cAAc;AAAA,EAC1C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaf;AAAA,EACA,MAAM;AAAA,IACJ,eAAe,EAAE,MAAM,UAAU,aAAa,uBAAuB;AAAA,IACrE,SAAS,EAAE,MAAM,UAAU,aAAa,iBAAiB;AAAA,IACzD,cAAc,EAAE,MAAM,UAAU,aAAa,0DAA0D;AAAA,IACvG,UAAU,EAAE,MAAM,UAAU,aAAa,gEAAgE;AAAA,IACzG,aAAa,EAAE,MAAM,UAAU,aAAa,yDAAyD;AAAA,IACrG,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,IACJ;AAAA,IACA,UAAU,EAAE,MAAM,UAAU,aAAa,6EAAwE;AAAA,IACjH,gBAAgB,EAAE,MAAM,WAAW,aAAa,+DAA+D;AAAA,IAC/G,YAAY,EAAE,MAAM,UAAU,aAAa,gCAAgC;AAAA,IAC3E,YAAY;AAAA,EACd;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI,KAAK,cAAc,GAAG;AACxB,mBAAa;AAAA,QACX,IAAI;AAAA,QACJ,MAAM;AAAA,UACJ,WAAW;AAAA,UACX,YAAY,EAAE,UAAU,0BAA0B,WAAW,0BAA0B;AAAA,QACzF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAEA,UAAM,YAAY,KAAK;AACvB,UAAM,WAAW,YAAY,iBAAiB,WAAW,KAAK,QAAQ,IAAK,KAAK,WAAW;AAC3F,QAAI,CAAC,UAAU;AACb,4BAAsB,sDAAsD;AAAA,IAC9E;AACA,QAAI,CAAC,iBAAiB,SAAS,QAAQ,GAAG;AACxC;AAAA,QACE,wBAAwB,QAAQ,6EAA6E,iBAAiB,KAAK,IAAI,CAAC;AAAA,MAC1I;AAAA,IACF;AACA,UAAM,OAAgC,EAAE,SAAS;AACjD,QAAI,KAAK,aAAa,EAAG,MAAK,aAAa,KAAK,aAAa;AAC7D,QAAI,KAAK,OAAO,EAAG,MAAK,OAAO,KAAK,OAAO;AAC3C,QAAI,KAAK,YAAY,EAAG,MAAK,YAAY,KAAK,YAAY;AAC1D,QAAI,KAAK,SAAU,MAAK,WAAW,KAAK;AACxC,QAAI,KAAK,UAAU,EAAG,MAAK,YAAY;AAEvC,QAAI;AACF,YAAM,OAAO,MAAM,QAAiC,yBAAyB,IAAI;AACjF,YAAM,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AAC9C,YAAM,QAAQ,YACV;AAAA,QACE,YAAY,SAAS,iBAAiB,QAAQ;AAAA,MAChD,IACA,CAAC;AACL,UAAI,KAAK,UAAU,GAAG;AACpB,cAAM,UAAU,EAAE,IAAI,MAAe,MAAM,EAAE,MAAM,KAAK,UAAU,GAAG,MAAM,KAAK,QAAQ,SAAS,EAAE;AACnG,sBAAc,KAAK,UAAU,GAAa,MAAM,OAAO;AACvD,0BAAkB,MAAM,SAAS,IAAI,EAAE,GAAG,SAAS,MAAM,IAAI,OAAO;AACpE;AAAA,MACF;AACA,wBAAkB,MAAM,SAAS,IAAI,EAAE,IAAI,MAAM,MAAM,MAAM,IAAI,EAAE,IAAI,MAAM,KAAK,CAAC;AAAA,IACrF,SAAS,KAAK;AACZ,sBAAgB,GAAG;AAAA,IACrB;AAAA,EACF;AACF,CAAC;","names":[]}
|