@vercel/cli-support 65.4.0 → 65.5.0-snapshot-8a613d8ad85d
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 +22 -0
- package/dist/chunks/add-6UOKR26K.js +8 -0
- package/dist/chunks/add-GULZ6EGJ.js +8 -0
- package/dist/chunks/add-RPAOJH5O.js +8 -0
- package/dist/chunks/build-MLAKPRSC.js +7 -0
- package/dist/chunks/{chunk-ADLBLGT3.js → chunk-26QK3I2S.js} +1 -1
- package/dist/chunks/chunk-2BKALEOP.js +7 -0
- package/dist/chunks/chunk-2FHZYQPY.js +7 -0
- package/dist/chunks/{chunk-TIPQQ4TG.js → chunk-2QIJEHNE.js} +1 -1
- package/dist/chunks/{chunk-JP33AIDQ.js → chunk-36NK2Z3C.js} +1 -1
- package/dist/chunks/{chunk-D6REP5QQ.js → chunk-3E364MJE.js} +1 -1
- package/dist/chunks/{chunk-EEUJLJEJ.js → chunk-3H36RI7C.js} +1 -1
- package/dist/chunks/{chunk-JUSR7V2L.js → chunk-3NG2EYQ5.js} +1 -1
- package/dist/chunks/{chunk-AYUUSAB7.js → chunk-4G7ZQONX.js} +1 -1
- package/dist/chunks/{chunk-SYFG2RM6.js → chunk-4HJGSSSZ.js} +1 -1
- package/dist/chunks/{chunk-CWM2F235.js → chunk-55H6G46X.js} +1 -1
- package/dist/chunks/{chunk-6TXEVQA4.js → chunk-5CZNUB7Y.js} +1 -1
- package/dist/chunks/{chunk-ZN6CQWVP.js → chunk-5EMSOR2P.js} +1 -1
- package/dist/chunks/{chunk-NAX6IARA.js → chunk-5K426HWC.js} +1 -1
- package/dist/chunks/{chunk-773GOZIR.js → chunk-5SIC5273.js} +1 -1
- package/dist/chunks/chunk-5WYPJ2T5.js +25 -0
- package/dist/chunks/{chunk-MBEKRUTQ.js → chunk-6IATT2ID.js} +2 -2
- package/dist/chunks/{chunk-KPQLUGFI.js → chunk-6WMO5G45.js} +3 -3
- package/dist/chunks/{chunk-6OVX3PWM.js → chunk-75JI2SZX.js} +1 -1
- package/dist/chunks/{chunk-ECEDD646.js → chunk-7G4PQR6J.js} +1 -1
- package/dist/chunks/chunk-7SAEZ4NC.js +7 -0
- package/dist/chunks/{chunk-363SJ4TN.js → chunk-7VTPAXDC.js} +1 -1
- package/dist/chunks/chunk-A2UZ2O7H.js +7 -0
- package/dist/chunks/{chunk-3LIKVGFT.js → chunk-A3RU52F4.js} +1 -1
- package/dist/chunks/{chunk-CC6FLKIP.js → chunk-AIRQFG5A.js} +1 -1
- package/dist/chunks/{chunk-IOZ3I765.js → chunk-AOC6XXOO.js} +1 -1
- package/dist/chunks/{chunk-EISD3RG7.js → chunk-ARQMFBV4.js} +1 -1
- package/dist/chunks/{chunk-UHBMX3OK.js → chunk-AUY363W7.js} +1 -1
- package/dist/chunks/chunk-BGWS5R5R.js +9 -0
- package/dist/chunks/chunk-C6IITJ5S.js +7 -0
- package/dist/chunks/{chunk-OHEOYFBU.js → chunk-CLVEFWEX.js} +1 -1
- package/dist/chunks/{chunk-KGBIRIFF.js → chunk-CU2FTX57.js} +1 -1
- package/dist/chunks/{chunk-YHULP2KK.js → chunk-CWO4HMKU.js} +1 -1
- package/dist/chunks/{chunk-EU2GBIPC.js → chunk-CZINAGH6.js} +1 -1
- package/dist/chunks/{chunk-QIVX6SCR.js → chunk-DAUAVRFC.js} +1 -1
- package/dist/chunks/{chunk-GA277JFB.js → chunk-DPM33VFZ.js} +1 -1
- package/dist/chunks/{chunk-Q5ODLDCU.js → chunk-DSY2S2YT.js} +1 -1
- package/dist/chunks/{chunk-XP3FT56R.js → chunk-DWOJP4ST.js} +3 -3
- package/dist/chunks/chunk-ED3VA7D4.js +7 -0
- package/dist/chunks/{chunk-GG5RME4X.js → chunk-EE2FTI3R.js} +1 -1
- package/dist/chunks/{chunk-QVZAAMGQ.js → chunk-EFEQQXRU.js} +1 -1
- package/dist/chunks/{chunk-DKJL2KV7.js → chunk-EPO7P734.js} +1 -1
- package/dist/chunks/{chunk-7QAGSRCU.js → chunk-EQT2VHL2.js} +1 -1
- package/dist/chunks/chunk-ETEVOJQJ.js +8 -0
- package/dist/chunks/chunk-EWP5WICJ.js +10 -0
- package/dist/chunks/chunk-F22QLVTX.js +7 -0
- package/dist/chunks/{chunk-XC46OAAT.js → chunk-FAEC4BER.js} +1 -1
- package/dist/chunks/{chunk-LSQREJXO.js → chunk-FAELJM4F.js} +1 -1
- package/dist/chunks/{chunk-7R6TRRG5.js → chunk-FNA4MIOH.js} +1 -1
- package/dist/chunks/{chunk-L3JYCXVB.js → chunk-GFD6UAAO.js} +2 -2
- package/dist/chunks/{chunk-U2OBPULW.js → chunk-GP55VEOQ.js} +1 -1
- package/dist/chunks/{chunk-FSPPKNKN.js → chunk-GVPVWHFK.js} +1 -1
- package/dist/chunks/{chunk-527GBU3K.js → chunk-HMWDOAWO.js} +1 -1
- package/dist/chunks/{chunk-7L2K4OKM.js → chunk-HVDGNAPM.js} +1 -1
- package/dist/chunks/{chunk-QVHXFHBV.js → chunk-I2WEQWCA.js} +1 -1
- package/dist/chunks/{chunk-JRPNHWA3.js → chunk-IC3THLYP.js} +1 -1
- package/dist/chunks/{chunk-IQKGQ2Y2.js → chunk-J6L5MDTX.js} +1 -1
- package/dist/chunks/{chunk-YMZ6WBKB.js → chunk-JCGEXU7T.js} +3 -3
- package/dist/chunks/{chunk-7L5QUDUR.js → chunk-JGMJP4T3.js} +1 -1
- package/dist/chunks/{chunk-ZQBSAMFL.js → chunk-JHNLBVO2.js} +1 -1
- package/dist/chunks/{chunk-HTXDC7E2.js → chunk-JMLKK7RL.js} +2 -2
- package/dist/chunks/{chunk-T6243EDS.js → chunk-JSAY52FE.js} +1 -1
- package/dist/chunks/{chunk-C7FQMC6D.js → chunk-JWUXHL35.js} +1 -1
- package/dist/chunks/{chunk-KQCROPL3.js → chunk-JXAEI2GJ.js} +1 -1
- package/dist/chunks/{chunk-VNIKIQVE.js → chunk-KHADRPBJ.js} +1 -1
- package/dist/chunks/{chunk-GCZVIDNG.js → chunk-KWKEBKUR.js} +1 -1
- package/dist/chunks/chunk-KY7LDQRX.js +7 -0
- package/dist/chunks/{chunk-YEZJNXQX.js → chunk-L4XLDN6T.js} +1 -1
- package/dist/chunks/{chunk-EGNR2DEI.js → chunk-LOO42IMZ.js} +1 -1
- package/dist/chunks/{chunk-CBVKB3DT.js → chunk-LT5UZRMK.js} +1 -1
- package/dist/chunks/{chunk-FUX6LKNP.js → chunk-LUX4PBJL.js} +1 -1
- package/dist/chunks/chunk-M7LUSXMG.js +7 -0
- package/dist/chunks/{chunk-ANMDN3EG.js → chunk-MFW6IJIK.js} +1 -1
- package/dist/chunks/{chunk-UGNIIDHR.js → chunk-MLGQ233X.js} +1 -1
- package/dist/chunks/chunk-MY4MONOH.js +7 -0
- package/dist/chunks/{chunk-N6JBQMOF.js → chunk-MZQEDXOH.js} +1 -1
- package/dist/chunks/chunk-N5CXIFE2.js +7 -0
- package/dist/chunks/{chunk-LQVSU5HR.js → chunk-NM44RWS6.js} +1 -1
- package/dist/chunks/{chunk-FHU2O7ZJ.js → chunk-NVNE3W7S.js} +1 -1
- package/dist/chunks/chunk-NZPGWZLV.js +9 -0
- package/dist/chunks/{chunk-462YCCJZ.js → chunk-O7COT3YB.js} +1 -1
- package/dist/chunks/{chunk-KY335KWI.js → chunk-ODAV7Z2H.js} +1 -1
- package/dist/chunks/{chunk-HCRD3JFL.js → chunk-OKNDHNH6.js} +1 -1
- package/dist/chunks/{chunk-Q4KTAQB3.js → chunk-OQX4YVGU.js} +1 -1
- package/dist/chunks/chunk-ORJBK5FT.js +9 -0
- package/dist/chunks/{chunk-5KUUMQ3M.js → chunk-OTYF3ZZW.js} +1 -1
- package/dist/chunks/{chunk-FGFLTLEA.js → chunk-P6ZTEDX2.js} +1 -1
- package/dist/chunks/{chunk-O72YDZKD.js → chunk-PHHZ6J7Q.js} +1 -1
- package/dist/chunks/{chunk-RMZTB2IU.js → chunk-PRFIFS3Q.js} +1 -1
- package/dist/chunks/{chunk-R2XHJDAP.js → chunk-QDPYU6KS.js} +1 -1
- package/dist/chunks/{chunk-JLEJB6KM.js → chunk-QHM6OK76.js} +1 -1
- package/dist/chunks/{chunk-CR3NBTHV.js → chunk-QNL22LAW.js} +1 -1
- package/dist/chunks/{chunk-5V53NA6C.js → chunk-QUSEBFDO.js} +1 -1
- package/dist/chunks/{chunk-DQ2SVW4R.js → chunk-R3BEQTZZ.js} +1 -1
- package/dist/chunks/{chunk-BUJITHGZ.js → chunk-RCUDI7OF.js} +1 -1
- package/dist/chunks/{chunk-Y5ZMKL7E.js → chunk-RMW2FDXS.js} +1 -1
- package/dist/chunks/{chunk-KRPY5FHJ.js → chunk-RQVIMYKN.js} +1 -1
- package/dist/chunks/chunk-RWPQOJTT.js +22 -0
- package/dist/chunks/{chunk-2TUVL6WE.js → chunk-SDOPVIKJ.js} +1 -1
- package/dist/chunks/{chunk-3XW7N4W3.js → chunk-SKSOCUDZ.js} +1 -1
- package/dist/chunks/chunk-SLDWAIO3.js +18 -0
- package/dist/chunks/{chunk-JWCEHQQF.js → chunk-SW3JRXUW.js} +1 -1
- package/dist/chunks/{chunk-M2NXKZKX.js → chunk-TGOGYSBO.js} +1 -1
- package/dist/chunks/chunk-TZT3VYZ3.js +7 -0
- package/dist/chunks/{chunk-F6EBOT64.js → chunk-UJQ6PBRF.js} +1 -1
- package/dist/chunks/{chunk-BVGGTBYE.js → chunk-UWMPVTXG.js} +1 -1
- package/dist/chunks/{chunk-R6BEOVTU.js → chunk-VAWZZK3Y.js} +1 -1
- package/dist/chunks/{chunk-4N6LMERQ.js → chunk-VLYVVC3P.js} +11 -11
- package/dist/chunks/{chunk-HSFKISDH.js → chunk-VQ755MPP.js} +1 -1
- package/dist/chunks/{chunk-QB7F3UAP.js → chunk-VUQWLLNI.js} +1 -1
- package/dist/chunks/chunk-VWHIWUGJ.js +7 -0
- package/dist/chunks/chunk-WDUHDLUA.js +14 -0
- package/dist/chunks/{chunk-K5U47EVH.js → chunk-WICRM2JL.js} +1 -1
- package/dist/chunks/{chunk-KJA2GKPT.js → chunk-WSVYZKI6.js} +1 -1
- package/dist/chunks/{chunk-N2FLYCCO.js → chunk-XAU3KTPX.js} +1 -1
- package/dist/chunks/chunk-XCKUJZUG.js +10 -0
- package/dist/chunks/{chunk-WDXW6A4H.js → chunk-XE24Y6NM.js} +2 -2
- package/dist/chunks/{chunk-RW3X523R.js → chunk-XSQVCDSD.js} +1 -1
- package/dist/chunks/{chunk-KW6GSQXV.js → chunk-XTKGBVSF.js} +1 -1
- package/dist/chunks/{chunk-2K3ISCQ6.js → chunk-YALEYPMP.js} +1 -1
- package/dist/chunks/chunk-YCJHUYBJ.js +19 -0
- package/dist/chunks/{chunk-TEYREL44.js → chunk-YIRSRF6D.js} +1 -1
- package/dist/chunks/chunk-YQDOADMG.js +10 -0
- package/dist/chunks/{chunk-PFPJLIFF.js → chunk-YT3QAZQF.js} +1 -1
- package/dist/chunks/{chunk-R2BUF6Z7.js → chunk-ZQUVDDPB.js} +1 -1
- package/dist/chunks/{chunk-XVDRGWXM.js → chunk-ZUNQHI5Y.js} +1 -1
- package/dist/chunks/{chunk-KQCFC2JL.js → chunk-ZUYPTLVO.js} +1 -1
- package/dist/chunks/clear-UZWOOGOH.js +8 -0
- package/dist/chunks/compile-vercel-config-2RQDL3RD.js +7 -0
- package/dist/chunks/config-C76IGJ6B.js +8 -0
- package/dist/chunks/config-RMJWRS7O.js +7 -0
- package/dist/chunks/{connect-git-provider-FS5Q2HO4.js → connect-git-provider-IQ7N2NPY.js} +1 -1
- package/dist/chunks/delete-2WBR5JQW.js +9 -0
- package/dist/chunks/delete-OKOBDL7Z.js +10 -0
- package/dist/chunks/{detect-projects-OD4JEAW2.js → detect-projects-XPB3R7VS.js} +1 -1
- package/dist/chunks/detect-services-DRHV22O5.js +7 -0
- package/dist/chunks/disable-DFEABU2Z.js +7 -0
- package/dist/chunks/discard-KGBEMNFT.js +14 -0
- package/dist/chunks/edit-5XIRLUKG.js +9 -0
- package/dist/chunks/edit-PJIDMKUS.js +8 -0
- package/dist/chunks/enable-UDWDPFOI.js +7 -0
- package/dist/chunks/{exec-OZSY46V6.js → exec-PX4GTZNE.js} +1 -1
- package/dist/chunks/{export-EPLYZF2Q.js → export-W75EA6EQ.js} +1 -1
- package/dist/chunks/future-PHSAEQIE.js +7 -0
- package/dist/chunks/generate-cert-for-deploy-C67VL5Z6.js +7 -0
- package/dist/chunks/image-U5CV2PRP.js +7 -0
- package/dist/chunks/import-builders-PHIIX7HW.js +7 -0
- package/dist/chunks/inspect-AU3MX7E2.js +13 -0
- package/dist/chunks/{inspect-CZ7WXYE5.js → inspect-DQQI3PM7.js} +1 -1
- package/dist/chunks/inspect-LJK7I6RZ.js +9 -0
- package/dist/chunks/{inspect-T2AIREYK.js → inspect-RNWLPR7I.js} +1 -1
- package/dist/chunks/{inspect-HFDGZNWC.js → inspect-WHPWW4BI.js} +1 -1
- package/dist/chunks/list-JV26NNYL.js +16 -0
- package/dist/chunks/{list-ON4YTQRN.js → list-QNRFVMMQ.js} +1 -1
- package/dist/chunks/list-YF4FXWUZ.js +12 -0
- package/dist/chunks/login-A4KNOUNA.js +9 -0
- package/dist/chunks/login-COGE7JQU.js +7 -0
- package/dist/chunks/logs-KMQATUYR.js +7 -0
- package/dist/chunks/{ls-FK5XEJEU.js → ls-DTFLHFOW.js} +1 -1
- package/dist/chunks/{ls-A7K4XDQB.js → ls-FOKMPVIB.js} +1 -1
- package/dist/chunks/ls-HMYU2ZGA.js +11 -0
- package/dist/chunks/{ls-2HUJHVLA.js → ls-IHF33MQP.js} +1 -1
- package/dist/chunks/{ls-QGUKJJY5.js → ls-QD54I4S7.js} +1 -1
- package/dist/chunks/{ls-3DVM5HLK.js → ls-RNRMYD3V.js} +1 -1
- package/dist/chunks/ls-ZQLCDIQJ.js +8 -0
- package/dist/chunks/mutate-RMIFQOF6.js +9 -0
- package/dist/chunks/notifications-BFBNV2HY.js +7 -0
- package/dist/chunks/open-L6HEXHAI.js +7 -0
- package/dist/chunks/openapi-6JKCOR7K.js +7 -0
- package/dist/chunks/permissions-UYGTYRKA.js +7 -0
- package/dist/chunks/{plugin-offer-TEGYA3TA.js → plugin-offer-NBHRXMNR.js} +1 -1
- package/dist/chunks/prompt-missing-credentials-2IYIF2JI.js +7 -0
- package/dist/chunks/publish-T2VSTPG4.js +15 -0
- package/dist/chunks/pull-4GL47Z2S.js +7 -0
- package/dist/chunks/purchase-domain-if-available-BHFBD3LW.js +7 -0
- package/dist/chunks/push-CQPIDVTL.js +7 -0
- package/dist/chunks/{query-FXXLX6UB.js → query-HN45ORIB.js} +1 -1
- package/dist/chunks/reauthenticate-FTHGAWK3.js +7 -0
- package/dist/chunks/reorder-7BD5JZKQ.js +10 -0
- package/dist/chunks/reply-2INQJ5KM.js +9 -0
- package/dist/chunks/resolve-DHAJC3I7.js +12 -0
- package/dist/chunks/resolve-agent-team-KGYPHN5F.js +7 -0
- package/dist/chunks/restore-OQKNWEFQ.js +16 -0
- package/dist/chunks/rm-CTP4UZH7.js +8 -0
- package/dist/chunks/rm-GFHEXQQW.js +8 -0
- package/dist/chunks/rm-OG3OXA6H.js +8 -0
- package/dist/chunks/rm-PFZYHXEN.js +8 -0
- package/dist/chunks/rm-XAW3WJ3I.js +8 -0
- package/dist/chunks/{routes-PKTWMDWQ.js → routes-XKEWEA3P.js} +1 -1
- package/dist/chunks/rule-inspect-MKQE5IVJ.js +8 -0
- package/dist/chunks/{schema-ZWE5MNMG.js → schema-TFN5PSYE.js} +2 -2
- package/dist/chunks/schema-XFER2RCF.js +14 -0
- package/dist/chunks/select-org-PFTR6HQZ.js +7 -0
- package/dist/chunks/set-KWOZNGRL.js +7 -0
- package/dist/chunks/setup-and-link-BRYK42L7.js +7 -0
- package/dist/chunks/{skills-RKIGVVNM.js → skills-2MOFBKIE.js} +1 -1
- package/dist/chunks/tags-BHZUQTOQ.js +7 -0
- package/dist/chunks/{types-YM7TMHXW.js → types-IWO5QLAV.js} +1 -1
- package/dist/chunks/{update-BGDQ5TXO.js → update-LP7ZZUFZ.js} +1 -1
- package/dist/commands/build/index.js +2 -2
- package/dist/commands/deploy/index.js +8 -8
- package/dist/commands/dev/index.js +6 -6
- package/dist/commands/env/index.js +3 -3
- package/dist/commands/link/index.js +2 -2
- package/dist/commands/list/index.js +1 -1
- package/dist/commands/project/index.js +4 -4
- package/dist/commands-account.js +18 -18
- package/dist/commands-ai.js +12 -12
- package/dist/commands-blob.js +7 -7
- package/dist/commands-core.js +23 -23
- package/dist/commands-deployments.js +3 -3
- package/dist/commands-flags.js +29 -29
- package/dist/commands-integrations.js +98 -83
- package/dist/commands-observability.js +4 -4
- package/dist/commands-routing.js +23 -23
- package/dist/help.js +1 -1
- package/dist/index.js +7 -7
- package/dist/internal-build.js +2 -2
- package/dist/native-download.js +7 -0
- package/dist/package.json +27 -26
- package/dist/root-help-commands.mjs +1 -1
- package/dist/vc.js +172 -17
- package/dist/version.mjs +1 -1
- package/package.json +20 -19
- package/dist/chunks/add-7NS6HIWC.js +0 -8
- package/dist/chunks/add-NMYFDVXW.js +0 -8
- package/dist/chunks/add-PMJ5BECU.js +0 -8
- package/dist/chunks/build-BCY6HQJG.js +0 -7
- package/dist/chunks/chunk-5IWFRZQT.js +0 -10
- package/dist/chunks/chunk-6I6QJHCY.js +0 -7
- package/dist/chunks/chunk-6VH56CX2.js +0 -19
- package/dist/chunks/chunk-6YXIWZ3X.js +0 -25
- package/dist/chunks/chunk-7E3WREH5.js +0 -7
- package/dist/chunks/chunk-EAXMWCOL.js +0 -63
- package/dist/chunks/chunk-EKZTFGDX.js +0 -7
- package/dist/chunks/chunk-FLHO75XC.js +0 -8
- package/dist/chunks/chunk-GYVJIIYL.js +0 -7
- package/dist/chunks/chunk-JLE7K4SY.js +0 -9
- package/dist/chunks/chunk-KCKYPLIH.js +0 -7
- package/dist/chunks/chunk-LOBA3E72.js +0 -7
- package/dist/chunks/chunk-LW4N3CW6.js +0 -9
- package/dist/chunks/chunk-NGKO2OOU.js +0 -8
- package/dist/chunks/chunk-NW7WWUCQ.js +0 -9
- package/dist/chunks/chunk-O4WNSKQR.js +0 -15
- package/dist/chunks/chunk-OZCQTXI4.js +0 -7
- package/dist/chunks/chunk-QVXS234E.js +0 -7
- package/dist/chunks/chunk-SLGUYM42.js +0 -10
- package/dist/chunks/chunk-TAISZMA2.js +0 -7
- package/dist/chunks/chunk-WEH6XC4Y.js +0 -22
- package/dist/chunks/chunk-WVHCBDTB.js +0 -7
- package/dist/chunks/clear-FKVWDCVA.js +0 -8
- package/dist/chunks/compile-vercel-config-GWAJE44R.js +0 -7
- package/dist/chunks/config-5WVLG5SE.js +0 -8
- package/dist/chunks/config-RMOHN5YT.js +0 -7
- package/dist/chunks/delete-5WMB4WFR.js +0 -9
- package/dist/chunks/delete-EM4JZPFA.js +0 -10
- package/dist/chunks/detect-services-BSJGB4RM.js +0 -7
- package/dist/chunks/disable-QOM7UHQC.js +0 -7
- package/dist/chunks/discard-L5ZH7P5B.js +0 -14
- package/dist/chunks/edit-F3VJGCG2.js +0 -9
- package/dist/chunks/edit-TM7YCWBU.js +0 -8
- package/dist/chunks/enable-72C3QX34.js +0 -7
- package/dist/chunks/future-V77DRMQG.js +0 -7
- package/dist/chunks/generate-cert-for-deploy-Y3YHBMPU.js +0 -7
- package/dist/chunks/image-CVXEXU5R.js +0 -7
- package/dist/chunks/import-builders-PGRKJOOE.js +0 -7
- package/dist/chunks/inspect-BTRNXRJT.js +0 -9
- package/dist/chunks/inspect-FGDVWAQP.js +0 -13
- package/dist/chunks/list-CKRRHAOE.js +0 -12
- package/dist/chunks/list-FLREMGJR.js +0 -16
- package/dist/chunks/login-55LJ5ZA6.js +0 -9
- package/dist/chunks/login-DQRZSD4Z.js +0 -7
- package/dist/chunks/logs-2HQXWOHM.js +0 -7
- package/dist/chunks/ls-4B3QYHCI.js +0 -8
- package/dist/chunks/ls-VTKHPDWS.js +0 -11
- package/dist/chunks/mutate-7ADZBCZM.js +0 -9
- package/dist/chunks/notifications-XZJXE2K4.js +0 -7
- package/dist/chunks/open-EE5IZQD7.js +0 -7
- package/dist/chunks/openapi-QBX62ZXC.js +0 -7
- package/dist/chunks/permissions-VYJ4LL5R.js +0 -7
- package/dist/chunks/prompt-missing-credentials-VP6OVCFM.js +0 -7
- package/dist/chunks/publish-2HEK5UMJ.js +0 -15
- package/dist/chunks/pull-WRTTSY7J.js +0 -7
- package/dist/chunks/purchase-domain-if-available-6S3NLTUI.js +0 -7
- package/dist/chunks/push-L3QRGGLC.js +0 -7
- package/dist/chunks/reauthenticate-IXQDC4UZ.js +0 -7
- package/dist/chunks/reorder-B4OXSYCI.js +0 -10
- package/dist/chunks/reply-F637K6XH.js +0 -9
- package/dist/chunks/resolve-E3F6NYQZ.js +0 -12
- package/dist/chunks/resolve-agent-team-EIPCH766.js +0 -7
- package/dist/chunks/restore-Q25KRZPH.js +0 -16
- package/dist/chunks/rm-FWD2NUGX.js +0 -8
- package/dist/chunks/rm-JMQ4QKCC.js +0 -8
- package/dist/chunks/rm-PPG7P3GN.js +0 -8
- package/dist/chunks/rm-SH3DYKNS.js +0 -8
- package/dist/chunks/rm-UEBLKFVC.js +0 -8
- package/dist/chunks/rule-inspect-LKQA5I4V.js +0 -8
- package/dist/chunks/schema-FBV42W7N.js +0 -14
- package/dist/chunks/select-org-WMB752Z6.js +0 -7
- package/dist/chunks/set-UTYIPOLC.js +0 -7
- package/dist/chunks/setup-and-link-ZLY5XQW5.js +0 -7
- package/dist/chunks/tags-UCLZ5UMX.js +0 -7
package/dist/commands-flags.js
CHANGED
|
@@ -4,10 +4,10 @@ import { dirname as __dirname_ } from 'node:path';
|
|
|
4
4
|
const require = __createRequire(import.meta.url);
|
|
5
5
|
const __filename = __fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = __dirname_(__filename);
|
|
7
|
-
import{FILTER_DEPRECATION_WARNING,alignTimeRangeToGranularity,canonicalResponseToMetricsResponse,createCanonicalMetricsRequest,usesODataSyntax}from"./chunks/chunk-Q4KTAQB3.js";import{init_dist,prepareFlagsDefinitions}from"./chunks/chunk-OAM5NJCU.js";import{EncryptJWT,base64url_exports,jwtDecrypt}from"./chunks/chunk-S3L2OHPO.js";import{require_fast_deep_equal}from"./chunks/chunk-MCRKBVZA.js";import{sanitizeForTerminal}from"./chunks/chunk-5RMIM4S2.js";import{getLinkedFlagsProject,getProjectNameFromFlags}from"./chunks/chunk-JRPNHWA3.js";import{parseSubcommandArguments,requireProjectContext}from"./chunks/chunk-YEZJNXQX.js";import{computeGranularity,formatText,generateSparkline}from"./chunks/chunk-XVDRGWXM.js";import{OBSERVABILITY_METRICS_PATH,getRollupColumnName,handleApiError}from"./chunks/chunk-CC6FLKIP.js";import"./chunks/chunk-IVSSTHB6.js";import{require_dist}from"./chunks/chunk-JELLVPCM.js";import{readStdinText}from"./chunks/chunk-PSOVLGHP.js";import{require_raw_body}from"./chunks/chunk-XOETL6DB.js";import{normalizeRepeatableStringFilters,outputError,resolveTimeRange,validateIntegerRangeWithDefault,validateTimeBound,validateTimeOrder}from"./chunks/chunk-RW3X523R.js";import{ellipsizeMiddle,truncateEnd}from"./chunks/chunk-ID663OJ7.js";import{formatDate}from"./chunks/chunk-HRR57QNP.js";import{formatTable}from"./chunks/chunk-LSQREJXO.js";import{stamp_default}from"./chunks/chunk-A2RZZQEP.js";import"./chunks/chunk-Q7D7RGXM.js";import"./chunks/chunk-GZNDA6SV.js";import{resolveProjectContext}from"./chunks/chunk-JP33AIDQ.js";import{STANDARD_ENVIRONMENTS}from"./chunks/chunk-7YKFF6CE.js";import{formatProject}from"./chunks/chunk-6OVX3PWM.js";import{require_open}from"./chunks/chunk-PVASGBEF.js";import"./chunks/chunk-2TUVL6WE.js";import"./chunks/chunk-7EJQLVWX.js";import{readOnOffOption}from"./chunks/chunk-Y5ZMKL7E.js";import{canPrompt}from"./chunks/chunk-IQ7FPAI4.js";import{getCommandFlags}from"./chunks/chunk-XGTKHQTT.js";import{printNextPageCommand}from"./chunks/chunk-VNIKIQVE.js";import"./chunks/chunk-PFD7LETF.js";import{getInvalidSubcommand}from"./chunks/chunk-TG2RCYTH.js";import{getRenamedOption,reportRenamedOptionError,withWarnings}from"./chunks/chunk-T6243EDS.js";import{getSubcommand}from"./chunks/chunk-ETV3C2CV.js";import{FLAG_ATTRIBUTE_TYPES,FLAG_CONDITION_LIST_COMPARATORS,FLAG_CONDITION_RHS_OPTIONAL_COMPARATORS,FLAG_EVALUATIONS_DIMENSIONS,FLAG_EVALUATIONS_DIMENSION_NAMES,FLAG_EVALUATIONS_GRANULARITIES,alertsInspectSubcommand,alertsListSubcommand,alertsSubcommand,archiveSubcommand,attackModeDisableSubcommand,attackModeEnableSubcommand,attackModeSubcommand,botManagementSubcommand,connectionsAddSubcommand,connectionsListSubcommand,connectionsRemoveSubcommand,connectionsSubcommand,createSubcommand6 as createSubcommand,datafileSubcommand,diffSubcommand,disableSubcommand,discardSubcommand,enableSubcommand2 as enableSubcommand,entitiesCreateSubcommand,entitiesListSubcommand,entitiesRemoveSubcommand,entitiesSubcommand,entitiesUpdateSubcommand,evaluationsSubcommand,feedbackCommand,firewallCommand,flagsCommand,formatFlagAttributeTypeList,formatFlagConditionComparator,formatFlagConditionComparatorList,getCommandAliases,getFlagAttributeType,inspectSubcommand9 as inspectSubcommand,ipBlocksBlockSubcommand,ipBlocksListSubcommand,ipBlocksSubcommand,ipBlocksUnblockSubcommand,isBucketingAttribute,isFlagAttributeType,isFlagEvaluationsDimension,isFlagEvaluationsGranularity,isTimestampAttributeType,labelsListSubcommand,labelsSubcommand,listSubcommand14 as listSubcommand,openSubcommand3 as openSubcommand,overrideSubcommand,overviewSubcommand,persistentActionsInspectSubcommand,persistentActionsListSubcommand,persistentActionsSubcommand,prepareSubcommand,publishSubcommand,removeSubcommand8 as removeSubcommand,rolloutSubcommand,rulesAddSubcommand2 as rulesAddSubcommand,rulesAddSubcommand3 as rulesAddSubcommand2,rulesDisableSubcommand,rulesEditSubcommand2 as rulesEditSubcommand,rulesEnableSubcommand,rulesInspectSubcommand,rulesListSubcommand2 as rulesListSubcommand,rulesListSubcommand3 as rulesListSubcommand2,rulesMoveSubcommand,rulesRemoveSubcommand2 as rulesRemoveSubcommand,rulesRemoveSubcommand3 as rulesRemoveSubcommand2,rulesReorderSubcommand,rulesSubcommand2 as rulesSubcommand,rulesSubcommand3 as rulesSubcommand2,rulesUpdateSubcommand,sdkKeysAddSubcommand,sdkKeysListSubcommand,sdkKeysRemoveSubcommand,sdkKeysSubcommand,segmentsCreateSubcommand,segmentsInspectSubcommand,segmentsListSubcommand,segmentsRemoveSubcommand,segmentsSubcommand,segmentsUpdateSubcommand,setSubcommand2 as setSubcommand,splitSubcommand,staleSubcommand,statusSubcommand,systemBypassAddSubcommand,systemBypassListSubcommand,systemBypassRemoveSubcommand,systemBypassSubcommand,systemMitigationsPauseSubcommand,systemMitigationsResumeSubcommand,systemMitigationsSubcommand,targetingEnableSubcommand,targetingSubcommand,targetsAddSubcommand,targetsListSubcommand,targetsRemoveSubcommand,targetsSubcommand,trafficInspectSubcommand,trafficListSubcommand,trafficSubcommand,unarchiveSubcommand,updateSubcommand5 as updateSubcommand,useTargetingSubcommand,versionsDiffSubcommand,versionsListSubcommand,versionsSubcommand}from"./chunks/chunk-O4WNSKQR.js";import"./chunks/chunk-6I6QJHCY.js";import"./chunks/chunk-EKZTFGDX.js";import"./chunks/chunk-462YCCJZ.js";import"./chunks/chunk-WVHCBDTB.js";import"./chunks/chunk-TAISZMA2.js";import"./chunks/chunk-527GBU3K.js";import"./chunks/chunk-CR3NBTHV.js";import"./chunks/chunk-BVGGTBYE.js";import"./chunks/chunk-6TXEVQA4.js";import"./chunks/chunk-5KUUMQ3M.js";import"./chunks/chunk-UHBMX3OK.js";import"./chunks/chunk-EEUJLJEJ.js";import"./chunks/chunk-NW7WWUCQ.js";import"./chunks/chunk-F6EBOT64.js";import"./chunks/chunk-LFOWP74R.js";import"./chunks/chunk-LOBA3E72.js";import"./chunks/chunk-7R6TRRG5.js";import"./chunks/chunk-JALVF3C2.js";import"./chunks/chunk-OZCQTXI4.js";import"./chunks/chunk-FSPPKNKN.js";import{help}from"./chunks/chunk-FLHO75XC.js";import{table}from"./chunks/chunk-773GOZIR.js";import{printError}from"./chunks/chunk-HSFKISDH.js";import"./chunks/chunk-67GZ5REA.js";import"./chunks/chunk-BS32OUOC.js";import{TelemetryClient}from"./chunks/chunk-6YXIWZ3X.js";import"./chunks/chunk-PUKYAALC.js";import{getScope}from"./chunks/chunk-K5U47EVH.js";import{require_ms}from"./chunks/chunk-MXTC4ZAQ.js";import"./chunks/chunk-NWGBDBZI.js";import{AGENT_REASON,AGENT_STATUS,buildCommandWithGlobalFlags,buildCommandWithYes,clientObservabilityPlanRecovery,getExitCodeForReason,outputAgentError,shouldEmitNonInteractiveCommandError,writeActionRequired,writeAgentError}from"./chunks/chunk-WDXW6A4H.js";import"./chunks/chunk-DKJL2KV7.js";import{getProjectByNameOrId,require_pluralize,ua_default}from"./chunks/chunk-4N6LMERQ.js";import{formatAlignedLabel,printAlignedLabel}from"./chunks/chunk-ADLBLGT3.js";import"./chunks/chunk-CWM2F235.js";import"./chunks/chunk-4NTBYNFR.js";import{parseArguments}from"./chunks/chunk-KCKYPLIH.js";import{quoteArg,teamCache}from"./chunks/chunk-F53OKXYI.js";import{SDK_KEY_PATTERN,getFlagsSpecification,getGlobalFlagsFromArgs,getProjectOptionFromArgs,warnDeprecatedInput,warnDeprecatedOption,warnDeprecatedSubcommand}from"./chunks/chunk-QVXS234E.js";import{fetch,toNodeReadable}from"./chunks/chunk-FUX6LKNP.js";import"./chunks/chunk-OPORM35X.js";import"./chunks/chunk-4SAVH3H7.js";import{ProjectNotFound,isAPIError}from"./chunks/chunk-6VH56CX2.js";import{cmd,getCommandName,getCommandNamePlain,packageName}from"./chunks/chunk-JESNVRVR.js";import{output_manager_default,recordCliError}from"./chunks/chunk-XP3FT56R.js";import"./chunks/chunk-BLUPZPAS.js";import"./chunks/chunk-RM3ZDRYE.js";import{pkg_default}from"./chunks/chunk-OO572JUC.js";import"./chunks/chunk-D3AHZ5LI.js";import"./chunks/chunk-2GHZGOWT.js";import"./chunks/chunk-YHPPP3SF.js";import{require_source}from"./chunks/chunk-NB2WLB3J.js";import"./chunks/chunk-ISWW3DKF.js";import"./chunks/chunk-BRQUZ5NC.js";import{__toESM}from"./chunks/chunk-BZENIQ7N.js";var import_raw_body=__toESM(require_raw_body(),1);var FeedbackTelemetryClient=class extends TelemetryClient{trackCliArgumentNote(note){note!==void 0&&this.trackCliArgument({arg:"note",value:this.redactedValue})}trackCliOptionField(fields){fields?.length&&this.trackCliOption({option:"field",value:this.redactedValue})}};var FEEDBACK_URL="https://vercel.com/api/feedback/cli",MAX_FEEDBACK_BYTES=1024*1024,FETCH_TIMEOUT_MS=1e4;async function feedback(client){let fail=(reason,message,code)=>(recordCliError({code:reason}),output_manager_default.error(message),code),parsed;try{parsed=parseArguments(client.argv.slice(2),getFlagsSpecification(feedbackCommand.options))}catch{return fail(AGENT_REASON.INVALID_ARGUMENTS,"Invalid feedback arguments. Run vercel feedback --help for usage.",2)}let notes=parsed.args.slice(1),fields=parsed.flags["--field"]??[];if(notes.length===0&&fields.length===0)return client.stdout.write(help(feedbackCommand,{columns:client.stderr.columns})),0;if(notes.length>1)return fail(AGENT_REASON.INVALID_ARGUMENTS,"Pass one note. Quote notes containing spaces, or use vercel feedback - to read stdin.",2);let telemetry=new FeedbackTelemetryClient({opts:{store:client.telemetryEventStore}});telemetry.trackCliArgumentNote(notes[0]),telemetry.trackCliOptionField(fields);let data=Object.create(null);for(let field of fields){let separator=field.indexOf("="),key=field.slice(0,separator).trim();if(separator<1||key==="")return fail(AGENT_REASON.INVALID_ARGUMENTS,"Each --field needs a non-empty key followed by =value. Example: vercel feedback --field topic=deploy.",2);data[key]=field.slice(separator+1)}if(notes.length&&Object.hasOwn(data,"note"))return fail(AGENT_REASON.INVALID_ARGUMENTS,"Provide the note once: use a positional note or --field note=..., rather than both.",2);if(notes[0]==="-"){if(client.stdin.isTTY)return fail(AGENT_REASON.INVALID_ARGUMENTS,"No input was piped to stdin. Pipe a note with: cat notes.md | vercel feedback -",2);try{data.note=await readStdinText(client.stdin,MAX_FEEDBACK_BYTES)}catch(error){return error.type==="entity.too.large"?fail(AGENT_REASON.INVALID_ARGUMENTS,"Feedback is too large. Keep the complete submission below 1 MiB.",2):fail(AGENT_REASON.STDIN_ERROR,"Could not read the feedback note from stdin. Check the input pipe and try again.",1)}}else notes[0]!==void 0&&(data.note=notes[0]);for(let key of Object.keys(data))data[key].trim()||delete data[key];if(!Object.keys(data).length)return fail(AGENT_REASON.INVALID_ARGUMENTS,"Provide a note or at least one named field. Run vercel feedback --help for examples.",2);let canSendTelemetry=client.telemetryEventStore?.enabled??!1,body=JSON.stringify({metadata:canSendTelemetry?{agent:client.isAgent,agent_name:client.isAgent?client.agentName:void 0,cli_version:pkg_default.version,operating_system:process.platform,team_id:client.config.currentTeam??null,user_id:client.authConfig.userId??null,invocation_id:client.telemetryEventStore?.currentInvocationId??null,session_id:client.telemetryEventStore?.currentSessionId??null}:null,data});if(Buffer.byteLength(body)>MAX_FEEDBACK_BYTES)return fail(AGENT_REASON.INVALID_ARGUMENTS,"Feedback is too large. Keep the complete submission below 1 MiB.",2);let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),FETCH_TIMEOUT_MS);timeout.unref?.();try{let response=await fetch(FEEDBACK_URL,{method:"POST",headers:{"content-type":"application/json","user-agent":ua_default},body,redirect:"manual",signal:controller.signal});if(!response.ok)return await response.body?.cancel(),fail(response.status===429?AGENT_REASON.RATE_LIMITED:AGENT_REASON.API_ERROR,`Feedback could not be submitted (HTTP ${response.status}). Try again later.`,1);let responseBody=toNodeReadable(response.body);return JSON.parse(await(0,import_raw_body.default)(responseBody,{limit:64*1024,encoding:"utf8"}).finally(()=>responseBody.destroy()))?.success!==!0?fail(AGENT_REASON.UNKNOWN_OUTCOME,"Could not confirm that Vercel accepted the feedback. It may have been submitted; no automatic retry was made.",1):(client.stdout.write(`Feedback sent
|
|
7
|
+
import{FILTER_DEPRECATION_WARNING,alignTimeRangeToGranularity,canonicalResponseToMetricsResponse,createCanonicalMetricsRequest,usesODataSyntax}from"./chunks/chunk-OQX4YVGU.js";import{init_dist,prepareFlagsDefinitions}from"./chunks/chunk-OAM5NJCU.js";import{EncryptJWT,base64url_exports,jwtDecrypt}from"./chunks/chunk-S3L2OHPO.js";import{require_fast_deep_equal}from"./chunks/chunk-MCRKBVZA.js";import{sanitizeForTerminal}from"./chunks/chunk-5RMIM4S2.js";import{getLinkedFlagsProject,getProjectNameFromFlags}from"./chunks/chunk-IC3THLYP.js";import{parseSubcommandArguments,requireProjectContext}from"./chunks/chunk-L4XLDN6T.js";import{computeGranularity,formatText,generateSparkline}from"./chunks/chunk-ZUNQHI5Y.js";import{OBSERVABILITY_METRICS_PATH,getRollupColumnName,handleApiError}from"./chunks/chunk-AIRQFG5A.js";import"./chunks/chunk-IVSSTHB6.js";import"./chunks/chunk-GZNDA6SV.js";import{require_dist}from"./chunks/chunk-JELLVPCM.js";import{readStdinText}from"./chunks/chunk-PSOVLGHP.js";import{require_raw_body}from"./chunks/chunk-XOETL6DB.js";import{findCommandShorthands}from"./chunks/chunk-KY7LDQRX.js";import{STANDARD_ENVIRONMENTS}from"./chunks/chunk-7YKFF6CE.js";import{resolveProjectContext}from"./chunks/chunk-36NK2Z3C.js";import{formatProject}from"./chunks/chunk-75JI2SZX.js";import{normalizeRepeatableStringFilters,outputError,resolveTimeRange,validateIntegerRangeWithDefault,validateTimeBound,validateTimeOrder}from"./chunks/chunk-XSQVCDSD.js";import{ellipsizeMiddle,truncateEnd}from"./chunks/chunk-ID663OJ7.js";import{require_open}from"./chunks/chunk-PVASGBEF.js";import"./chunks/chunk-SDOPVIKJ.js";import"./chunks/chunk-7EJQLVWX.js";import{readOnOffOption}from"./chunks/chunk-RMW2FDXS.js";import{getCommandFlags}from"./chunks/chunk-XGTKHQTT.js";import{printNextPageCommand}from"./chunks/chunk-KHADRPBJ.js";import{canPrompt}from"./chunks/chunk-IQ7FPAI4.js";import{formatDate}from"./chunks/chunk-HRR57QNP.js";import"./chunks/chunk-PFD7LETF.js";import{getInvalidSubcommand}from"./chunks/chunk-TG2RCYTH.js";import{formatTable}from"./chunks/chunk-FAELJM4F.js";import{stamp_default}from"./chunks/chunk-A2RZZQEP.js";import{table}from"./chunks/chunk-5SIC5273.js";import{getRenamedOption,reportRenamedOptionError,withWarnings}from"./chunks/chunk-JSAY52FE.js";import"./chunks/chunk-Q7D7RGXM.js";import{getSubcommand}from"./chunks/chunk-ETV3C2CV.js";import{FLAG_ATTRIBUTE_TYPES,FLAG_CONDITION_LIST_COMPARATORS,FLAG_CONDITION_RHS_OPTIONAL_COMPARATORS,FLAG_EVALUATIONS_DIMENSIONS,FLAG_EVALUATIONS_DIMENSION_NAMES,FLAG_EVALUATIONS_GRANULARITIES,alertsInspectSubcommand,alertsListSubcommand,alertsSubcommand,archiveSubcommand,attackModeDisableSubcommand,attackModeEnableSubcommand,attackModeSubcommand,botManagementSubcommand,commandsStructs,connectionsAddSubcommand,connectionsListSubcommand,connectionsRemoveSubcommand,connectionsSubcommand,createSubcommand6 as createSubcommand,datafileSubcommand,diffSubcommand,disableSubcommand,discardSubcommand,enableSubcommand2 as enableSubcommand,entitiesCreateSubcommand,entitiesListSubcommand,entitiesRemoveSubcommand,entitiesSubcommand,entitiesUpdateSubcommand,evaluationsSubcommand,feedbackCommand,firewallCommand,flagsCommand,formatFlagAttributeTypeList,formatFlagConditionComparator,formatFlagConditionComparatorList,getCommandAliases,getFlagAttributeType,inspectSubcommand9 as inspectSubcommand,ipBlocksBlockSubcommand,ipBlocksListSubcommand,ipBlocksSubcommand,ipBlocksUnblockSubcommand,isBucketingAttribute,isFlagAttributeType,isFlagEvaluationsDimension,isFlagEvaluationsGranularity,isTimestampAttributeType,labelsListSubcommand,labelsSubcommand,listSubcommand14 as listSubcommand,openSubcommand3 as openSubcommand,overrideSubcommand,overviewSubcommand,persistentActionsInspectSubcommand,persistentActionsListSubcommand,persistentActionsSubcommand,prepareSubcommand,publishSubcommand,removeSubcommand8 as removeSubcommand,rolloutSubcommand,rulesAddSubcommand2 as rulesAddSubcommand,rulesAddSubcommand3 as rulesAddSubcommand2,rulesDisableSubcommand,rulesEditSubcommand2 as rulesEditSubcommand,rulesEnableSubcommand,rulesInspectSubcommand,rulesListSubcommand2 as rulesListSubcommand,rulesListSubcommand3 as rulesListSubcommand2,rulesMoveSubcommand,rulesRemoveSubcommand2 as rulesRemoveSubcommand,rulesRemoveSubcommand3 as rulesRemoveSubcommand2,rulesReorderSubcommand,rulesSubcommand2 as rulesSubcommand,rulesSubcommand3 as rulesSubcommand2,rulesUpdateSubcommand,sdkKeysAddSubcommand,sdkKeysListSubcommand,sdkKeysRemoveSubcommand,sdkKeysSubcommand,segmentsCreateSubcommand,segmentsInspectSubcommand,segmentsListSubcommand,segmentsRemoveSubcommand,segmentsSubcommand,segmentsUpdateSubcommand,setSubcommand2 as setSubcommand,splitSubcommand,staleSubcommand,statusSubcommand,systemBypassAddSubcommand,systemBypassListSubcommand,systemBypassRemoveSubcommand,systemBypassSubcommand,systemMitigationsPauseSubcommand,systemMitigationsResumeSubcommand,systemMitigationsSubcommand,targetingEnableSubcommand,targetingSubcommand,targetsAddSubcommand,targetsListSubcommand,targetsRemoveSubcommand,targetsSubcommand,trafficInspectSubcommand,trafficListSubcommand,trafficSubcommand,unarchiveSubcommand,updateSubcommand5 as updateSubcommand,useTargetingSubcommand,versionsDiffSubcommand,versionsListSubcommand,versionsSubcommand}from"./chunks/chunk-WDUHDLUA.js";import"./chunks/chunk-O7COT3YB.js";import"./chunks/chunk-2FHZYQPY.js";import"./chunks/chunk-M7LUSXMG.js";import"./chunks/chunk-C6IITJ5S.js";import"./chunks/chunk-TZT3VYZ3.js";import"./chunks/chunk-HMWDOAWO.js";import"./chunks/chunk-QNL22LAW.js";import"./chunks/chunk-UWMPVTXG.js";import"./chunks/chunk-5CZNUB7Y.js";import"./chunks/chunk-AUY363W7.js";import"./chunks/chunk-OTYF3ZZW.js";import"./chunks/chunk-3H36RI7C.js";import"./chunks/chunk-BGWS5R5R.js";import"./chunks/chunk-UJQ6PBRF.js";import"./chunks/chunk-LFOWP74R.js";import"./chunks/chunk-GVPVWHFK.js";import"./chunks/chunk-N5CXIFE2.js";import"./chunks/chunk-FNA4MIOH.js";import"./chunks/chunk-JALVF3C2.js";import"./chunks/chunk-VWHIWUGJ.js";import{printError}from"./chunks/chunk-VQ755MPP.js";import{help}from"./chunks/chunk-SLDWAIO3.js";import"./chunks/chunk-67GZ5REA.js";import"./chunks/chunk-BS32OUOC.js";import{TelemetryClient}from"./chunks/chunk-5WYPJ2T5.js";import"./chunks/chunk-2EYYB6YN.js";import{getScope}from"./chunks/chunk-WICRM2JL.js";import{require_ms}from"./chunks/chunk-MXTC4ZAQ.js";import"./chunks/chunk-NWGBDBZI.js";import{AGENT_REASON,AGENT_STATUS,buildCommandWithGlobalFlags,buildCommandWithYes,clientObservabilityPlanRecovery,getExitCodeForReason,outputAgentError,shouldEmitNonInteractiveCommandError,writeActionRequired,writeAgentError}from"./chunks/chunk-XE24Y6NM.js";import"./chunks/chunk-EPO7P734.js";import{getProjectByNameOrId,require_pluralize,ua_default}from"./chunks/chunk-VLYVVC3P.js";import{formatAlignedLabel,printAlignedLabel}from"./chunks/chunk-26QK3I2S.js";import"./chunks/chunk-55H6G46X.js";import"./chunks/chunk-4NTBYNFR.js";import{parseArguments}from"./chunks/chunk-F22QLVTX.js";import{quoteArg,teamCache}from"./chunks/chunk-F53OKXYI.js";import{warnDeprecatedInput,warnDeprecatedOption,warnDeprecatedSubcommand}from"./chunks/chunk-7SAEZ4NC.js";import"./chunks/chunk-LUX4PBJL.js";import"./chunks/chunk-OPORM35X.js";import"./chunks/chunk-4SAVH3H7.js";import{ProjectNotFound,isAPIError}from"./chunks/chunk-YCJHUYBJ.js";import{cmd,getCommandName,getCommandNamePlain,packageName}from"./chunks/chunk-JESNVRVR.js";import{output_manager_default,recordCliError}from"./chunks/chunk-DWOJP4ST.js";import"./chunks/chunk-BLUPZPAS.js";import"./chunks/chunk-RM3ZDRYE.js";import"./chunks/chunk-D3AHZ5LI.js";import"./chunks/chunk-2GHZGOWT.js";import"./chunks/chunk-YHPPP3SF.js";import{pkg_default}from"./chunks/chunk-OO572JUC.js";import"./chunks/chunk-PUKYAALC.js";import{SDK_KEY_PATTERN,getFlagsSpecification,getGlobalFlagsFromArgs,getProjectOptionFromArgs}from"./chunks/chunk-A2UZ2O7H.js";import"./chunks/chunk-2BKALEOP.js";import{require_source}from"./chunks/chunk-NB2WLB3J.js";import"./chunks/chunk-ISWW3DKF.js";import"./chunks/chunk-BRQUZ5NC.js";import{fetch,toNodeReadable}from"./chunks/chunk-MY4MONOH.js";import{__toESM}from"./chunks/chunk-BZENIQ7N.js";var import_raw_body=__toESM(require_raw_body(),1);var FeedbackTelemetryClient=class extends TelemetryClient{trackCliArgumentNote(note){note!==void 0&&this.trackCliArgument({arg:"note",value:this.redactedValue})}trackCliOptionField(fields){fields?.length&&this.trackCliOption({option:"field",value:this.redactedValue})}};var FEEDBACK_URL="https://vercel.com/api/feedback/cli",MAX_FEEDBACK_BYTES=1024*1024,FETCH_TIMEOUT_MS=1e4;async function feedback(client){let fail=(reason,message,code)=>(recordCliError({code:reason}),output_manager_default.error(message),code),parsed;try{parsed=parseArguments(client.argv.slice(2),getFlagsSpecification(feedbackCommand.options))}catch{return fail(AGENT_REASON.INVALID_ARGUMENTS,"Invalid feedback arguments. Run vercel feedback --help for usage.",2)}let notes=parsed.args.slice(1),fields=parsed.flags["--field"]??[];if(notes.length===0&&fields.length===0)return client.stdout.write(help(feedbackCommand,{stream:client.stdout,columns:client.stdout.columns??client.stderr.columns})),0;if(notes.length>1)return fail(AGENT_REASON.INVALID_ARGUMENTS,"Pass one note. Quote notes containing spaces, or use vercel feedback - to read stdin.",2);let telemetry=new FeedbackTelemetryClient({opts:{store:client.telemetryEventStore}});telemetry.trackCliArgumentNote(notes[0]),telemetry.trackCliOptionField(fields);let data=Object.create(null);for(let field of fields){let separator=field.indexOf("="),key=field.slice(0,separator).trim();if(separator<1||key==="")return fail(AGENT_REASON.INVALID_ARGUMENTS,"Each --field needs a non-empty key followed by =value. Example: vercel feedback --field topic=deploy.",2);data[key]=field.slice(separator+1)}if(notes.length&&Object.hasOwn(data,"note"))return fail(AGENT_REASON.INVALID_ARGUMENTS,"Provide the note once: use a positional note or --field note=..., rather than both.",2);if(notes[0]==="-"){if(client.stdin.isTTY)return fail(AGENT_REASON.INVALID_ARGUMENTS,"No input was piped to stdin. Pipe a note with: cat notes.md | vercel feedback -",2);try{data.note=await readStdinText(client.stdin,MAX_FEEDBACK_BYTES)}catch(error){return error.type==="entity.too.large"?fail(AGENT_REASON.INVALID_ARGUMENTS,"Feedback is too large. Keep the complete submission below 1 MiB.",2):fail(AGENT_REASON.STDIN_ERROR,"Could not read the feedback note from stdin. Check the input pipe and try again.",1)}}else notes[0]!==void 0&&(data.note=notes[0]);for(let key of Object.keys(data))data[key].trim()||delete data[key];if(!Object.keys(data).length)return fail(AGENT_REASON.INVALID_ARGUMENTS,"Provide a note or at least one named field. Run vercel feedback --help for examples.",2);let canSendTelemetry=client.telemetryEventStore?.enabled??!1,body=JSON.stringify({metadata:canSendTelemetry?{agent:client.isAgent,agent_name:client.isAgent?client.agentName:void 0,cli_version:pkg_default.version,operating_system:process.platform,team_id:client.config.currentTeam??null,user_id:client.authConfig.userId??null,invocation_id:client.telemetryEventStore?.currentInvocationId??null,session_id:client.telemetryEventStore?.currentSessionId??null}:null,data});if(Buffer.byteLength(body)>MAX_FEEDBACK_BYTES)return fail(AGENT_REASON.INVALID_ARGUMENTS,"Feedback is too large. Keep the complete submission below 1 MiB.",2);let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),FETCH_TIMEOUT_MS);timeout.unref?.();try{let response=await fetch(FEEDBACK_URL,{method:"POST",headers:{"content-type":"application/json","user-agent":ua_default},body,redirect:"manual",signal:controller.signal});if(!response.ok)return await response.body?.cancel(),fail(response.status===429?AGENT_REASON.RATE_LIMITED:AGENT_REASON.API_ERROR,`Feedback could not be submitted (HTTP ${response.status}). Try again later.`,1);let responseBody=toNodeReadable(response.body);return JSON.parse(await(0,import_raw_body.default)(responseBody,{limit:64*1024,encoding:"utf8"}).finally(()=>responseBody.destroy()))?.success!==!0?fail(AGENT_REASON.UNKNOWN_OUTCOME,"Could not confirm that Vercel accepted the feedback. It may have been submitted; no automatic retry was made.",1):(client.stdout.write(`Feedback sent
|
|
8
8
|
`),0)}catch{return fail(AGENT_REASON.UNKNOWN_OUTCOME,"Could not confirm that Vercel accepted the feedback. Check your connection. It may have been submitted; no automatic retry was made.",1)}finally{clearTimeout(timeout)}}var import_chalk6=__toESM(require_source(),1);var import_chalk2=__toESM(require_source(),1);var import_chalk=__toESM(require_source(),1);var ACTION_COLORS={allow:import_chalk.default.blue,deny:import_chalk.default.red,challenge:import_chalk.default.yellow,log:import_chalk.default.magenta,rate_limit:import_chalk.default.cyan,"rate-limit":import_chalk.default.cyan,bypass:import_chalk.default.green};function labelForAction(action){return action==="rate_limit"||action==="rate-limit"?"Rate Limited":action.split(/[-_]/).filter(Boolean).map(word=>word.charAt(0).toUpperCase()+word.slice(1)).join(" ")}var MONTHS=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function formatCount(n){return n>=1e6?`${(n/1e6).toFixed(1)}M`:n>=1e3?`${(n/1e3).toFixed(1)}k`:String(Math.round(n))}function pad2(n){return String(n).padStart(2,"0")}function formatUtcTime(ms8,withDate){let d=new Date(ms8),hm=`${pad2(d.getUTCHours())}:${pad2(d.getUTCMinutes())}`;return withDate?`${MONTHS[d.getUTCMonth()]} ${d.getUTCDate()} ${hm}`:hm}function relativeTime(ts){let diff2=Date.now()-ts;return diff2<6e4?"just now":diff2<36e5?`${Math.floor(diff2/6e4)}m ago`:diff2<864e5?`${Math.floor(diff2/36e5)}h ago`:`${Math.floor(diff2/864e5)}d ago`}function formatUtcDateTime(ms8){return`${formatUtcTime(ms8,!0)} UTC (${relativeTime(ms8)})`}function colorizeDetail(detail){return detail.split(" \xB7 ").map(part=>{let color=ACTION_COLORS[part.toLowerCase().replace(/ /g,"_")];return color?color(part):part}).join(" \xB7 ")}function windowNeedsDate(startMs,endMs){return endMs-startMs>25*36e5}function granularityLabel(granularity){return"minutes"in granularity?`${granularity.minutes}m`:"hours"in granularity?`${granularity.hours}h`:`${granularity.days}d`}function formatActionTrendTable(series){let allTs=new Set;for(let s of series)for(let p of s.timeseries)allTs.add(p.timestamp);let axis=[...allTs].sort(),hasAnyTraffic=series.some(s=>s.total>0||s.timeseries.some(p=>p.value>0));if(series.length===0||axis.length===0||!hasAnyTraffic)return import_chalk.default.dim(" No request data for this period.");let startMs=new Date(axis[0]).getTime(),endMs=new Date(axis[axis.length-1]).getTime(),needsDate=windowNeedsDate(startMs,endMs),rows=[["Action","Trend","Total","Peak","Peak at"].map(h=>import_chalk.default.bold(import_chalk.default.cyan(h)))];for(let s of series){let byTs=new Map(s.timeseries.map(p=>[p.timestamp,p.value])),values=axis.map(t=>byTs.get(t)??0),peak=0,peakTs="";for(let i=0;i<axis.length;i++)values[i]>peak&&(peak=values[i],peakTs=axis[i]);let plain=x=>x,color=s.total>0?ACTION_COLORS[s.action]??plain:import_chalk.default.dim,trend=s.total>0?plain:import_chalk.default.dim;rows.push([color(labelForAction(s.action)),trend(generateSparkline(values)),formatCount(s.total),peak>0?formatCount(peak):"--",peak>0?formatUtcTime(new Date(peakTs).getTime(),needsDate):"--"])}return table(rows,{align:["l","l","r","r","r"],hsep:3}).split(`
|
|
9
9
|
`).map(line2=>` ${line2}`.trimEnd()).join(`
|
|
10
|
-
`)}var NO_SERVER_MESSAGE="Response Error";function apiServerMessage(error){let message=isAPIError(error)?error.serverMessage:void 0;return message&&message!==NO_SERVER_MESSAGE?message:void 0}var FIREWALL_O11Y_ALERT_TYPES=["botId_anomaly","firewallSystemRule_anomaly","firewallCustomRule_anomaly"],FIREWALL_ANOMALY_TYPE="firewall_anomaly",SYS_DOS_MITIGATION_RULE_ID="sys_dos_mitigation",SYSTEM_RULE_ANOMALY_TYPE="firewallSystemRule_anomaly",FIREWALL_ACTIVITY_PLAN_MESSAGE="Traffic and alerts need Observability Plus.",FIREWALL_ALERTS_PARTIAL_ERROR_MESSAGE="Couldn't load every alert source.";function reduceAttackAnomaly(anomaly){return Object.keys(anomaly.affectedHostMap).reduce((acc,host)=>{acc.hosts.push(host);let challenged=anomaly.affectedHostMap[host].ddosAlerts?.["sys_dos_mitigation:challenge"]?.totalReqs||0,denied=anomaly.affectedHostMap[host].ddosAlerts?.["sys_dos_mitigation:deny"]?.totalReqs||0;return acc.challenged+=challenged,acc.denied+=denied,acc.count+=challenged+denied,acc},{hosts:[],challenged:0,denied:0,count:0})}function hostsFromAnomaly(anomaly){return Object.entries(anomaly.affectedHostMap).map(([host,data])=>{let challenged=data.ddosAlerts?.["sys_dos_mitigation:challenge"]?.totalReqs||0,denied=data.ddosAlerts?.["sys_dos_mitigation:deny"]?.totalReqs||0;return{name:host,count:challenged+denied}}).filter(row=>row.count>0).sort((a,b)=>b.count-a.count)}function mapAttackAnomaly(anomaly){let reduced=reduceAttackAnomaly(anomaly),parts=["System rule"];return reduced.denied>0&&parts.push(labelForAction("deny")),reduced.challenged>0&&parts.push(labelForAction("challenge")),{id:`${anomaly.ownerId}-${anomaly.projectId}-${anomaly.startTime}`,title:"DDoS Mitigation",type:FIREWALL_ANOMALY_TYPE,startedAt:anomaly.startTime,resolvedAt:anomaly.endTime||void 0,count:reduced.count,detail:parts.join(" \xB7 "),action:reduced.denied>=reduced.challenged?"deny":"challenge",ruleId:SYS_DOS_MITIGATION_RULE_ID,host:reduced.hosts[0]}}function mapO11yAlert(alert){if(!alert.startedAt)return null;let action=alert.data?.action,ruleId=alert.data?.ruleId,detailParts=[alert.type,action?labelForAction(action):void 0,ruleId].filter(Boolean);return{id:alert.id||`${alert.type}-${alert.startedAt}`,title:alert.title||alert.type||"Firewall alert",type:alert.type||"unknown",startedAt:alert.startedAt,resolvedAt:alert.resolvedAt,count:alert.data?.count,detail:detailParts.filter(p=>p!==alert.title).join(" \xB7 ")||void 0,action,ruleId,path:alert.data?.path}}var ATTACK_STATUS_MAX_DAYS=7;async function getAttackStatus(client,opts){let query=new URLSearchParams;if(query.set("projectId",opts.projectId),query.set("teamId",opts.teamId),opts.sinceDays!==void 0){let sinceDays=Math.min(ATTACK_STATUS_MAX_DAYS,Math.max(1,Math.ceil(opts.sinceDays)));query.set("since",String(sinceDays))}return client.fetch(`/v1/security/firewall/attack-status?${query.toString()}`,{accountId:opts.teamId,signal:opts.signal})}var O11Y_ALERTS_LIMIT=200;async function getFirewallO11yAlerts(client,opts){let query=new URLSearchParams;query.set("teamId",opts.teamId),query.set("projectId",opts.projectId),query.set("from",opts.from.toISOString()),query.set("to",opts.to.toISOString()),query.set("limit",String(O11Y_ALERTS_LIMIT));for(let type of FIREWALL_O11Y_ALERT_TYPES)query.append("types",type);return(await client.fetch(`/alerts/v3/groups?${query.toString()}`,{accountId:opts.teamId,signal:opts.signal})).flatMap(g=>g.alerts??[]).map(mapO11yAlert).filter(a=>a!==null)}var ALERTS_TIMEOUT_MS=2e4;function sourceFailureReason(err){return isAPIError(err)&&err.status===408||err instanceof Error&&(err.name==="TimeoutError"||err.name==="AbortError")?"timed out":isAPIError(err)&&err.status===402?"needs Observability Plus":isAPIError(err)&&typeof err.status=="number"?`HTTP ${err.status}`:err instanceof Error&&err.message?err.message:"unknown error"}function resolveAlertsWindow(opts){let now=Date.now(),to=opts.to??new Date(now),from=opts.from??new Date(to.getTime()-864e5*(opts.sinceDays??1)),sinceDays=opts.sinceDays??Math.max(1,Math.ceil((now-from.getTime())/864e5));return{from,to,sinceDays}}function classifyAlertSourceError(err){if(isAPIError(err)&&(err.status===401||err.status===403))throw err;return isAPIError(err)&&err.status===402?{reason:"plan",message:FIREWALL_ACTIVITY_PLAN_MESSAGE}:{reason:"error",message:apiServerMessage(err)||!isAPIError(err)&&err instanceof Error&&err.message||FIREWALL_ALERTS_PARTIAL_ERROR_MESSAGE}}async function getFirewallAlertsDetailed(client,opts){let{from,to,sinceDays}=resolveAlertsWindow(opts),timeoutMs=opts.timeoutMs??ALERTS_TIMEOUT_MS,signal=AbortSignal.timeout(timeoutMs),[o11yResult,attackResult]=await Promise.allSettled([getFirewallO11yAlerts(client,{...opts,from,to,signal}),getAttackStatus(client,{...opts,sinceDays,signal})]),errors=[],o11yAlerts=[],o11y;o11yResult.status==="fulfilled"?o11yAlerts=o11yResult.value:(o11y=classifyAlertSourceError(o11yResult.reason),errors.push({source:"alerts",message:sourceFailureReason(o11yResult.reason)}));let mappedAttacks=[],attackStatus;attackResult.status==="fulfilled"?mappedAttacks=(attackResult.value.anomalies||[]).map(mapAttackAnomaly):(attackStatus=classifyAlertSourceError(attackResult.reason),errors.push({source:"attackStatus",message:sourceFailureReason(attackResult.reason)}));let resolvedCutoff=from.getTime();return{alerts:mappedAttacks.concat(o11yAlerts.filter(a=>!a.resolvedAt||a.resolvedAt>resolvedCutoff)).sort((a,b)=>!a.resolvedAt&&b.resolvedAt?-1:a.resolvedAt&&!b.resolvedAt?1:b.startedAt-a.startedAt),o11y,attackStatus,errors}}function alertsIncompleteMessage(errors){return`Attack count and alerts may be incomplete: ${errors.map(e=>`${e.source==="alerts"?"alerts":"attack history"} ${e.message}`).join("; ")}.`}function countAttacksMitigated(alerts,windowStartMs,windowEndMs){return alerts.filter(alert=>isAttackAlert(alert)&&alertOverlapsWindow(alert,windowStartMs,windowEndMs)).length}function alertOverlapsWindow(alert,windowStartMs,windowEndMs){return alert.startedAt<=windowEndMs&&(alert.resolvedAt??Number.POSITIVE_INFINITY)>=windowStartMs}function isAttackAlert(alert){return alert.type===FIREWALL_ANOMALY_TYPE?!0:alert.type===SYSTEM_RULE_ANOMALY_TYPE&&alert.ruleId===SYS_DOS_MITIGATION_RULE_ID}var O11Y_ALERT_ID_PREFIX="al_",INSPECT_FALLBACK_DAYS=7;function isO11yAlertId(id){return id.startsWith(O11Y_ALERT_ID_PREFIX)}function parseLegacyAlertStartTime(id){let match=id.match(/-(\d{13})$/);return match?Number(match[1]):void 0}function daysCovering(startMs,endMs){return Math.max(1,Math.ceil((endMs-startMs)/864e5))}function mapGroupAsAlert(group,alertId){let nested=(group.alerts??[]).map(mapO11yAlert).filter(a=>a!==null),hit=nested.find(a=>a.id===alertId)??nested[0];if(hit)return hit;let startedAt=group.recordedStartedAt;return startedAt?mapO11yAlert({id:alertId,title:group.title,type:group.type,startedAt,resolvedAt:group.recordedResolvedAt,data:group.alerts?.[0]?.data}):null}async function getO11yAlertById(client,opts){let query=new URLSearchParams;query.set("teamId",opts.teamId),query.set("projectId",opts.projectId);try{let group=await client.fetch(`/alerts/v3/groups/${encodeURIComponent(opts.alertId)}?${query.toString()}`,{accountId:opts.teamId,signal:opts.signal});return mapGroupAsAlert(group,opts.alertId)}catch(err){if(isAPIError(err)&&err.status===404)return null;throw err}}async function findFirewallAlert(client,opts){let timeoutMs=opts.timeoutMs??ALERTS_TIMEOUT_MS,budget=()=>AbortSignal.timeout(timeoutMs),now=Date.now();if(isO11yAlertId(opts.alertId)){let fromGroup2=await getO11yAlertById(client,{...opts,signal:budget()});if(fromGroup2)return{alert:fromGroup2};let from=new Date(now-864e5*INSPECT_FALLBACK_DAYS),hit=(await getFirewallO11yAlerts(client,{projectId:opts.projectId,teamId:opts.teamId,from,to:new Date(now),signal:budget()})).find(a=>a.id===opts.alertId);return hit?{alert:hit}:null}let startTime=parseLegacyAlertStartTime(opts.alertId),sinceDays=startTime?daysCovering(startTime,now)+1:INSPECT_FALLBACK_DAYS,anomaly=((await getAttackStatus(client,{projectId:opts.projectId,teamId:opts.teamId,sinceDays,signal:budget()}).catch(err=>{if(isAPIError(err)&&(err.status===401||err.status===403))throw err;return{anomalies:[]}})).anomalies||[]).find(a=>`${a.ownerId}-${a.projectId}-${a.startTime}`===opts.alertId);if(anomaly)return{alert:mapAttackAnomaly(anomaly),hosts:hostsFromAnomaly(anomaly)};let fromGroup=await getO11yAlertById(client,{...opts,signal:budget()}).catch(err=>{if(isAPIError(err)&&(err.status===401||err.status===403))throw err;return null});return fromGroup?{alert:fromGroup}:null}var MANAGED_BOT_RULE_IDS=["bot-protection","ai-bots","bot-id"],ALIASES={"bot-protection":"bot-protection","bot protection":"bot-protection",bot_protection:"bot-protection",bot_filter:"bot-protection",managed_bot_protection:"bot-protection",managed_bot_filter:"bot-protection","ai-bots":"ai-bots","ai bots":"ai-bots",ai_bots:"ai-bots",managed_ai_bots:"ai-bots","bot-id":"bot-id",botid:"bot-id",bot_id:"bot-id"},ACTIONS={"bot-protection":["off","log","challenge"],"ai-bots":["allow","log","challenge","deny"],"bot-id":["basic","deep-analysis"]},NAMES={"bot-protection":"Bot Protection","ai-bots":"AI Bots","bot-id":"BotID"},WAF_RULE_IDS={"bot-protection":"managed_bot_protection","ai-bots":"managed_ai_bots"};function resolveManagedBotRuleId(identifier){if(identifier)return ALIASES[identifier.trim().toLowerCase()]}function managedBotActions(id){return ACTIONS[id]}function formatManagedBotAction(action){return action==="deep-analysis"?"Deep Analysis":action.charAt(0).toUpperCase()+action.slice(1)}function botProtectionConfig(managedRules){return managedRules?.bot_filter??managedRules?.bot_protection}function currentBotProtectionAction(config){let ruleset=botProtectionConfig(config?.managedRules);return ruleset?.active?ruleset.action==="log"?"log":"challenge":"off"}function currentAiBotsAction(config){let ruleset=config?.managedRules?.ai_bots;return ruleset?.active?ruleset.action==="challenge"?"challenge":ruleset.action==="deny"?"deny":"log":"allow"}function currentBotIdAction(config){return config?.botIdEnabled?"deep-analysis":"basic"}function getManagedBotRule(config,id){let action=id==="bot-protection"?currentBotProtectionAction(config):id==="ai-bots"?currentAiBotsAction(config):currentBotIdAction(config);return{id,name:NAMES[id],action,wafRuleId:WAF_RULE_IDS[id]}}function getManagedBotRules(config){return MANAGED_BOT_RULE_IDS.map(id=>getManagedBotRule(config,id))}function parseManagedBotAction(id,raw){let action=raw.trim().toLowerCase().replace(/\s+/g,"-"),valid=ACTIONS[id];return valid.includes(action)?{action}:{error:`Invalid action "${raw}" for ${NAMES[id]}. Use ${valid.join(", ")}.`}}function buildManagedBotPatch(id,action){if(id==="bot-id")return{action:"botId.toggle",value:action==="deep-analysis"};let patchId=id==="bot-protection"?"bot_protection":"ai_bots";return action==="off"||action==="allow"?{action:"managedRules.update",id:patchId,value:{active:!1}}:{action:"managedRules.update",id:patchId,value:{active:!0,action}}}function suggestedManagedBotAction(rule){return rule.id==="bot-protection"?rule.action==="challenge"?"log":"challenge":rule.id==="ai-bots"?rule.action==="deny"?"allow":"deny":rule.action==="deep-analysis"?"basic":"deep-analysis"}function managedBotTrafficWarning(id,from,to){if(id==="ai-bots"&&to==="deny")return"AI Bots deny blocks known AI crawlers from this project.";if(id==="bot-protection"&&from==="off"&&to==="challenge")return"Bot Protection challenge will present a verification page to non-browser traffic."}function managedBotJson(rule){return{id:rule.id,name:rule.name,action:rule.action,wafRuleId:rule.wafRuleId??null}}function projectScope(project,teamId,teamSlug){return{type:"project",projectId:project.id,teamId,...teamSlug?{teamSlug}:{},displayName:project.name}}function firewallConfigUrl(scope,path=""){let query=new URLSearchParams;return scope.type==="project"?(query.set("projectId",scope.projectId),scope.teamId&&query.set("teamId",scope.teamId),`/v1/security/firewall/config${path}?${query.toString()}`):(query.set("teamId",scope.teamId),`/v1/security/firewall/team-config${path}?${query.toString()}`)}async function listFirewallConfigs(client,scope){return client.fetch(firewallConfigUrl(scope))}async function activateFirewallConfig(client,scope,configVersion){return client.fetch(firewallConfigUrl(scope,`/${configVersion}/activate`),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})})}var PRIORITY_PROJECT_ENABLE_COMMAND="project priority enable",BUY_PRO_COMMAND="buy pro";function withGlobalFlags(client,commandTemplate,scope,options={}){let template=scope?.type==="team"?`${commandTemplate} --team-level`:commandTemplate;return buildCommandWithGlobalFlags(client.argv,template,void 0,{globalFlags:"all",preserveProject:options.preserveProject??!0,excludeFlags:options.excludeFlags})}async function resolveFirewallScope(client,flags){if(flags["--team-level"]&&flags["--project"]){let message="Cannot specify both --team-level and --project. Use one or the other.";return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message},2),2):(output_manager_default.error(message),2)}if(flags["--team-level"]){let{team}=await getScope(client);if(!team){let message="Team-level firewall requires a team scope. Personal accounts are not supported. Run `vercel switch` to select a team or pass --scope <team>.";return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_SCOPE,message},1),1):(output_manager_default.error(message),1)}return{type:"team",teamId:team.id,displayName:team.slug}}let link=await requireProjectContext(client,"firewall",flags["--project"]);if(typeof link=="number")return link;let{project,org}=link;return{type:"project",projectId:project.id,teamId:org.type==="team"?org.id:void 0,teamSlug:org.type==="team"?org.slug:void 0,displayName:project.name}}function mentionsPriorityProject(message){return/priority\s+project/i.test(message)||/priority\s+tier/i.test(message)}function teamPlan(scope){return scope.teamId?teamCache.get(scope.teamId)?.billing?.plan:void 0}function priorityTeam(scope){let cached=scope.teamId?teamCache.get(scope.teamId):void 0;if(scope.type==="team")return{id:scope.teamId,slug:scope.displayName,name:cached?.name??null,scopeArg:scope.displayName};if(!scope.teamId)return null;let slug=scope.teamSlug??cached?.slug??null;return{id:scope.teamId,slug,name:cached?.name??null,scopeArg:slug??scope.teamId}}function teamLabel(team){return team.name&&team.name!==team.slug?`${team.slug} (${team.name})`:team.slug}function styledCommand(command,plain){return plain?getCommandNamePlain(command):getCommandName(command)}function priorityProjectFix(scope){let excludeFlags=["--non-interactive","--project","--yes","--scope","--team"],project=scope.type==="project"?{id:scope.projectId,name:scope.displayName}:null,team=priorityTeam(scope),plan=teamPlan(scope)??null,data={project,team:team&&{id:team.id,slug:team.slug,name:team.name},plan},projectToken=project?quoteArg(project.name):"<project>",scopeFlag=team?` --scope ${quoteArg(team.scopeArg)}`:"",enable4=`${PRIORITY_PROJECT_ENABLE_COMMAND} ${projectToken}${scopeFlag}`;if(!team){let hint="Priority projects are only available on team accounts. Use --scope to specify one.";return{command:"",hint,plainHint:hint,when:hint,excludeFlags,preserveProject:!1,reason:AGENT_REASON.MISSING_SCOPE,data}}if(plan==="hobby"||plan==="oss"){let upgrade=`${BUY_PRO_COMMAND}${scopeFlag}`,hint=plain2=>`Priority Projects are only available on Pro or Enterprise team plans. Upgrade with ${styledCommand(upgrade,plain2)}, then run ${styledCommand(enable4,plain2)}.`;return{command:upgrade,hint:hint(!1),plainHint:hint(!0),when:"a person has approved upgrading the plan",excludeFlags,preserveProject:!1,reason:AGENT_REASON.PLAN_UPGRADE_REQUIRED,scope:team.scopeArg,data}}let shown=styledCommand(enable4,!1),plain=styledCommand(enable4,!0),placeholder="Replace <project> with a project on this team.";return{command:enable4,hint:project?shown:`${shown} ${placeholder}`,plainHint:project?plain:`${plain} ${placeholder}`,when:project?"user runs this command in an interactive terminal":"Replace <project> with a project on this team.",excludeFlags,preserveProject:!1,reason:AGENT_REASON.PLAN_UPGRADE_REQUIRED,scope:team.scopeArg,data}}function mapFirewallApiError(e,scope,fallback){let err=e;return scope.type==="team"&&err.status===403?err.code==="plan_not_supported"?`Team-level firewall requires an Enterprise plan (current team: "${scope.displayName}"). Pass --scope <team> or run \`vercel switch\` to target a different team.`:`You need to be a team owner to manage the team-level firewall for "${scope.displayName}".${err.message?` (${err.message})`:""}`:err.message||fallback}function priorityProjectMessage(scope,fix){let team=fix.data.team,label=team?.slug!=null?teamLabel({slug:team.slug,name:team.name}):void 0;return scope.type==="project"?label?`This rule requires a Priority project for ${scope.displayName} on team ${label}.`:`This rule requires a Priority project. ${fix.hint}`:label?`This rule requires a Priority project on team ${label}.`:"This rule requires a Priority project."}function failPriorityProjectGate(client,error,scope,opts){let serverMessage=apiServerMessage(error);if(!serverMessage||!mentionsPriorityProject(serverMessage))return null;let fix=priorityProjectFix(scope),message=priorityProjectMessage(scope,fix),payload={status:AGENT_STATUS.ERROR,reason:fix.reason,message,userActionRequired:!0,hint:fix.plainHint,retryable:!1,...fix.scope?{scope:fix.scope}:{},data:fix.data,...fix.command?{next:[{command:buildCommandWithGlobalFlags(client.argv,fix.command,packageName,{globalFlags:"all",preserveProject:!1,excludeFlags:fix.excludeFlags}),when:fix.when}]}:{}};return shouldEmitNonInteractiveCommandError(client)&&outputAgentError(client,payload,1),opts?.json?(output_manager_default.stopSpinner(),writeAgentError(client,payload),1):(output_manager_default.error(message),fix.command&&output_manager_default.log(fix.hint),1)}function getRulePayload(flags){let legacy=flags["--json"];return legacy!==void 0&&flags["--data"]!==void 0?(output_manager_default.error("Can't use --data with --json."),2):(legacy!==void 0&&output_manager_default.warning("--json is deprecated for rule payloads. Use --data."),flags["--data"]??legacy)}async function parseSubcommandArgs(argv,command,client,commandPath){let parsedArgs,fullPath=commandPath||command.name;try{parsedArgs=parseSubcommandArguments(argv,command)}catch(err){if(client?.nonInteractive){let rawMessage=err instanceof Error?err.message:String(err),flags=getGlobalFlagsFromArgs(client.argv.slice(2),{preserveProject:!0});return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message:rawMessage,next:[{command:getCommandNamePlain(`firewall ${fullPath} ${flags.join(" ")}`.trim()),when:"fix flags and retry"}]},2),2}return printError(err),2}return parsedArgs}async function confirmAction(client,skipConfirmation,message,details){return skipConfirmation?!0:client.nonInteractive||!client.stdin.isTTY?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`${message} Re-run with --yes to confirm.`,next:[{command:buildCommandWithYes(client.argv),when:"re-run with --yes to confirm"}]}),process.exit(1),!1):(details&&output_manager_default.print(` ${details}
|
|
10
|
+
`)}var NO_SERVER_MESSAGE="Response Error";function apiServerMessage(error){let message=isAPIError(error)?error.serverMessage:void 0;return message&&message!==NO_SERVER_MESSAGE?message:void 0}var FIREWALL_O11Y_ALERT_TYPES=["botId_anomaly","firewallSystemRule_anomaly","firewallCustomRule_anomaly"],FIREWALL_ANOMALY_TYPE="firewall_anomaly",SYS_DOS_MITIGATION_RULE_ID="sys_dos_mitigation",SYSTEM_RULE_ANOMALY_TYPE="firewallSystemRule_anomaly",FIREWALL_ACTIVITY_PLAN_MESSAGE="Traffic and alerts need Observability Plus.",FIREWALL_ALERTS_PARTIAL_ERROR_MESSAGE="Couldn't load every alert source.";function reduceAttackAnomaly(anomaly){return Object.keys(anomaly.affectedHostMap).reduce((acc,host)=>{acc.hosts.push(host);let challenged=anomaly.affectedHostMap[host].ddosAlerts?.["sys_dos_mitigation:challenge"]?.totalReqs||0,denied=anomaly.affectedHostMap[host].ddosAlerts?.["sys_dos_mitigation:deny"]?.totalReqs||0;return acc.challenged+=challenged,acc.denied+=denied,acc.count+=challenged+denied,acc},{hosts:[],challenged:0,denied:0,count:0})}function hostsFromAnomaly(anomaly){return Object.entries(anomaly.affectedHostMap).map(([host,data])=>{let challenged=data.ddosAlerts?.["sys_dos_mitigation:challenge"]?.totalReqs||0,denied=data.ddosAlerts?.["sys_dos_mitigation:deny"]?.totalReqs||0;return{name:host,count:challenged+denied}}).filter(row=>row.count>0).sort((a,b)=>b.count-a.count)}function mapAttackAnomaly(anomaly){let reduced=reduceAttackAnomaly(anomaly),parts=["System rule"];return reduced.denied>0&&parts.push(labelForAction("deny")),reduced.challenged>0&&parts.push(labelForAction("challenge")),{id:`${anomaly.ownerId}-${anomaly.projectId}-${anomaly.startTime}`,title:"DDoS Mitigation",type:FIREWALL_ANOMALY_TYPE,startedAt:anomaly.startTime,resolvedAt:anomaly.endTime||void 0,count:reduced.count,detail:parts.join(" \xB7 "),action:reduced.denied>=reduced.challenged?"deny":"challenge",ruleId:SYS_DOS_MITIGATION_RULE_ID,host:reduced.hosts[0]}}function mapO11yAlert(alert){if(!alert.startedAt)return null;let action=alert.data?.action,ruleId=alert.data?.ruleId,detailParts=[alert.type,action?labelForAction(action):void 0,ruleId].filter(Boolean);return{id:alert.id||`${alert.type}-${alert.startedAt}`,title:alert.title||alert.type||"Firewall alert",type:alert.type||"unknown",startedAt:alert.startedAt,resolvedAt:alert.resolvedAt,count:alert.data?.count,detail:detailParts.filter(p=>p!==alert.title).join(" \xB7 ")||void 0,action,ruleId,path:alert.data?.path}}var ATTACK_STATUS_MAX_DAYS=7;async function getAttackStatus(client,opts){let query=new URLSearchParams;if(query.set("projectId",opts.projectId),query.set("teamId",opts.teamId),opts.sinceDays!==void 0){let sinceDays=Math.min(ATTACK_STATUS_MAX_DAYS,Math.max(1,Math.ceil(opts.sinceDays)));query.set("since",String(sinceDays))}return client.fetch(`/v1/security/firewall/attack-status?${query.toString()}`,{accountId:opts.teamId,signal:opts.signal})}var O11Y_ALERTS_LIMIT=200;async function getFirewallO11yAlerts(client,opts){let query=new URLSearchParams;query.set("teamId",opts.teamId),query.set("projectId",opts.projectId),query.set("from",opts.from.toISOString()),query.set("to",opts.to.toISOString()),query.set("limit",String(O11Y_ALERTS_LIMIT));for(let type of FIREWALL_O11Y_ALERT_TYPES)query.append("types",type);return(await client.fetch(`/alerts/v3/groups?${query.toString()}`,{accountId:opts.teamId,signal:opts.signal})).flatMap(g=>g.alerts??[]).map(mapO11yAlert).filter(a=>a!==null)}var ALERTS_TIMEOUT_MS=2e4;function sourceFailureReason(err){return isAPIError(err)&&err.status===408||err instanceof Error&&(err.name==="TimeoutError"||err.name==="AbortError")?"timed out":isAPIError(err)&&err.status===402?"needs Observability Plus":isAPIError(err)&&typeof err.status=="number"?`HTTP ${err.status}`:err instanceof Error&&err.message?err.message:"unknown error"}function resolveAlertsWindow(opts){let now=Date.now(),to=opts.to??new Date(now),from=opts.from??new Date(to.getTime()-864e5*(opts.sinceDays??1)),sinceDays=opts.sinceDays??Math.max(1,Math.ceil((now-from.getTime())/864e5));return{from,to,sinceDays}}function classifyAlertSourceError(err){if(isAPIError(err)&&(err.status===401||err.status===403))throw err;return isAPIError(err)&&err.status===402?{reason:"plan",message:FIREWALL_ACTIVITY_PLAN_MESSAGE}:{reason:"error",message:apiServerMessage(err)||!isAPIError(err)&&err instanceof Error&&err.message||FIREWALL_ALERTS_PARTIAL_ERROR_MESSAGE}}async function getFirewallAlertsDetailed(client,opts){let{from,to,sinceDays}=resolveAlertsWindow(opts),timeoutMs=opts.timeoutMs??ALERTS_TIMEOUT_MS,signal=AbortSignal.timeout(timeoutMs),[o11yResult,attackResult]=await Promise.allSettled([getFirewallO11yAlerts(client,{...opts,from,to,signal}),getAttackStatus(client,{...opts,sinceDays,signal})]),errors=[],o11yAlerts=[],o11y;o11yResult.status==="fulfilled"?o11yAlerts=o11yResult.value:(o11y=classifyAlertSourceError(o11yResult.reason),errors.push({source:"alerts",message:sourceFailureReason(o11yResult.reason)}));let mappedAttacks=[],attackStatus;attackResult.status==="fulfilled"?mappedAttacks=(attackResult.value.anomalies||[]).map(mapAttackAnomaly):(attackStatus=classifyAlertSourceError(attackResult.reason),errors.push({source:"attackStatus",message:sourceFailureReason(attackResult.reason)}));let resolvedCutoff=from.getTime();return{alerts:mappedAttacks.concat(o11yAlerts.filter(a=>!a.resolvedAt||a.resolvedAt>resolvedCutoff)).sort((a,b)=>!a.resolvedAt&&b.resolvedAt?-1:a.resolvedAt&&!b.resolvedAt?1:b.startedAt-a.startedAt),o11y,attackStatus,errors}}function alertsIncompleteMessage(errors){return`Attack count and alerts may be incomplete: ${errors.map(e=>`${e.source==="alerts"?"alerts":"attack history"} ${e.message}`).join("; ")}.`}function countAttacksMitigated(alerts,windowStartMs,windowEndMs){return alerts.filter(alert=>isAttackAlert(alert)&&alertOverlapsWindow(alert,windowStartMs,windowEndMs)).length}function alertOverlapsWindow(alert,windowStartMs,windowEndMs){return alert.startedAt<=windowEndMs&&(alert.resolvedAt??Number.POSITIVE_INFINITY)>=windowStartMs}function isAttackAlert(alert){return alert.type===FIREWALL_ANOMALY_TYPE?!0:alert.type===SYSTEM_RULE_ANOMALY_TYPE&&alert.ruleId===SYS_DOS_MITIGATION_RULE_ID}var O11Y_ALERT_ID_PREFIX="al_",INSPECT_FALLBACK_DAYS=7;function isO11yAlertId(id){return id.startsWith(O11Y_ALERT_ID_PREFIX)}function parseLegacyAlertStartTime(id){let match=id.match(/-(\d{13})$/);return match?Number(match[1]):void 0}function daysCovering(startMs,endMs){return Math.max(1,Math.ceil((endMs-startMs)/864e5))}function mapGroupAsAlert(group,alertId){let nested=(group.alerts??[]).map(mapO11yAlert).filter(a=>a!==null),hit=nested.find(a=>a.id===alertId)??nested[0];if(hit)return hit;let startedAt=group.recordedStartedAt;return startedAt?mapO11yAlert({id:alertId,title:group.title,type:group.type,startedAt,resolvedAt:group.recordedResolvedAt,data:group.alerts?.[0]?.data}):null}async function getO11yAlertById(client,opts){let query=new URLSearchParams;query.set("teamId",opts.teamId),query.set("projectId",opts.projectId);try{let group=await client.fetch(`/alerts/v3/groups/${encodeURIComponent(opts.alertId)}?${query.toString()}`,{accountId:opts.teamId,signal:opts.signal});return mapGroupAsAlert(group,opts.alertId)}catch(err){if(isAPIError(err)&&err.status===404)return null;throw err}}async function findFirewallAlert(client,opts){let timeoutMs=opts.timeoutMs??ALERTS_TIMEOUT_MS,budget=()=>AbortSignal.timeout(timeoutMs),now=Date.now();if(isO11yAlertId(opts.alertId)){let fromGroup2=await getO11yAlertById(client,{...opts,signal:budget()});if(fromGroup2)return{alert:fromGroup2};let from=new Date(now-864e5*INSPECT_FALLBACK_DAYS),hit=(await getFirewallO11yAlerts(client,{projectId:opts.projectId,teamId:opts.teamId,from,to:new Date(now),signal:budget()})).find(a=>a.id===opts.alertId);return hit?{alert:hit}:null}let startTime=parseLegacyAlertStartTime(opts.alertId),sinceDays=startTime?daysCovering(startTime,now)+1:INSPECT_FALLBACK_DAYS,anomaly=((await getAttackStatus(client,{projectId:opts.projectId,teamId:opts.teamId,sinceDays,signal:budget()}).catch(err=>{if(isAPIError(err)&&(err.status===401||err.status===403))throw err;return{anomalies:[]}})).anomalies||[]).find(a=>`${a.ownerId}-${a.projectId}-${a.startTime}`===opts.alertId);if(anomaly)return{alert:mapAttackAnomaly(anomaly),hosts:hostsFromAnomaly(anomaly)};let fromGroup=await getO11yAlertById(client,{...opts,signal:budget()}).catch(err=>{if(isAPIError(err)&&(err.status===401||err.status===403))throw err;return null});return fromGroup?{alert:fromGroup}:null}var MANAGED_BOT_RULE_IDS=["bot-protection","ai-bots","bot-id"],ALIASES={"bot-protection":"bot-protection","bot protection":"bot-protection",bot_protection:"bot-protection",bot_filter:"bot-protection",managed_bot_protection:"bot-protection",managed_bot_filter:"bot-protection","ai-bots":"ai-bots","ai bots":"ai-bots",ai_bots:"ai-bots",managed_ai_bots:"ai-bots","bot-id":"bot-id",botid:"bot-id",bot_id:"bot-id"},ACTIONS={"bot-protection":["off","log","challenge"],"ai-bots":["allow","log","challenge","deny"],"bot-id":["basic","deep-analysis"]},NAMES={"bot-protection":"Bot Protection","ai-bots":"AI Bots","bot-id":"BotID"},WAF_RULE_IDS={"bot-protection":"managed_bot_protection","ai-bots":"managed_ai_bots"};function resolveManagedBotRuleId(identifier){if(identifier)return ALIASES[identifier.trim().toLowerCase()]}function managedBotActions(id){return ACTIONS[id]}function formatManagedBotAction(action){return action==="deep-analysis"?"Deep Analysis":action.charAt(0).toUpperCase()+action.slice(1)}function botProtectionConfig(managedRules){return managedRules?.bot_filter??managedRules?.bot_protection}function currentBotProtectionAction(config){let ruleset=botProtectionConfig(config?.managedRules);return ruleset?.active?ruleset.action==="log"?"log":"challenge":"off"}function currentAiBotsAction(config){let ruleset=config?.managedRules?.ai_bots;return ruleset?.active?ruleset.action==="challenge"?"challenge":ruleset.action==="deny"?"deny":"log":"allow"}function currentBotIdAction(config){return config?.botIdEnabled?"deep-analysis":"basic"}function getManagedBotRule(config,id){let action=id==="bot-protection"?currentBotProtectionAction(config):id==="ai-bots"?currentAiBotsAction(config):currentBotIdAction(config);return{id,name:NAMES[id],action,wafRuleId:WAF_RULE_IDS[id]}}function getManagedBotRules(config){return MANAGED_BOT_RULE_IDS.map(id=>getManagedBotRule(config,id))}function parseManagedBotAction(id,raw){let action=raw.trim().toLowerCase().replace(/\s+/g,"-"),valid=ACTIONS[id];return valid.includes(action)?{action}:{error:`Invalid action "${raw}" for ${NAMES[id]}. Use ${valid.join(", ")}.`}}function buildManagedBotPatch(id,action){if(id==="bot-id")return{action:"botId.toggle",value:action==="deep-analysis"};let patchId=id==="bot-protection"?"bot_protection":"ai_bots";return action==="off"||action==="allow"?{action:"managedRules.update",id:patchId,value:{active:!1}}:{action:"managedRules.update",id:patchId,value:{active:!0,action}}}function suggestedManagedBotAction(rule){return rule.id==="bot-protection"?rule.action==="challenge"?"log":"challenge":rule.id==="ai-bots"?rule.action==="deny"?"allow":"deny":rule.action==="deep-analysis"?"basic":"deep-analysis"}function managedBotTrafficWarning(id,from,to){if(id==="ai-bots"&&to==="deny")return"AI Bots deny blocks known AI crawlers from this project.";if(id==="bot-protection"&&from==="off"&&to==="challenge")return"Bot Protection challenge will present a verification page to non-browser traffic."}function managedBotJson(rule){return{id:rule.id,name:rule.name,action:rule.action,wafRuleId:rule.wafRuleId??null}}function projectScope(project,teamId,teamSlug){return{type:"project",projectId:project.id,teamId,...teamSlug?{teamSlug}:{},displayName:project.name}}function firewallConfigUrl(scope,path=""){let query=new URLSearchParams;return scope.type==="project"?(query.set("projectId",scope.projectId),scope.teamId&&query.set("teamId",scope.teamId),`/v1/security/firewall/config${path}?${query.toString()}`):(query.set("teamId",scope.teamId),`/v1/security/firewall/team-config${path}?${query.toString()}`)}async function listFirewallConfigs(client,scope){return client.fetch(firewallConfigUrl(scope))}async function activateFirewallConfig(client,scope,configVersion){return client.fetch(firewallConfigUrl(scope,`/${configVersion}/activate`),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})})}var PRIORITY_PROJECT_ENABLE_COMMAND="project priority enable",BUY_PRO_COMMAND="buy pro";function withGlobalFlags(client,commandTemplate,scope,options={}){let template=scope?.type==="team"?`${commandTemplate} --team-level`:commandTemplate;return buildCommandWithGlobalFlags(client.argv,template,void 0,{globalFlags:"all",preserveProject:options.preserveProject??!0,excludeFlags:options.excludeFlags})}async function resolveFirewallScope(client,flags){if(flags["--team-level"]&&flags["--project"]){let message="Cannot specify both --team-level and --project. Use one or the other.";return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message},2),2):(output_manager_default.error(message),2)}if(flags["--team-level"]){let{team}=await getScope(client);if(!team){let message="Team-level firewall requires a team scope. Personal accounts are not supported. Run `vercel switch` to select a team or pass --scope <team>.";return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_SCOPE,message},1),1):(output_manager_default.error(message),1)}return{type:"team",teamId:team.id,displayName:team.slug}}let link=await requireProjectContext(client,"firewall",flags["--project"]);if(typeof link=="number")return link;let{project,org}=link;return{type:"project",projectId:project.id,teamId:org.type==="team"?org.id:void 0,teamSlug:org.type==="team"?org.slug:void 0,displayName:project.name}}function mentionsPriorityProject(message){return/priority\s+project/i.test(message)||/priority\s+tier/i.test(message)}function teamPlan(scope){return scope.teamId?teamCache.get(scope.teamId)?.billing?.plan:void 0}function priorityTeam(scope){let cached=scope.teamId?teamCache.get(scope.teamId):void 0;if(scope.type==="team")return{id:scope.teamId,slug:scope.displayName,name:cached?.name??null,scopeArg:scope.displayName};if(!scope.teamId)return null;let slug=scope.teamSlug??cached?.slug??null;return{id:scope.teamId,slug,name:cached?.name??null,scopeArg:slug??scope.teamId}}function teamLabel(team){return team.name&&team.name!==team.slug?`${team.slug} (${team.name})`:team.slug}function styledCommand(command,plain){return plain?getCommandNamePlain(command):getCommandName(command)}function priorityProjectFix(scope){let excludeFlags=["--non-interactive","--project","--yes","--scope","--team"],project=scope.type==="project"?{id:scope.projectId,name:scope.displayName}:null,team=priorityTeam(scope),plan=teamPlan(scope)??null,data={project,team:team&&{id:team.id,slug:team.slug,name:team.name},plan},projectToken=project?quoteArg(project.name):"<project>",scopeFlag=team?` --scope ${quoteArg(team.scopeArg)}`:"",enable4=`${PRIORITY_PROJECT_ENABLE_COMMAND} ${projectToken}${scopeFlag}`;if(!team){let hint="Priority projects are only available on team accounts. Use --scope to specify one.";return{command:"",hint,plainHint:hint,when:hint,excludeFlags,preserveProject:!1,reason:AGENT_REASON.MISSING_SCOPE,data}}if(plan==="hobby"||plan==="oss"){let upgrade=`${BUY_PRO_COMMAND}${scopeFlag}`,hint=plain2=>`Priority Projects are only available on Pro or Enterprise team plans. Upgrade with ${styledCommand(upgrade,plain2)}, then run ${styledCommand(enable4,plain2)}.`;return{command:upgrade,hint:hint(!1),plainHint:hint(!0),when:"a person has approved upgrading the plan",excludeFlags,preserveProject:!1,reason:AGENT_REASON.PLAN_UPGRADE_REQUIRED,scope:team.scopeArg,data}}let shown=styledCommand(enable4,!1),plain=styledCommand(enable4,!0),placeholder="Replace <project> with a project on this team.";return{command:enable4,hint:project?shown:`${shown} ${placeholder}`,plainHint:project?plain:`${plain} ${placeholder}`,when:project?"user runs this command in an interactive terminal":"Replace <project> with a project on this team.",excludeFlags,preserveProject:!1,reason:AGENT_REASON.PLAN_UPGRADE_REQUIRED,scope:team.scopeArg,data}}function mapFirewallApiError(e,scope,fallback){let err=e;return scope.type==="team"&&err.status===403?err.code==="plan_not_supported"?`Team-level firewall requires an Enterprise plan (current team: "${scope.displayName}"). Pass --scope <team> or run \`vercel switch\` to target a different team.`:`You need to be a team owner to manage the team-level firewall for "${scope.displayName}".${err.message?` (${err.message})`:""}`:err.message||fallback}function priorityProjectMessage(scope,fix){let team=fix.data.team,label=team?.slug!=null?teamLabel({slug:team.slug,name:team.name}):void 0;return scope.type==="project"?label?`This rule requires a Priority project for ${scope.displayName} on team ${label}.`:`This rule requires a Priority project. ${fix.hint}`:label?`This rule requires a Priority project on team ${label}.`:"This rule requires a Priority project."}function failPriorityProjectGate(client,error,scope,opts){let serverMessage=apiServerMessage(error);if(!serverMessage||!mentionsPriorityProject(serverMessage))return null;let fix=priorityProjectFix(scope),message=priorityProjectMessage(scope,fix),payload={status:AGENT_STATUS.ERROR,reason:fix.reason,message,userActionRequired:!0,hint:fix.plainHint,retryable:!1,...fix.scope?{scope:fix.scope}:{},data:fix.data,...fix.command?{next:[{command:buildCommandWithGlobalFlags(client.argv,fix.command,packageName,{globalFlags:"all",preserveProject:!1,excludeFlags:fix.excludeFlags}),when:fix.when}]}:{}};return shouldEmitNonInteractiveCommandError(client)&&outputAgentError(client,payload,1),opts?.json?(output_manager_default.stopSpinner(),writeAgentError(client,payload),1):(output_manager_default.error(message),fix.command&&output_manager_default.log(fix.hint),1)}function getRulePayload(flags){let legacy=flags["--json"];return legacy!==void 0&&flags["--data"]!==void 0?(output_manager_default.error("Can't use --data with --json."),2):(legacy!==void 0&&output_manager_default.warning("--json is deprecated for rule payloads. Use --data."),flags["--data"]??legacy)}async function parseSubcommandArgs(argv,command,client,commandPath){let parsedArgs,fullPath=commandPath||command.name;try{parsedArgs=parseSubcommandArguments(argv,command)}catch(err){if(client?.nonInteractive){let rawMessage=err instanceof Error?err.message:String(err),flags=getGlobalFlagsFromArgs(client.argv.slice(2),{preserveProject:!0});return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message:rawMessage,next:[{command:getCommandNamePlain(`firewall ${fullPath} ${flags.join(" ")}`.trim()),when:"fix options and retry"}]},2),2}return printError(err),2}return parsedArgs}async function confirmAction(client,skipConfirmation,message,details){return skipConfirmation?!0:client.nonInteractive||!client.stdin.isTTY?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`${message} Re-run with --yes to confirm.`,next:[{command:buildCommandWithYes(client.argv),when:"re-run with --yes to confirm"}]}),process.exit(1),!1):(details&&output_manager_default.print(` ${details}
|
|
11
11
|
`),await client.input.confirm(message,!1))}function firewallPermissionMessage(action,projectName){return`You don't have permission to ${action} for ${projectName}. Ask a team owner to grant access.`}function failFirewall(client,opts){let reason=opts.reason??AGENT_REASON.INVALID_ARGUMENTS,exitCode=getExitCodeForReason(reason);return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason,message:opts.message,...opts.fix?.hint?{hint:opts.fix.hint}:{},next:[...opts.fix?.command?[{command:withGlobalFlags(client,opts.fix.command,void 0,{excludeFlags:opts.fix.excludeFlags,preserveProject:opts.fix.preserveProject}),...opts.fix.when?{when:opts.fix.when}:{}}]:[],...opts.nextCommand?[{command:withGlobalFlags(client,opts.nextCommand)}]:[]]},exitCode),exitCode):(output_manager_default.error(opts.message),opts.fix&&output_manager_default.log(opts.fix.hint),exitCode)}function failFirewallObservabilityPlan(client,error,projectName){let message=apiServerMessage(error)??FIREWALL_ACTIVITY_PLAN_MESSAGE,fix=clientObservabilityPlanRecovery(client,error,message,projectName);return failFirewall(client,{message,fix,reason:AGENT_REASON.API_ERROR})}function refuseManagedBotMutation(client,scope,identifier,verb){if(scope.type!=="project")return null;let id=resolveManagedBotRuleId(identifier);if(!id)return null;let command=`firewall rules update ${id} --action <action>`;return failFirewall(client,{message:`Can't ${verb} "${identifier}". That's a managed bot rule.`,reason:AGENT_REASON.INVALID_ARGUMENTS,fix:{command,hint:`Use ${import_chalk2.default.cyan(withGlobalFlags(client,command,scope))} to change it.`,when:"change the managed bot rule instead"}})}function isRetryableApiError(error){return isAPIError(error)&&(error.status>=500||error.status===429)}function failFirewallApi(client,e,opts){if(isAPIError(e)&&(e.status===401||e.status===403))return failFirewall(client,{message:firewallPermissionMessage(opts.permissionAction,opts.projectName),reason:AGENT_REASON.PERMISSION_DENIED});if(e instanceof Error&&(e.name==="TimeoutError"||e.name==="AbortError")){let job=opts.timeoutJob??"firewall data";return failFirewall(client,{message:`Timed out waiting for ${job}. Re-run the command \u2014 the next try is usually faster.`,nextCommand:opts.nextCommand,reason:AGENT_REASON.API_ERROR})}let msg=e instanceof Error&&e.message?e.message:opts.fallback;return failFirewall(client,{message:msg,nextCommand:isRetryableApiError(e)?opts.nextCommand:void 0,reason:AGENT_REASON.API_ERROR})}function outputJson(client,data){output_manager_default.stopSpinner(),client.stdout.write(JSON.stringify(data,null,2)+`
|
|
12
12
|
`)}async function detectExistingDraft(client,scope){let{draft}=await listFirewallConfigs(client,scope);return draft!==null&&draft.changes.length>0}async function offerAutoPublish(client,scope,hadExistingDraft,opts){if(output_manager_default.print(`
|
|
13
13
|
${import_chalk2.default.gray(`This change is staged. Run ${import_chalk2.default.cyan(withGlobalFlags(client,"firewall publish",scope))} to make it live, or ${import_chalk2.default.cyan(withGlobalFlags(client,"firewall discard",scope))} to undo.`)}
|
|
@@ -58,14 +58,14 @@ ${import_chalk10.default.bold(`Changes to be discarded (${draft.changes.length})
|
|
|
58
58
|
`),!await confirmAction(client,parsed.flags["--yes"],"Discard all draft changes?","This action cannot be undone."))return output_manager_default.log("Canceled"),0;let updateStamp=stamp_default();return output_manager_default.spinner("Discarding draft changes"),await deleteFirewallDraft(client,scope),output_manager_default.log(`${import_chalk10.default.cyan("Success!")} Draft changes discarded ${import_chalk10.default.gray(updateStamp())}`),0}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to discard draft changes");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,"firewall discard --yes",scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk11=__toESM(require_source(),1);async function list(client,argv){let parsed=await parseSubcommandArgs(argv,systemBypassListSubcommand,client,"system-bypass list");if(typeof parsed=="number")return parsed;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;output_manager_default.spinner(`Fetching system bypass rules for ${import_chalk11.default.bold(project.name)}`);try{let{result:allBypasses}=await getBypass(client,project.id,{teamId}),bypasses=allBypasses.filter(b=>!isAllSourcesBypass(b.Ip));return parsed.flags["--json"]?(outputJson(client,bypasses),0):bypasses.length===0?(output_manager_default.log("No system bypass rules configured."),0):(output_manager_default.print(`
|
|
59
59
|
${formatBypassTable(bypasses)}
|
|
60
60
|
|
|
61
|
-
`),0)}catch(e){let msg=e.message||"Failed to fetch bypass rules";return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,"firewall system-bypass list")}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk12=__toESM(require_source(),1);async function addBypass(client,projectId,body,options={}){let{teamId}=options,query=new URLSearchParams;query.set("projectId",projectId),teamId&&query.set("teamId",teamId);let url=`/v1/security/firewall/bypass?${query.toString()}`;return client.fetch(url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)})}import{isIP as isIP2}from"node:net";function parseCidr(input){let slashIndex=input.lastIndexOf("/");if(slashIndex===-1)return null;let ip=input.slice(0,slashIndex),prefixStr=input.slice(slashIndex+1),prefix=Number.parseInt(prefixStr,10);return Number.isNaN(prefix)||prefix<0||String(prefix)!==prefixStr?null:{ip,prefix}}function ipVersion(ip){return isIP2(ip)}function validateBypassIp(input){let version=ipVersion(input);if(version===4||version===6)return null;let cidr=parseCidr(input);if(!cidr)return"Please enter a valid IP address or CIDR.";let cidrVersion=ipVersion(cidr.ip);if(cidrVersion===0)return"Please enter a valid IP address or CIDR.";if(cidrVersion===4){if(cidr.prefix>32)return"Please enter a valid IP address or CIDR.";if(input==="0.0.0.0/0")return null;if(cidr.prefix<16)return"IPv4 CIDR cannot have a net mask less than /16."}if(cidrVersion===6){if(cidr.prefix>128)return"Please enter a valid IP address or CIDR.";if(input==="::/0")return null;if(cidr.prefix<16)return"IPv6 CIDR cannot have a net mask less than /16."}return null}function validateBlockingIp(input){let version=ipVersion(input);if(version===4||version===6)return null;let cidr=parseCidr(input);if(!cidr)return"Please enter a valid IP address or CIDR.";let cidrVersion=ipVersion(cidr.ip);if(cidrVersion===0)return"Please enter a valid IP address or CIDR.";if(cidrVersion===4){if(cidr.prefix>32)return"Please enter a valid IP address or CIDR.";if(cidr.prefix<16)return"IPv4 CIDR cannot have a net mask less than /16."}if(cidrVersion===6){if(cidr.prefix>128)return"Please enter a valid IP address or CIDR.";if(cidr.prefix<48)return"IPv6 CIDR cannot have a net mask less than /48."}return null}function validateHostname(input){return/^\*{1}$|^(?!-)(?:\*\.)?[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*$/.test(input)?null:"Please enter a valid domain (e.g. example.com, *.example.com, or * for all domains)."}function validateNote(input){return input.length>500?`Note must be 500 characters or less (currently ${input.length}).`:null}async function add(client,argv){let parsed=await parseSubcommandArgs(argv,systemBypassAddSubcommand,client,"system-bypass add");if(typeof parsed=="number")return parsed;let ip=parsed.args[0];if(!ip)return output_manager_default.error("Missing required argument: <ip>"),2;let ipError=validateBypassIp(ip);if(ipError)return output_manager_default.error(ipError),1;let domain=parsed.flags["--domain"],notes=parsed.flags["--notes"];if(domain){let domainError=validateHostname(domain);if(domainError)return output_manager_default.error(domainError),1}if(notes){let noteError=validateNote(notes);if(noteError)return output_manager_default.error(noteError),1}let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0,scopeLabel=domain||"all domains";if(!await confirmAction(client,parsed.flags["--yes"],`Add system bypass for ${import_chalk12.default.bold(ip)} on ${import_chalk12.default.bold(scopeLabel)}?`))return output_manager_default.log("Canceled"),0;let addStamp=stamp_default();output_manager_default.spinner("Adding system bypass rule");try{return await addBypass(client,project.id,{sourceIp:ip,...domain?{domain}:{projectScope:!0},...notes?{note:notes}:{}},{teamId}),output_manager_default.log(`${import_chalk12.default.cyan("Success!")} Added system bypass for ${import_chalk12.default.bold(ip)} on ${import_chalk12.default.bold(scopeLabel)} ${import_chalk12.default.gray(addStamp())}`),0}catch(e){let msg=e.message||"Failed to add bypass rule";return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall system-bypass add ${ip}${domain?` --domain ${domain}`:""}${notes?` --notes "${notes}"`:""} --yes`)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk13=__toESM(require_source(),1);async function removeBypass(client,projectId,body,options={}){let{teamId}=options,query=new URLSearchParams;query.set("projectId",projectId),teamId&&query.set("teamId",teamId);let url=`/v1/security/firewall/bypass?${query.toString()}`;return client.fetch(url,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)})}async function remove(client,argv){let parsed=await parseSubcommandArgs(argv,systemBypassRemoveSubcommand,client,"system-bypass remove");if(typeof parsed=="number")return parsed;let ip=parsed.args[0];if(!ip)return output_manager_default.error("Missing required argument: <ip>"),2;let ipError=validateBypassIp(ip);if(ipError)return output_manager_default.error(ipError),1;let domain=parsed.flags["--domain"];if(domain){let domainError=validateHostname(domain);if(domainError)return output_manager_default.error(domainError),1}let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0,scopeLabel=domain||"all domains";if(!await confirmAction(client,parsed.flags["--yes"],`Remove system bypass for ${import_chalk13.default.bold(ip)} on ${import_chalk13.default.bold(scopeLabel)}?`))return output_manager_default.log("Canceled"),0;let removeStamp=stamp_default();output_manager_default.spinner("Removing system bypass rule");try{return await removeBypass(client,project.id,{sourceIp:ip,...domain?{domain}:{projectScope:!0}},{teamId}),output_manager_default.log(`${import_chalk13.default.cyan("Success!")} Removed system bypass for ${import_chalk13.default.bold(ip)} ${import_chalk13.default.gray(removeStamp())}`),0}catch(e){let error=e;if(error.status===404)return output_manager_default.error(`No bypass rule found for ${import_chalk13.default.bold(ip)}. Run ${import_chalk13.default.cyan(withGlobalFlags(client,"firewall system-bypass list"))} to view all rules.`),1;let msg=error.message||"Failed to remove bypass rule";return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall system-bypass remove ${ip}${domain?` --domain ${domain}`:""} --yes`)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var COMMAND_CONFIG={list:getCommandAliases(systemBypassListSubcommand),add:getCommandAliases(systemBypassAddSubcommand),remove:getCommandAliases(systemBypassRemoveSubcommand)};async function main(client,args,telemetry){let flagsSpecification=getFlagsSpecification(systemBypassSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","system-bypass"),output_manager_default.print(help(systemBypassSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-bypass:${subcommandOriginal}`),printHelp(systemBypassListSubcommand),0):(telemetry.trackCliSubcommandSystemBypassList(subcommandOriginal),list(client,subArgs));case"add":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-bypass:${subcommandOriginal}`),printHelp(systemBypassAddSubcommand),0):(telemetry.trackCliSubcommandSystemBypassAdd(subcommandOriginal),add(client,subArgs));case"remove":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-bypass:${subcommandOriginal}`),printHelp(systemBypassRemoveSubcommand),0):(telemetry.trackCliSubcommandSystemBypassRemove(subcommandOriginal),remove(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG)),output_manager_default.print(help(systemBypassSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk14=__toESM(require_source(),1);async function updateAttackMode(client,body){return client.fetch("/security/attack-mode",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)})}var DURATION_MAP={"1h":60*60*1e3,"6h":6*60*60*1e3,"24h":24*60*60*1e3},VALID_DURATIONS2=Object.keys(DURATION_MAP);async function enable(client,argv){let parsed=await parseSubcommandArgs(argv,attackModeEnableSubcommand,client,"attack-mode enable");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Enabling attack mode challenges all visitors and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal to review the impact and confirm.",next:[{command:withGlobalFlags(client,"firewall attack-mode enable"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Enabling attack mode requires interactive confirmation. Please run this command in an interactive terminal."),1;let duration=parsed.flags["--duration"]||"1h";if(!DURATION_MAP[duration])return output_manager_default.error(`Invalid duration "${duration}". Valid options: ${VALID_DURATIONS2.join(", ")}`),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project}=link;if(!await confirmAction(client,parsed.flags["--yes"],`Enable attack mode for ${import_chalk14.default.bold(project.name)} (${import_chalk14.default.bold(duration)})?`,`${import_chalk14.default.yellow("Warning:")} Every visitor will be shown a verification challenge before accessing your site. This may impact legitimate traffic and SEO. Attack mode automatically expires after ${duration}.`))return output_manager_default.log("Canceled"),0;let updateStamp=stamp_default();output_manager_default.spinner("Enabling attack mode");try{return await updateAttackMode(client,{projectId:project.id,attackModeEnabled:!0,attackModeActiveUntil:Date.now()+DURATION_MAP[duration]}),output_manager_default.log(`${import_chalk14.default.cyan("Success!")} Attack mode enabled for ${import_chalk14.default.bold(duration)} ${import_chalk14.default.gray(updateStamp())}`),0}catch(e){let msg=e.message||"Failed to enable attack mode";return output_manager_default.error(msg),1}}var import_chalk15=__toESM(require_source(),1);async function disable(client,argv){let parsed=await parseSubcommandArgs(argv,attackModeDisableSubcommand,client,"attack-mode disable");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Disabling attack mode affects traffic handling and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal.",next:[{command:withGlobalFlags(client,"firewall attack-mode disable"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Disabling attack mode requires interactive confirmation. Please run this command in an interactive terminal."),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project}=link;if(!await confirmAction(client,parsed.flags["--yes"],`Disable attack mode for ${import_chalk15.default.bold(project.name)}?`,"Visitors will no longer be shown a verification challenge."))return output_manager_default.log("Canceled"),0;let updateStamp=stamp_default();output_manager_default.spinner("Disabling attack mode");try{return await updateAttackMode(client,{projectId:project.id,attackModeEnabled:!1}),output_manager_default.log(`${import_chalk15.default.cyan("Success!")} Attack mode disabled ${import_chalk15.default.gray(updateStamp())}`),0}catch(e){let msg=e.message||"Failed to disable attack mode";return output_manager_default.error(msg),1}}var COMMAND_CONFIG2={enable:getCommandAliases(attackModeEnableSubcommand),disable:getCommandAliases(attackModeDisableSubcommand)};async function main2(client,args,telemetry){let flagsSpecification=getFlagsSpecification(attackModeSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG2),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","attack-mode"),output_manager_default.print(help(attackModeSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"enable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`attack-mode:${subcommandOriginal}`),printHelp(attackModeEnableSubcommand),0):(telemetry.trackCliSubcommandAttackModeEnable(subcommandOriginal),enable(client,subArgs));case"disable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`attack-mode:${subcommandOriginal}`),printHelp(attackModeDisableSubcommand),0):(telemetry.trackCliSubcommandAttackModeDisable(subcommandOriginal),disable(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG2)),output_manager_default.print(help(attackModeSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk16=__toESM(require_source(),1);async function pause(client,argv){let parsed=await parseSubcommandArgs(argv,systemMitigationsPauseSubcommand,client,"system-mitigations pause");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Pausing system mitigations disables DDoS protection and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal to review the impact and confirm.",next:[{command:withGlobalFlags(client,"firewall system-mitigations pause"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Pausing system mitigations requires interactive confirmation. Please run this command in an interactive terminal."),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;if(!await confirmAction(client,parsed.flags["--yes"],`Pause system mitigations for ${import_chalk16.default.bold(project.name)}?`,`${import_chalk16.default.yellow("Warning:")} This disables automatic DDoS protection, bot mitigation, and system-level traffic filtering for 24 hours. Your project will be unprotected from automated attacks during this period. Auto-resumes after 24 hours.`))return output_manager_default.log("Canceled"),0;let pauseStamp=stamp_default();output_manager_default.spinner("Pausing system mitigations");try{return await addBypass(client,project.id,{allSources:!0,projectScope:!0},{teamId}),output_manager_default.log(`${import_chalk16.default.cyan("Success!")} System mitigations paused for ${import_chalk16.default.bold(project.name)}. Auto-resumes in 24 hours. ${import_chalk16.default.gray(pauseStamp())}`),0}catch(e){let msg=e.message||"Failed to pause system mitigations";return output_manager_default.error(msg),1}}var import_chalk17=__toESM(require_source(),1);async function resume(client,argv){let parsed=await parseSubcommandArgs(argv,systemMitigationsResumeSubcommand,client,"system-mitigations resume");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Resuming system mitigations affects traffic protection and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal.",next:[{command:withGlobalFlags(client,"firewall system-mitigations resume"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Resuming system mitigations requires interactive confirmation. Please run this command in an interactive terminal."),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;if(!await confirmAction(client,parsed.flags["--yes"],`Resume system mitigations for ${import_chalk17.default.bold(project.name)}?`,"Automatic DDoS protection and system-level traffic filtering will be re-enabled immediately."))return output_manager_default.log("Canceled"),0;let resumeStamp=stamp_default();output_manager_default.spinner("Resuming system mitigations");try{return await removeBypass(client,project.id,{allSources:!0,projectScope:!0},{teamId}),output_manager_default.log(`${import_chalk17.default.cyan("Success!")} System mitigations resumed for ${import_chalk17.default.bold(project.name)} ${import_chalk17.default.gray(resumeStamp())}`),0}catch(e){let msg=e.message||"Failed to resume system mitigations";return output_manager_default.error(msg),1}}var COMMAND_CONFIG3={pause:getCommandAliases(systemMitigationsPauseSubcommand),resume:getCommandAliases(systemMitigationsResumeSubcommand)};async function main3(client,args,telemetry){let flagsSpecification=getFlagsSpecification(systemMitigationsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG3),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","system-mitigations"),output_manager_default.print(help(systemMitigationsSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"pause":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-mitigations:${subcommandOriginal}`),printHelp(systemMitigationsPauseSubcommand),0):(telemetry.trackCliSubcommandSystemMitigationsPause(subcommandOriginal),pause(client,subArgs));case"resume":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-mitigations:${subcommandOriginal}`),printHelp(systemMitigationsResumeSubcommand),0):(telemetry.trackCliSubcommandSystemMitigationsResume(subcommandOriginal),resume(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG3)),output_manager_default.print(help(systemMitigationsSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk18=__toESM(require_source(),1);async function list2(client,argv){let parsed=await parseSubcommandArgs(argv,ipBlocksListSubcommand,client,"ip-blocks list");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching IP blocking rules for ${import_chalk18.default.bold(scope.displayName)}`);try{let{active,draft}=await listFirewallConfigs(client,scope),activeIps=active?.ips||[],draftIps=draft?.ips||null,changes=draft?.changes||[],hasDraftChanges=changes.length>0,annotated=annotateIpRules(activeIps,draftIps,changes);if(parsed.flags["--json"])return outputJson(client,{rules:annotated.map(a=>({...a.rule,_status:a.status})),hasDraft:hasDraftChanges,pendingChanges:changes.length}),0;if(annotated.length===0)return output_manager_default.log("No IP blocking rules configured."),0;output_manager_default.print(`
|
|
61
|
+
`),0)}catch(e){let msg=e.message||"Failed to fetch bypass rules";return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,"firewall system-bypass list")}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk12=__toESM(require_source(),1);async function addBypass(client,projectId,body,options={}){let{teamId}=options,query=new URLSearchParams;query.set("projectId",projectId),teamId&&query.set("teamId",teamId);let url=`/v1/security/firewall/bypass?${query.toString()}`;return client.fetch(url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)})}import{isIP as isIP2}from"node:net";function parseCidr(input){let slashIndex=input.lastIndexOf("/");if(slashIndex===-1)return null;let ip=input.slice(0,slashIndex),prefixStr=input.slice(slashIndex+1),prefix=Number.parseInt(prefixStr,10);return Number.isNaN(prefix)||prefix<0||String(prefix)!==prefixStr?null:{ip,prefix}}function ipVersion(ip){return isIP2(ip)}function validateBypassIp(input){let version=ipVersion(input);if(version===4||version===6)return null;let cidr=parseCidr(input);if(!cidr)return"Please enter a valid IP address or CIDR.";let cidrVersion=ipVersion(cidr.ip);if(cidrVersion===0)return"Please enter a valid IP address or CIDR.";if(cidrVersion===4){if(cidr.prefix>32)return"Please enter a valid IP address or CIDR.";if(input==="0.0.0.0/0")return null;if(cidr.prefix<16)return"IPv4 CIDR cannot have a net mask less than /16."}if(cidrVersion===6){if(cidr.prefix>128)return"Please enter a valid IP address or CIDR.";if(input==="::/0")return null;if(cidr.prefix<16)return"IPv6 CIDR cannot have a net mask less than /16."}return null}function validateBlockingIp(input){let version=ipVersion(input);if(version===4||version===6)return null;let cidr=parseCidr(input);if(!cidr)return"Please enter a valid IP address or CIDR.";let cidrVersion=ipVersion(cidr.ip);if(cidrVersion===0)return"Please enter a valid IP address or CIDR.";if(cidrVersion===4){if(cidr.prefix>32)return"Please enter a valid IP address or CIDR.";if(cidr.prefix<16)return"IPv4 CIDR cannot have a net mask less than /16."}if(cidrVersion===6){if(cidr.prefix>128)return"Please enter a valid IP address or CIDR.";if(cidr.prefix<48)return"IPv6 CIDR cannot have a net mask less than /48."}return null}function validateHostname(input){return/^\*{1}$|^(?!-)(?:\*\.)?[A-Za-z0-9-]{1,63}(?<!-)(?:\.(?!-)[A-Za-z0-9-]{1,63}(?<!-))*$/.test(input)?null:"Please enter a valid domain (e.g. example.com, *.example.com, or * for all domains)."}function validateNote(input){return input.length>500?`Note must be 500 characters or less (currently ${input.length}).`:null}async function add(client,argv){let parsed=await parseSubcommandArgs(argv,systemBypassAddSubcommand,client,"system-bypass add");if(typeof parsed=="number")return parsed;let ip=parsed.args[0];if(!ip)return output_manager_default.error("Missing required argument: <ip>"),2;let ipError=validateBypassIp(ip);if(ipError)return output_manager_default.error(ipError),1;let domain=parsed.flags["--domain"],notes=parsed.flags["--notes"];if(domain){let domainError=validateHostname(domain);if(domainError)return output_manager_default.error(domainError),1}if(notes){let noteError=validateNote(notes);if(noteError)return output_manager_default.error(noteError),1}let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0,scopeLabel=domain||"all domains";if(!await confirmAction(client,parsed.flags["--yes"],`Add system bypass for ${import_chalk12.default.bold(ip)} on ${import_chalk12.default.bold(scopeLabel)}?`))return output_manager_default.log("Canceled"),0;let addStamp=stamp_default();output_manager_default.spinner("Adding system bypass rule");try{return await addBypass(client,project.id,{sourceIp:ip,...domain?{domain}:{projectScope:!0},...notes?{note:notes}:{}},{teamId}),output_manager_default.log(`${import_chalk12.default.cyan("Success!")} Added system bypass for ${import_chalk12.default.bold(ip)} on ${import_chalk12.default.bold(scopeLabel)} ${import_chalk12.default.gray(addStamp())}`),0}catch(e){let msg=e.message||"Failed to add bypass rule";return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall system-bypass add ${ip}${domain?` --domain ${domain}`:""}${notes?` --notes "${notes}"`:""} --yes`)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk13=__toESM(require_source(),1);async function removeBypass(client,projectId,body,options={}){let{teamId}=options,query=new URLSearchParams;query.set("projectId",projectId),teamId&&query.set("teamId",teamId);let url=`/v1/security/firewall/bypass?${query.toString()}`;return client.fetch(url,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)})}async function remove(client,argv){let parsed=await parseSubcommandArgs(argv,systemBypassRemoveSubcommand,client,"system-bypass remove");if(typeof parsed=="number")return parsed;let ip=parsed.args[0];if(!ip)return output_manager_default.error("Missing required argument: <ip>"),2;let ipError=validateBypassIp(ip);if(ipError)return output_manager_default.error(ipError),1;let domain=parsed.flags["--domain"];if(domain){let domainError=validateHostname(domain);if(domainError)return output_manager_default.error(domainError),1}let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0,scopeLabel=domain||"all domains";if(!await confirmAction(client,parsed.flags["--yes"],`Remove system bypass for ${import_chalk13.default.bold(ip)} on ${import_chalk13.default.bold(scopeLabel)}?`))return output_manager_default.log("Canceled"),0;let removeStamp=stamp_default();output_manager_default.spinner("Removing system bypass rule");try{return await removeBypass(client,project.id,{sourceIp:ip,...domain?{domain}:{projectScope:!0}},{teamId}),output_manager_default.log(`${import_chalk13.default.cyan("Success!")} Removed system bypass for ${import_chalk13.default.bold(ip)} ${import_chalk13.default.gray(removeStamp())}`),0}catch(e){let error=e;if(error.status===404)return output_manager_default.error(`No bypass rule found for ${import_chalk13.default.bold(ip)}. Run ${import_chalk13.default.cyan(withGlobalFlags(client,"firewall system-bypass list"))} to view all rules.`),1;let msg=error.message||"Failed to remove bypass rule";return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall system-bypass remove ${ip}${domain?` --domain ${domain}`:""} --yes`)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var COMMAND_CONFIG={list:getCommandAliases(systemBypassListSubcommand),add:getCommandAliases(systemBypassAddSubcommand),remove:getCommandAliases(systemBypassRemoveSubcommand)};async function main(client,args,telemetry){let flagsSpecification=getFlagsSpecification(systemBypassSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","system-bypass"),output_manager_default.print(help(systemBypassSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-bypass:${subcommandOriginal}`),printHelp(systemBypassListSubcommand),0):(telemetry.trackCliSubcommandSystemBypassList(subcommandOriginal),list(client,subArgs));case"add":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-bypass:${subcommandOriginal}`),printHelp(systemBypassAddSubcommand),0):(telemetry.trackCliSubcommandSystemBypassAdd(subcommandOriginal),add(client,subArgs));case"remove":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-bypass:${subcommandOriginal}`),printHelp(systemBypassRemoveSubcommand),0):(telemetry.trackCliSubcommandSystemBypassRemove(subcommandOriginal),remove(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG)),output_manager_default.print(help(systemBypassSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk14=__toESM(require_source(),1);async function updateAttackMode(client,body){return client.fetch("/security/attack-mode",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)})}var DURATION_MAP={"1h":60*60*1e3,"6h":6*60*60*1e3,"24h":24*60*60*1e3},VALID_DURATIONS2=Object.keys(DURATION_MAP);async function enable(client,argv){let parsed=await parseSubcommandArgs(argv,attackModeEnableSubcommand,client,"attack-mode enable");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Enabling attack mode challenges all visitors and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal to review the impact and confirm.",next:[{command:withGlobalFlags(client,"firewall attack-mode enable"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Enabling attack mode requires interactive confirmation. Please run this command in an interactive terminal."),1;let duration=parsed.flags["--duration"]||"1h";if(!DURATION_MAP[duration])return output_manager_default.error(`Invalid duration "${duration}". Valid options: ${VALID_DURATIONS2.join(", ")}`),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project}=link;if(!await confirmAction(client,parsed.flags["--yes"],`Enable attack mode for ${import_chalk14.default.bold(project.name)} (${import_chalk14.default.bold(duration)})?`,`${import_chalk14.default.yellow("Warning:")} Every visitor will be shown a verification challenge before accessing your site. This may impact legitimate traffic and SEO. Attack mode automatically expires after ${duration}.`))return output_manager_default.log("Canceled"),0;let updateStamp=stamp_default();output_manager_default.spinner("Enabling attack mode");try{return await updateAttackMode(client,{projectId:project.id,attackModeEnabled:!0,attackModeActiveUntil:Date.now()+DURATION_MAP[duration]}),output_manager_default.log(`${import_chalk14.default.cyan("Success!")} Attack mode enabled for ${import_chalk14.default.bold(duration)} ${import_chalk14.default.gray(updateStamp())}`),0}catch(e){let msg=e.message||"Failed to enable attack mode";return output_manager_default.error(msg),1}}var import_chalk15=__toESM(require_source(),1);async function disable(client,argv){let parsed=await parseSubcommandArgs(argv,attackModeDisableSubcommand,client,"attack-mode disable");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Disabling attack mode affects traffic handling and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal.",next:[{command:withGlobalFlags(client,"firewall attack-mode disable"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Disabling attack mode requires interactive confirmation. Please run this command in an interactive terminal."),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project}=link;if(!await confirmAction(client,parsed.flags["--yes"],`Disable attack mode for ${import_chalk15.default.bold(project.name)}?`,"Visitors will no longer be shown a verification challenge."))return output_manager_default.log("Canceled"),0;let updateStamp=stamp_default();output_manager_default.spinner("Disabling attack mode");try{return await updateAttackMode(client,{projectId:project.id,attackModeEnabled:!1}),output_manager_default.log(`${import_chalk15.default.cyan("Success!")} Attack mode disabled ${import_chalk15.default.gray(updateStamp())}`),0}catch(e){let msg=e.message||"Failed to disable attack mode";return output_manager_default.error(msg),1}}var COMMAND_CONFIG2={enable:getCommandAliases(attackModeEnableSubcommand),disable:getCommandAliases(attackModeDisableSubcommand)};async function main2(client,args,telemetry){let flagsSpecification=getFlagsSpecification(attackModeSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG2),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","attack-mode"),output_manager_default.print(help(attackModeSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"enable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`attack-mode:${subcommandOriginal}`),printHelp(attackModeEnableSubcommand),0):(telemetry.trackCliSubcommandAttackModeEnable(subcommandOriginal),enable(client,subArgs));case"disable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`attack-mode:${subcommandOriginal}`),printHelp(attackModeDisableSubcommand),0):(telemetry.trackCliSubcommandAttackModeDisable(subcommandOriginal),disable(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG2)),output_manager_default.print(help(attackModeSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk16=__toESM(require_source(),1);async function pause(client,argv){let parsed=await parseSubcommandArgs(argv,systemMitigationsPauseSubcommand,client,"system-mitigations pause");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Pausing system mitigations disables DDoS protection and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal to review the impact and confirm.",next:[{command:withGlobalFlags(client,"firewall system-mitigations pause"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Pausing system mitigations requires interactive confirmation. Please run this command in an interactive terminal."),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;if(!await confirmAction(client,parsed.flags["--yes"],`Pause system mitigations for ${import_chalk16.default.bold(project.name)}?`,`${import_chalk16.default.yellow("Warning:")} This disables automatic DDoS protection, bot mitigation, and system-level traffic filtering for 24 hours. Your project will be unprotected from automated attacks during this period. Auto-resumes after 24 hours.`))return output_manager_default.log("Canceled"),0;let pauseStamp=stamp_default();output_manager_default.spinner("Pausing system mitigations");try{return await addBypass(client,project.id,{allSources:!0,projectScope:!0},{teamId}),output_manager_default.log(`${import_chalk16.default.cyan("Success!")} System mitigations paused for ${import_chalk16.default.bold(project.name)}. Auto-resumes in 24 hours. ${import_chalk16.default.gray(pauseStamp())}`),0}catch(e){let msg=e.message||"Failed to pause system mitigations";return output_manager_default.error(msg),1}}var import_chalk17=__toESM(require_source(),1);async function resume(client,argv){let parsed=await parseSubcommandArgs(argv,systemMitigationsResumeSubcommand,client,"system-mitigations resume");if(typeof parsed=="number")return parsed;if(client.nonInteractive)return outputAgentError(client,{status:"error",reason:"dangerous_operation_requires_user",message:"Resuming system mitigations affects traffic protection and cannot be performed non-interactively. Agents must not make this change on behalf of a user. The user must run this command interactively in a terminal.",next:[{command:withGlobalFlags(client,"firewall system-mitigations resume"),when:"user runs this command interactively"}]},1),1;if(!client.stdin.isTTY)return output_manager_default.error("Resuming system mitigations requires interactive confirmation. Please run this command in an interactive terminal."),1;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;if(!await confirmAction(client,parsed.flags["--yes"],`Resume system mitigations for ${import_chalk17.default.bold(project.name)}?`,"Automatic DDoS protection and system-level traffic filtering will be re-enabled immediately."))return output_manager_default.log("Canceled"),0;let resumeStamp=stamp_default();output_manager_default.spinner("Resuming system mitigations");try{return await removeBypass(client,project.id,{allSources:!0,projectScope:!0},{teamId}),output_manager_default.log(`${import_chalk17.default.cyan("Success!")} System mitigations resumed for ${import_chalk17.default.bold(project.name)} ${import_chalk17.default.gray(resumeStamp())}`),0}catch(e){let msg=e.message||"Failed to resume system mitigations";return output_manager_default.error(msg),1}}var COMMAND_CONFIG3={pause:getCommandAliases(systemMitigationsPauseSubcommand),resume:getCommandAliases(systemMitigationsResumeSubcommand)};async function main3(client,args,telemetry){let flagsSpecification=getFlagsSpecification(systemMitigationsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG3),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","system-mitigations"),output_manager_default.print(help(systemMitigationsSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"pause":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-mitigations:${subcommandOriginal}`),printHelp(systemMitigationsPauseSubcommand),0):(telemetry.trackCliSubcommandSystemMitigationsPause(subcommandOriginal),pause(client,subArgs));case"resume":return needHelp?(telemetry.trackCliFlagHelp("firewall",`system-mitigations:${subcommandOriginal}`),printHelp(systemMitigationsResumeSubcommand),0):(telemetry.trackCliSubcommandSystemMitigationsResume(subcommandOriginal),resume(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG3)),output_manager_default.print(help(systemMitigationsSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk18=__toESM(require_source(),1);async function list2(client,argv){let parsed=await parseSubcommandArgs(argv,ipBlocksListSubcommand,client,"ip-blocks list");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching IP blocking rules for ${import_chalk18.default.bold(scope.displayName)}`);try{let{active,draft}=await listFirewallConfigs(client,scope),activeIps=active?.ips||[],draftIps=draft?.ips||null,changes=draft?.changes||[],hasDraftChanges=changes.length>0,annotated=annotateIpRules(activeIps,draftIps,changes);if(parsed.flags["--json"])return outputJson(client,{rules:annotated.map(a=>({...a.rule,_status:a.status})),hasDraft:hasDraftChanges,pendingChanges:changes.length}),0;if(annotated.length===0)return output_manager_default.log("No IP blocking rules configured."),0;output_manager_default.print(`
|
|
62
62
|
${formatIpBlocksTable(annotated)}
|
|
63
63
|
`);let ipChanges=changes.filter(c=>c.action.startsWith("ip.")).length;return ipChanges>0?output_manager_default.print(`
|
|
64
64
|
${import_chalk18.default.yellow(`${ipChanges} unpublished IP block change${ipChanges!==1?"s":""}.`)} Run ${import_chalk18.default.cyan(withGlobalFlags(client,"firewall publish",scope))} to publish.
|
|
65
65
|
`):output_manager_default.print(`
|
|
66
66
|
${import_chalk18.default.dim("Showing live configuration.")}
|
|
67
67
|
`),output_manager_default.print(`
|
|
68
|
-
`),0}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to fetch IP blocking rules");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,"firewall ip-blocks list",scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk19=__toESM(require_source(),1);async function patchFirewallDraft(client,scope,patch){return client.fetch(firewallConfigUrl(scope,"/draft"),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(patch)})}async function block(client,argv){let parsed=await parseSubcommandArgs(argv,ipBlocksBlockSubcommand,client,"ip-blocks block");if(typeof parsed=="number")return parsed;let ip=parsed.args[0];if(!ip)return output_manager_default.error("Missing required argument: <ip>"),2;let ipError=validateBlockingIp(ip);if(ipError)return output_manager_default.error(ipError),1;let hostnameFlag=parsed.flags["--hostname"],hostname=hostnameFlag&&hostnameFlag!==""?hostnameFlag:"*",notes=parsed.flags["--notes"];if(hostname!=="*"){let hostnameError=validateHostname(hostname);if(hostnameError)return output_manager_default.error(hostnameError),1}if(notes){let noteError=validateNote(notes);if(noteError)return output_manager_default.error(noteError),1}let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let hostnameLabel=hostname==="*"||hostname===""?"all hosts":hostname;if(!await confirmAction(client,parsed.flags["--yes"],`Block ${import_chalk19.default.bold(ip)} on ${import_chalk19.default.bold(hostnameLabel)}?`))return output_manager_default.log("Canceled"),0;let blockStamp=stamp_default();output_manager_default.spinner("Staging IP block rule");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"ip.insert",id:null,value:{ip,hostname,action:"deny",...notes?{notes}:{}}}),output_manager_default.log(`${import_chalk19.default.cyan("Success!")} IP block for ${import_chalk19.default.bold(ip)} on ${import_chalk19.default.bold(hostnameLabel)} staged ${import_chalk19.default.gray(blockStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to stage IP block rule");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall ip-blocks block ${ip}${hostname!=="*"?` --hostname ${hostname}`:""} --yes`,scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk20=__toESM(require_source(),1);async function unblock(client,argv){let parsed=await parseSubcommandArgs(argv,ipBlocksUnblockSubcommand,client,"ip-blocks unblock");if(typeof parsed=="number")return parsed;let identifier=parsed.args[0];if(!identifier)return output_manager_default.error("Missing required argument: <id-or-ip>"),2;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching IP blocking rules for ${import_chalk20.default.bold(scope.displayName)}`);try{let{active,draft}=await listFirewallConfigs(client,scope),currentIps=draft?.ips||active?.ips||[],hostnameFlag=parsed.flags["--hostname"],matches=resolveIpRule(currentIps,identifier);if(hostnameFlag&&matches.length>1){let filtered=matches.filter(r=>r.hostname.toLowerCase()===hostnameFlag.toLowerCase());filtered.length>0&&(matches=filtered)}if(matches.length===0)return output_manager_default.error(`No IP block found for "${identifier}". Run ${import_chalk20.default.cyan(withGlobalFlags(client,"firewall ip-blocks list",scope))} to view all rules.`),1;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple IP blocks match "${identifier}". Use --hostname to narrow the match or specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall ip-blocks unblock "${identifier}" --hostname "${r.hostname}" --yes`,scope),when:`unblock on ${r.hostname==="*"?"all hosts":r.hostname}`}))},1),output_manager_default.error(`Multiple IP blocks match "${identifier}". Use --hostname to narrow the match or specify the full rule ID.`),1;let selectedId=await client.input.select({message:`Multiple IP blocks match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.ip} on ${r.hostname==="*"?"all hosts":r.hostname} (${r.action})${r.notes?` \u2014 ${r.notes}`:""}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}let hostnameLabel=rule.hostname==="*"||rule.hostname===""?"all hosts":rule.hostname;if(output_manager_default.stopSpinner(),!await confirmAction(client,parsed.flags["--yes"],`Remove IP block for ${import_chalk20.default.bold(rule.ip)} on ${import_chalk20.default.bold(hostnameLabel)}?`))return output_manager_default.log("Canceled"),0;let unblockStamp=stamp_default();output_manager_default.spinner("Staging IP block removal");let hadExistingDraft=draft!==null&&draft.changes.length>0;return await patchFirewallDraft(client,scope,{action:"ip.remove",id:rule.id,value:null}),output_manager_default.log(`${import_chalk20.default.cyan("Success!")} IP block removal for ${import_chalk20.default.bold(rule.ip)} staged ${import_chalk20.default.gray(unblockStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to stage IP block removal");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall ip-blocks unblock ${identifier} --yes`,scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var COMMAND_CONFIG4={list:getCommandAliases(ipBlocksListSubcommand),block:getCommandAliases(ipBlocksBlockSubcommand),unblock:getCommandAliases(ipBlocksUnblockSubcommand)};async function main4(client,args,telemetry){let flagsSpecification=getFlagsSpecification(ipBlocksSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG4),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","ip-blocks"),output_manager_default.print(help(ipBlocksSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`ip-blocks:${subcommandOriginal}`),printHelp(ipBlocksListSubcommand),0):(telemetry.trackCliSubcommandIpBlocksList(subcommandOriginal),list2(client,subArgs));case"block":return needHelp?(telemetry.trackCliFlagHelp("firewall",`ip-blocks:${subcommandOriginal}`),printHelp(ipBlocksBlockSubcommand),0):(telemetry.trackCliSubcommandIpBlocksBlock(subcommandOriginal),block(client,subArgs));case"unblock":return needHelp?(telemetry.trackCliFlagHelp("firewall",`ip-blocks:${subcommandOriginal}`),printHelp(ipBlocksUnblockSubcommand),0):(telemetry.trackCliSubcommandIpBlocksUnblock(subcommandOriginal),subcommandOriginal==="rm"&&warnDeprecatedSubcommand(client,"firewall ip-blocks rm","firewall ip-blocks unblock"),unblock(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG4)),output_manager_default.print(help(ipBlocksSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk21=__toESM(require_source(),1);function unpublishedRuleChangeCount(changes){return changes.filter(c=>c.action.startsWith("rules.")||c.action==="managedRules.update"||c.action==="botId.toggle").length}async function list3(client,argv){let parsed=await parseSubcommandArgs(argv,rulesListSubcommand,client,"rules list");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching rules for ${import_chalk21.default.bold(scope.displayName)}`);try{let{active,draft}=await listFirewallConfigs(client,scope),config=draft??active,managed=scope.type==="project"?getManagedBotRules(config):[],activeRules=active?.rules||[],draftRules=draft?.rules||null,changes=draft?.changes||[],annotated=annotateRules(activeRules,draftRules,changes);if(parsed.flags["--json"])return outputJson(client,{...scope.type==="project"?{managed:managed.map(managedBotJson)}:{},rules:annotated.map(a=>({...a.rule,_status:a.status})),hasDraft:changes.length>0,pendingChanges:changes.length}),0;if(scope.type==="project"&&output_manager_default.print(`
|
|
68
|
+
`),0}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to fetch IP blocking rules");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,"firewall ip-blocks list",scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk19=__toESM(require_source(),1);async function patchFirewallDraft(client,scope,patch){return client.fetch(firewallConfigUrl(scope,"/draft"),{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(patch)})}async function block(client,argv){let parsed=await parseSubcommandArgs(argv,ipBlocksBlockSubcommand,client,"ip-blocks block");if(typeof parsed=="number")return parsed;let ip=parsed.args[0];if(!ip)return output_manager_default.error("Missing required argument: <ip>"),2;let ipError=validateBlockingIp(ip);if(ipError)return output_manager_default.error(ipError),1;let hostnameFlag=parsed.flags["--hostname"],hostname=hostnameFlag&&hostnameFlag!==""?hostnameFlag:"*",notes=parsed.flags["--notes"];if(hostname!=="*"){let hostnameError=validateHostname(hostname);if(hostnameError)return output_manager_default.error(hostnameError),1}if(notes){let noteError=validateNote(notes);if(noteError)return output_manager_default.error(noteError),1}let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let hostnameLabel=hostname==="*"||hostname===""?"all hosts":hostname;if(!await confirmAction(client,parsed.flags["--yes"],`Block ${import_chalk19.default.bold(ip)} on ${import_chalk19.default.bold(hostnameLabel)}?`))return output_manager_default.log("Canceled"),0;let blockStamp=stamp_default();output_manager_default.spinner("Staging IP block rule");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"ip.insert",id:null,value:{ip,hostname,action:"deny",...notes?{notes}:{}}}),output_manager_default.log(`${import_chalk19.default.cyan("Success!")} IP block for ${import_chalk19.default.bold(ip)} on ${import_chalk19.default.bold(hostnameLabel)} staged ${import_chalk19.default.gray(blockStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to stage IP block rule");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall ip-blocks block ${ip}${hostname!=="*"?` --hostname ${hostname}`:""} --yes`,scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk20=__toESM(require_source(),1);async function unblock(client,argv){let parsed=await parseSubcommandArgs(argv,ipBlocksUnblockSubcommand,client,"ip-blocks unblock");if(typeof parsed=="number")return parsed;let identifier=parsed.args[0];if(!identifier)return output_manager_default.error("Missing required argument: <id-or-ip>"),2;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching IP blocking rules for ${import_chalk20.default.bold(scope.displayName)}`);try{let{active,draft}=await listFirewallConfigs(client,scope),currentIps=draft?.ips||active?.ips||[],hostnameFlag=parsed.flags["--hostname"],matches=resolveIpRule(currentIps,identifier);if(hostnameFlag&&matches.length>1){let filtered=matches.filter(r=>r.hostname.toLowerCase()===hostnameFlag.toLowerCase());filtered.length>0&&(matches=filtered)}if(matches.length===0)return output_manager_default.error(`No IP block found for "${identifier}". Run ${import_chalk20.default.cyan(withGlobalFlags(client,"firewall ip-blocks list",scope))} to view all rules.`),1;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple IP blocks match "${identifier}". Use --hostname to narrow the match or specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall ip-blocks unblock "${identifier}" --hostname "${r.hostname}" --yes`,scope),when:`unblock on ${r.hostname==="*"?"all hosts":r.hostname}`}))},1),output_manager_default.error(`Multiple IP blocks match "${identifier}". Use --hostname to narrow the match or specify the full rule ID.`),1;let selectedId=await client.input.select({message:`Multiple IP blocks match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.ip} on ${r.hostname==="*"?"all hosts":r.hostname} (${r.action})${r.notes?` \u2014 ${r.notes}`:""}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}let hostnameLabel=rule.hostname==="*"||rule.hostname===""?"all hosts":rule.hostname;if(output_manager_default.stopSpinner(),!await confirmAction(client,parsed.flags["--yes"],`Remove IP block for ${import_chalk20.default.bold(rule.ip)} on ${import_chalk20.default.bold(hostnameLabel)}?`))return output_manager_default.log("Canceled"),0;let unblockStamp=stamp_default();output_manager_default.spinner("Staging IP block removal");let hadExistingDraft=draft!==null&&draft.changes.length>0;return await patchFirewallDraft(client,scope,{action:"ip.remove",id:rule.id,value:null}),output_manager_default.log(`${import_chalk20.default.cyan("Success!")} IP block removal for ${import_chalk20.default.bold(rule.ip)} staged ${import_chalk20.default.gray(unblockStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to stage IP block removal");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall ip-blocks unblock ${identifier} --yes`,scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var COMMAND_CONFIG4={list:getCommandAliases(ipBlocksListSubcommand),block:getCommandAliases(ipBlocksBlockSubcommand),unblock:getCommandAliases(ipBlocksUnblockSubcommand)};async function main4(client,args,telemetry){let flagsSpecification=getFlagsSpecification(ipBlocksSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG4),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","ip-blocks"),output_manager_default.print(help(ipBlocksSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`ip-blocks:${subcommandOriginal}`),printHelp(ipBlocksListSubcommand),0):(telemetry.trackCliSubcommandIpBlocksList(subcommandOriginal),list2(client,subArgs));case"block":return needHelp?(telemetry.trackCliFlagHelp("firewall",`ip-blocks:${subcommandOriginal}`),printHelp(ipBlocksBlockSubcommand),0):(telemetry.trackCliSubcommandIpBlocksBlock(subcommandOriginal),block(client,subArgs));case"unblock":return needHelp?(telemetry.trackCliFlagHelp("firewall",`ip-blocks:${subcommandOriginal}`),printHelp(ipBlocksUnblockSubcommand),0):(telemetry.trackCliSubcommandIpBlocksUnblock(subcommandOriginal),subcommandOriginal==="rm"&&warnDeprecatedSubcommand(client,"firewall ip-blocks rm","firewall ip-blocks unblock"),unblock(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG4)),output_manager_default.print(help(ipBlocksSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk21=__toESM(require_source(),1);function unpublishedRuleChangeCount(changes){return changes.filter(c=>c.action.startsWith("rules.")||c.action==="managedRules.update"||c.action==="botId.toggle").length}async function list3(client,argv){let parsed=await parseSubcommandArgs(argv,rulesListSubcommand,client,"rules list");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching rules for ${import_chalk21.default.bold(scope.displayName)}`);try{let{active,draft}=await listFirewallConfigs(client,scope),config=draft??active,managed=scope.type==="project"?getManagedBotRules(config):[],activeRules=active?.rules||[],draftRules=draft?.rules||null,changes=draft?.changes||[],annotated=annotateRules(activeRules,draftRules,changes);if(parsed.flags["--json"])return outputJson(client,{...scope.type==="project"?{managed:managed.map(managedBotJson)}:{},rules:annotated.map(a=>({...a.rule,_status:a.status})),hasDraft:changes.length>0,pendingChanges:changes.length}),0;if(scope.type==="project"&&output_manager_default.print(`
|
|
69
69
|
${formatManagedBotRulesTable(managed)}
|
|
70
70
|
`),annotated.length===0)if(scope.type==="project")output_manager_default.print(`
|
|
71
71
|
${import_chalk21.default.bold("Custom")}
|
|
@@ -99,7 +99,7 @@ ${import_chalk22.default.dim(" Change this rule:")}
|
|
|
99
99
|
`),0)}let currentRules=draft?.rules||active?.rules||[],matches=resolveRule(currentRules,identifier);if(matches.length===0)return output_manager_default.stopSpinner(),client.nonInteractive&&outputAgentError(client,{status:"error",reason:"not_found",message:`No rule found for "${identifier}".`,next:[{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},1),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk22.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules inspect "${r.id}"`,scope),when:`inspect "${r.name}"`}))},1),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] (${r.id})`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}return parsed.flags["--json"]?(outputJson(client,rule),0):(output_manager_default.print(`
|
|
100
100
|
${formatRuleDetail(rule)}
|
|
101
101
|
|
|
102
|
-
`),0)}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to fetch rules");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall rules inspect ${identifier}`,scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk26=__toESM(require_source(),1);function parseConditionFlags(conditionFlags){if(conditionFlags.length===0)return"At least one --condition is required.";let groups=[{conditions:[]}];for(let flag of conditionFlags){if(flag==="--or"){if(groups[groups.length-1].conditions.length===0)return"--or cannot be placed before any conditions or consecutively.";groups.push({conditions:[]});continue}let result=parseConditionFlag(flag);if(typeof result=="string")return result;groups[groups.length-1].conditions.push(result)}return groups[groups.length-1].conditions.length===0?"--or cannot be the last
|
|
102
|
+
`),0)}catch(e){let msg=mapFirewallApiError(e,scope,"Failed to fetch rules");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall rules inspect ${identifier}`,scope)}]}),process.exit(1),1):(output_manager_default.error(msg),1)}}var import_chalk26=__toESM(require_source(),1);function parseConditionFlags(conditionFlags){if(conditionFlags.length===0)return"At least one --condition is required.";let groups=[{conditions:[]}];for(let flag of conditionFlags){if(flag==="--or"){if(groups[groups.length-1].conditions.length===0)return"--or cannot be placed before any conditions or consecutively.";groups.push({conditions:[]});continue}let result=parseConditionFlag(flag);if(typeof result=="string")return result;groups[groups.length-1].conditions.push(result)}return groups[groups.length-1].conditions.length===0?"--or cannot be the last option \u2014 add conditions after it.":{groups}}function parseConditionFlag(flag){let parsed;try{parsed=JSON.parse(flag)}catch{return`Invalid condition JSON: "${flag}". Expected a JSON object like {"type":"path","op":"pre","value":"/api"}.`}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return`Invalid condition: expected a JSON object, got ${typeof parsed}.`;let type=parsed.type;if(!type||typeof type!="string")return'Condition must have a "type" field (string).';let meta=CONDITION_TYPE_MAP[type],op=parsed.op;if(!op||typeof op!="string")return`Condition must have an "op" field (string). Valid operators: ${ALL_OPERATORS.join(", ")}`;if(!ALL_OPERATORS.includes(op)){let validOps=meta?meta.operators.join(", "):ALL_OPERATORS.join(", ");return`Invalid operator "${op}" for condition type "${type}". Valid operators: ${validOps}`}let requiresKey=meta?.requiresKey??!1,key=parsed.key;if(requiresKey&&!key)return`Condition type "${type}" requires a "key" field. Example: {"type":"${type}","key":"name","op":"${op}","value":"..."}`;let neg=parsed.neg===!0,condition={type,op};neg&&(condition.neg=!0),key&&(condition.key=key);let value=parsed.value;if(!(op==="ex"||op==="nex"))if(op==="inc"||op==="ninc"){if(!value)return`Operator "inc" requires a "value" field. Example: {"type":"${type}","op":"inc","value":"val1,val2"}`;Array.isArray(value)?condition.value=value.map(String):condition.value=String(value).split(",").map(v=>v.trim())}else if(op==="gt"||op==="gte"||op==="lt"||op==="lte"){if(value==null)return`Operator "${op}" requires a numeric "value" field.`;let num=Number(value);if(Number.isNaN(num))return`Operator "${op}" requires a numeric value, got "${value}".`;condition.value=num}else if(op==="re"){if(!value)return'Operator "re" requires a "value" field with a regex pattern.';try{new RegExp(String(value))}catch{return`Invalid regex pattern: "${value}".`}condition.value=String(value)}else{if(value==null)return`Operator "${op}" requires a "value" field.`;condition.value=String(value)}return condition}function buildActionFromFlags(flags,actionType){let duration=flags["--duration"];if(duration&&!VALID_DURATIONS.includes(duration))return`Invalid duration "${duration}". Valid durations: ${VALID_DURATIONS.join(", ")}`;let action={mitigate:{action:actionType,rateLimit:null,redirect:null,actionDuration:duration||null}};if(actionType==="rate_limit"){let algo=flags["--rate-limit-algo"]||"fixed_window",window=flags["--rate-limit-window"],requests=flags["--rate-limit-requests"],keys=flags["--rate-limit-keys"]||["ip"];if(!VALID_ALGORITHMS.includes(algo))return`Invalid rate limit algorithm "${algo}". Valid: ${VALID_ALGORITHMS.join(", ")}`;if(!window||window<10)return"Rate limit --rate-limit-window is required (minimum 10 seconds).";if(window>3600)return"Rate limit --rate-limit-window maximum is 3600 seconds (1 hour).";if(!requests||requests<1)return"Rate limit --rate-limit-requests is required (minimum 1).";if(requests>1e7)return"Rate limit --rate-limit-requests maximum is 10,000,000.";let rlAction=flags["--rate-limit-action"]||"rate_limit",validRlActions=["log","deny","challenge","rate_limit"];if(!validRlActions.includes(rlAction))return`Invalid rate limit action "${rlAction}". Valid: ${validRlActions.join(", ")}`;action.mitigate.rateLimit={algo,window,limit:requests,keys,action:rlAction}}if(actionType==="redirect"){let redirectUrl=flags["--redirect-url"],permanent=!!flags["--redirect-permanent"];if(!redirectUrl)return"Redirect action requires --redirect-url.";if(!redirectUrl.startsWith("/")&&!redirectUrl.startsWith("http://")&&!redirectUrl.startsWith("https://"))return"Redirect URL must start with /, http://, or https://";action.mitigate.redirect={location:redirectUrl,permanent}}return action}var import_chalk25=__toESM(require_source(),1);async function generateFirewallRule(client,projectId,body,options={}){let{teamId}=options,query=new URLSearchParams;query.set("projectId",projectId),teamId&&query.set("teamId",teamId);let url=`/v1/security/firewall/config/generate-rule?${query.toString()}`;return client.fetch(url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)})}var import_chalk24=__toESM(require_source(),1);var import_chalk23=__toESM(require_source(),1);async function addInteractive(client,scope,opts={}){let pre=opts.prePopulated,planInfo=await fetchPlanInfo(client),name=await client.input.text({message:"Rule name:",default:pre?.name,validate:val=>val.trim()?val.length>160?"Name must be 160 characters or less.":!0:"Name is required."}),description=await client.input.text({message:"Description (optional, press Enter to skip):",default:pre?.description||""}),conditionGroups=await buildConditionGroupLoop(client,planInfo,pre?.conditionGroup),action=await buildActionInteractive(client,pre?.action),active=pre?.active!==void 0?pre.active:!0,previewRule={id:"(new)",name,description:description||void 0,active,conditionGroup:conditionGroups,action};if(output_manager_default.print(`
|
|
103
103
|
${formatRuleExpanded(previewRule)}
|
|
104
104
|
|
|
105
105
|
`),!await confirmAction(client,opts.skipPrompts??!1,"Create this rule?"))return output_manager_default.log("Canceled"),0;let createStamp=stamp_default();output_manager_default.spinner("Staging rule");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.insert",id:null,value:{name,description:description||void 0,active,conditionGroup:conditionGroups,action}}),output_manager_default.log(`${import_chalk23.default.cyan("Success!")} Rule "${import_chalk23.default.bold(name)}" staged ${import_chalk23.default.gray(createStamp())}`),printActionImpactWarning(action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:opts.skipPrompts}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);return priority!==null?priority:(output_manager_default.error(mapFirewallApiError(e,scope,"Failed to stage rule")),1)}}async function buildConditionGroupLoop(client,planInfo,prePopulated){let groups=prePopulated?JSON.parse(JSON.stringify(prePopulated)):[];if(groups.length===0){let condition=await buildConditionInteractive(client,planInfo);groups.push({conditions:[condition]})}for(;;){output_manager_default.print(`
|
|
@@ -120,13 +120,13 @@ ${import_chalk24.default.bold(" Current conditions:")}
|
|
|
120
120
|
|
|
121
121
|
`);let availableTypes=getAvailableConditionTypes(planInfo),type=await client.input.select({message:"Condition type:",choices:availableTypes.map(ct=>({value:ct.type,name:`${ct.displayName} ${import_chalk24.default.dim(ct.description)}`})),default:current.type}),meta=CONDITION_TYPES.find(ct=>ct.type===type),key;meta?.requiresKey&&(key=await client.input.text({message:`${meta.displayName} key:`,default:current.type===type?current.key:void 0,validate:val=>val.trim()?!0:"Key is required."}));let operatorChoices=(meta?.operators||["eq"]).flatMap(op2=>[{value:op2,name:getOperatorDisplayName(op2,!1)},{value:`!${op2}`,name:getOperatorDisplayName(op2,!0)}]),currentOpValue=current.type===type?current.neg?`!${current.op}`:current.op:void 0,opChoice=await client.input.select({message:"Operator:",choices:operatorChoices,default:currentOpValue}),neg=opChoice.startsWith("!"),op=neg?opChoice.slice(1):opChoice,value;if(op!=="ex"){let currentValue=current.type===type&¤t.op===op?current.value:void 0;if(op==="inc"&&meta?.presetValues){let currentArr=Array.isArray(currentValue)?currentValue:[];for(;;){let selected=await client.input.checkbox({message:"Select values:",choices:meta.presetValues.map(p=>({name:p.label,value:p.value,checked:currentArr.includes(p.value)})),pageSize:meta.presetValues.length});if(selected.length===0){output_manager_default.warn("Please select at least one value.");continue}value=selected;break}}else if(op==="inc"){let defaultVal=Array.isArray(currentValue)?currentValue.join(", "):"";value=(await client.input.text({message:"Values (comma-separated):",default:defaultVal,validate:val=>val.trim()?!0:"At least one value is required."})).split(",").map(v=>v.trim())}else if(op==="eq"&&meta?.presetValues)value=await client.input.select({message:"Value:",choices:meta.presetValues.map(p=>({name:p.label,value:p.value})),default:typeof currentValue=="string"?currentValue:void 0,pageSize:meta.presetValues.length});else{let defaultVal=typeof currentValue=="string"?currentValue:"";value=await client.input.text({message:"Value:",default:defaultVal,validate:val=>val.trim()?validateConditionValue(val,meta):"Value is required."})}}let condition={type,op};return neg&&(condition.neg=!0),key&&(condition.key=key),value!==void 0&&(condition.value=value),condition}async function buildCondition(client,planInfo){return buildConditionInteractive(client,planInfo)}async function editAction(client,current){let currentActionType=current.mitigate?.action,actionType=await client.input.select({message:"Action:",choices:VALID_ACTIONS.map(a=>({value:a,name:getActionLabel(a)})),default:currentActionType}),action={mitigate:{action:actionType,rateLimit:null,redirect:null,actionDuration:null}};if(actionType==="rate_limit"){let currentRL=current.mitigate?.rateLimit;output_manager_default.print(` ${import_chalk24.default.dim("Algorithm:")} Fixed Window ${import_chalk24.default.dim("(Token Bucket available on Enterprise via flags)")}
|
|
122
122
|
`);let windowStr=await client.input.text({message:"Window in seconds (10-3600):",default:String(currentRL?.window||60),validate:val=>{let n=Number(val);return Number.isNaN(n)||!Number.isInteger(n)?"Please enter a whole number.":n<10?"Minimum 10 seconds.":n>3600?"Maximum 3600 seconds (1 hour).":!0}}),limitStr=await client.input.text({message:"Max requests per window (1-10,000,000):",default:String(currentRL?.limit||100),validate:val=>{let n=Number(val);return Number.isNaN(n)||!Number.isInteger(n)?"Please enter a whole number.":n<1?"Minimum 1 request.":n>1e7?"Maximum 10,000,000 requests.":!0}}),currentKeys=currentRL?.keys||["ip"],keys=[...await client.input.checkbox({message:"Rate limit keys:",choices:[{name:"IP Address (ip)",value:"ip",checked:currentKeys.includes("ip")},{name:"JA4 Digest (ja4)",value:"ja4",checked:currentKeys.includes("ja4")},{name:"User Agent (header:user-agent)",value:"header:user-agent",checked:currentKeys.includes("header:user-agent")}],pageSize:3})],customKeys=currentKeys.filter(k=>!["ip","ja4","header:user-agent"].includes(k));customKeys.length>0&&(output_manager_default.print(` ${import_chalk24.default.dim("Custom keys preserved:")} ${customKeys.join(", ")}
|
|
123
|
-
`),keys=[...keys,...customKeys]),keys.length===0&&(keys=["ip"]);let subAction=await client.input.select({message:"Action when limit is exceeded:",choices:[{value:"deny",name:"Deny (403)"},{value:"challenge",name:"Challenge"},{value:"log",name:"Log only"},{value:"rate_limit",name:"Rate limit (429)"}],default:currentRL?.action||"deny"});action.mitigate.rateLimit={algo:currentRL?.algo||"fixed_window",window:Number(windowStr),limit:Number(limitStr),keys,action:subAction}}if(actionType==="redirect"){let currentRD=current.mitigate?.redirect,location=await client.input.text({message:"Redirect URL or path:",default:currentRD?.location||"",validate:val=>val.trim()?!val.startsWith("/")&&!val.startsWith("http://")&&!val.startsWith("https://")?"URL must start with /, http://, or https://":!0:"URL is required."}),permanent=await client.input.confirm("Permanent redirect (301)?",currentRD?.permanent??!1);action.mitigate.redirect={location,permanent}}if(["deny","challenge","rate_limit"].includes(actionType)){let currentDuration=current.mitigate?.actionDuration,durationChoice=await client.input.select({message:"Action duration:",choices:[{value:"none",name:"None (no persistent block)"},...VALID_DURATIONS.map(d=>({value:d,name:d}))],default:currentDuration||"none"});durationChoice!=="none"&&(action.mitigate.actionDuration=durationChoice)}return action}async function handleAIAdd(client,project,teamId,opts){let prompt=opts.prompt;if(!prompt){if(!client.stdin.isTTY||client.nonInteractive)return output_manager_default.error('--ai requires a description. Example: firewall rules add --ai "Rate limit /api to 100 requests per minute by IP"'),1;prompt=await client.input.text({message:"Describe the rule you want to create:",validate:val=>val.trim()?!0:"Please provide a description."})}let scope=projectScope(project,teamId,opts.teamSlug),currentRule,retryCount=0,maxRetries=client.nonInteractive?1:0;for(;;){output_manager_default.spinner("Generating rule with AI...");try{let response=await generateFirewallRule(client,project.id,{prompt,...currentRule?{currentRule}:{}},{teamId});if(response.error){if(output_manager_default.stopSpinner(),client.nonInteractive&&retryCount<maxRetries){retryCount++,output_manager_default.warn(`AI generation failed: ${response.error}. Retrying...`);continue}if(client.stdin.isTTY&&!client.nonInteractive&&!opts.skipPrompts){if(await client.input.select({message:`AI could not generate a rule: ${response.error}`,choices:[{value:"retry",name:"Try again with a different description"},{value:"cancel",name:"Cancel"}]})==="cancel")return output_manager_default.log("Canceled"),0;prompt=await client.input.text({message:"Describe the rule you want to create:",validate:val=>val.trim()?!0:"Please provide a description."});continue}return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ai_generation_failed",message:`AI could not generate a rule: ${response.error}`,next:[{command:withGlobalFlags(client,'firewall rules add --ai "more specific prompt" --yes'),when:"try with a more specific description"},{command:withGlobalFlags(client,`firewall rules add "Name" --condition '{"type":"path","op":"pre","value":"/api"}' --action deny --yes`),when:"create with
|
|
123
|
+
`),keys=[...keys,...customKeys]),keys.length===0&&(keys=["ip"]);let subAction=await client.input.select({message:"Action when limit is exceeded:",choices:[{value:"deny",name:"Deny (403)"},{value:"challenge",name:"Challenge"},{value:"log",name:"Log only"},{value:"rate_limit",name:"Rate limit (429)"}],default:currentRL?.action||"deny"});action.mitigate.rateLimit={algo:currentRL?.algo||"fixed_window",window:Number(windowStr),limit:Number(limitStr),keys,action:subAction}}if(actionType==="redirect"){let currentRD=current.mitigate?.redirect,location=await client.input.text({message:"Redirect URL or path:",default:currentRD?.location||"",validate:val=>val.trim()?!val.startsWith("/")&&!val.startsWith("http://")&&!val.startsWith("https://")?"URL must start with /, http://, or https://":!0:"URL is required."}),permanent=await client.input.confirm("Permanent redirect (301)?",currentRD?.permanent??!1);action.mitigate.redirect={location,permanent}}if(["deny","challenge","rate_limit"].includes(actionType)){let currentDuration=current.mitigate?.actionDuration,durationChoice=await client.input.select({message:"Action duration:",choices:[{value:"none",name:"None (no persistent block)"},...VALID_DURATIONS.map(d=>({value:d,name:d}))],default:currentDuration||"none"});durationChoice!=="none"&&(action.mitigate.actionDuration=durationChoice)}return action}async function handleAIAdd(client,project,teamId,opts){let prompt=opts.prompt;if(!prompt){if(!client.stdin.isTTY||client.nonInteractive)return output_manager_default.error('--ai requires a description. Example: firewall rules add --ai "Rate limit /api to 100 requests per minute by IP"'),1;prompt=await client.input.text({message:"Describe the rule you want to create:",validate:val=>val.trim()?!0:"Please provide a description."})}let scope=projectScope(project,teamId,opts.teamSlug),currentRule,retryCount=0,maxRetries=client.nonInteractive?1:0;for(;;){output_manager_default.spinner("Generating rule with AI...");try{let response=await generateFirewallRule(client,project.id,{prompt,...currentRule?{currentRule}:{}},{teamId});if(response.error){if(output_manager_default.stopSpinner(),client.nonInteractive&&retryCount<maxRetries){retryCount++,output_manager_default.warn(`AI generation failed: ${response.error}. Retrying...`);continue}if(client.stdin.isTTY&&!client.nonInteractive&&!opts.skipPrompts){if(await client.input.select({message:`AI could not generate a rule: ${response.error}`,choices:[{value:"retry",name:"Try again with a different description"},{value:"cancel",name:"Cancel"}]})==="cancel")return output_manager_default.log("Canceled"),0;prompt=await client.input.text({message:"Describe the rule you want to create:",validate:val=>val.trim()?!0:"Please provide a description."});continue}return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ai_generation_failed",message:`AI could not generate a rule: ${response.error}`,next:[{command:withGlobalFlags(client,'firewall rules add --ai "more specific prompt" --yes'),when:"try with a more specific description"},{command:withGlobalFlags(client,`firewall rules add "Name" --condition '{"type":"path","op":"pre","value":"/api"}' --action deny --yes`),when:"create with options instead"}]},1),output_manager_default.error(`AI could not generate a rule: ${response.error}`),1}if(!response.rule){if(output_manager_default.stopSpinner(),client.stdin.isTTY&&!client.nonInteractive&&!opts.skipPrompts){if(await client.input.select({message:"AI did not return a rule.",choices:[{value:"retry",name:"Try again with a different description"},{value:"cancel",name:"Cancel"}]})==="cancel")return output_manager_default.log("Canceled"),0;prompt=await client.input.text({message:"Describe the rule you want to create:",validate:val=>val.trim()?!0:"Please provide a description."});continue}return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ai_no_result",message:"AI did not return a rule. Try a more specific description.",next:[{command:withGlobalFlags(client,'firewall rules add --ai "more specific prompt" --yes'),when:"try with a more specific description"}]},1),output_manager_default.error("AI did not return a rule. Try a more specific description."),1}currentRule=response.rule,opts.name&&(currentRule.name=opts.name),output_manager_default.stopSpinner();break}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let msg=e.message||"Failed to generate rule";if(client.nonInteractive&&retryCount<maxRetries){retryCount++,output_manager_default.warn(`Generation failed: ${msg}. Retrying...`);continue}if(!client.stdin.isTTY||client.nonInteractive||opts.skipPrompts)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ai_generation_failed",message:msg,next:[{command:withGlobalFlags(client,'firewall rules add --ai "more specific prompt" --yes'),when:"try again"}]},1),output_manager_default.error(msg),1;if(await client.input.select({message:`Generation failed: ${msg}`,choices:[{value:"retry",name:"Try again"},{value:"cancel",name:"Cancel"}]})==="cancel")return output_manager_default.log("Canceled"),0}}let previewRule={...currentRule,id:"(AI-generated)"};if(output_manager_default.print(`
|
|
124
124
|
${formatRuleExpanded(previewRule)}
|
|
125
125
|
|
|
126
126
|
`),opts.skipPrompts)return createFromGenerated(client,scope,currentRule,opts);for(;;){let choice=await client.input.select({message:"What would you like to do?",choices:[{value:"create",name:"Create this rule"},{value:"edit-ai",name:"Edit with AI (describe changes)"},{value:"edit-manual",name:"Edit manually (step by step)"},{value:"discard",name:"Discard"}]});if(choice==="create")return createFromGenerated(client,scope,currentRule,opts);if(choice==="edit-ai"){let editPrompt=await client.input.text({message:"Describe the changes you want:",validate:val=>val.trim()?!0:"Please describe the changes."});output_manager_default.spinner("Regenerating rule...");try{let response=await generateFirewallRule(client,project.id,{prompt:editPrompt,currentRule},{teamId});if(output_manager_default.stopSpinner(),response.error||!response.rule){output_manager_default.error(`AI could not update the rule: ${response.error||"No rule returned"}`);continue}currentRule=response.rule;let updatedPreview={...currentRule,id:"(AI-generated)"};output_manager_default.print(`
|
|
127
127
|
${formatRuleExpanded(updatedPreview)}
|
|
128
128
|
|
|
129
|
-
`);continue}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let error=e;output_manager_default.error(`Failed to regenerate: ${error.message||"Unknown error"}`);continue}}if(choice==="edit-manual"){let prePopulated={...currentRule,id:"(new)"},modified=await runInteractiveEditLoop(client,prePopulated);if(!modified)continue;return createFromGenerated(client,scope,modified,opts)}if(choice==="discard")return output_manager_default.log("Discarded"),0}}async function createFromGenerated(client,scope,rule,opts){let createStamp=stamp_default();output_manager_default.spinner("Staging rule");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.insert",id:null,value:{name:rule.name,description:rule.description,active:rule.active!==!1,conditionGroup:rule.conditionGroup,action:rule.action}}),output_manager_default.log(`${import_chalk25.default.cyan("Success!")} Rule "${import_chalk25.default.bold(rule.name)}" staged ${import_chalk25.default.gray(createStamp())}`),printActionImpactWarning(rule.action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:opts.skipPrompts}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let msg=e.message||"Failed to stage rule";return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"staging_failed",message:msg,next:[{command:withGlobalFlags(client,"firewall rules add --yes"),when:"try again"}]},1),output_manager_default.error(msg),1}}async function add2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesAddSubcommand,client,"rules add");if(typeof parsed=="number")return parsed;let aiPrompt=parsed.flags["--ai"],jsonInput=getRulePayload(parsed.flags);if(typeof jsonInput=="number")return jsonInput;let conditionFlags=parsed.flags["--condition"];if([aiPrompt,jsonInput,conditionFlags].filter(Boolean).length>1)return output_manager_default.error("Cannot use --ai, --data, and --condition together. Use only one mode."),1;if(aiPrompt){if(parsed.flags["--team-level"])return output_manager_default.error("AI mode is not available with --team-level. Use --data or --condition
|
|
129
|
+
`);continue}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let error=e;output_manager_default.error(`Failed to regenerate: ${error.message||"Unknown error"}`);continue}}if(choice==="edit-manual"){let prePopulated={...currentRule,id:"(new)"},modified=await runInteractiveEditLoop(client,prePopulated);if(!modified)continue;return createFromGenerated(client,scope,modified,opts)}if(choice==="discard")return output_manager_default.log("Discarded"),0}}async function createFromGenerated(client,scope,rule,opts){let createStamp=stamp_default();output_manager_default.spinner("Staging rule");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.insert",id:null,value:{name:rule.name,description:rule.description,active:rule.active!==!1,conditionGroup:rule.conditionGroup,action:rule.action}}),output_manager_default.log(`${import_chalk25.default.cyan("Success!")} Rule "${import_chalk25.default.bold(rule.name)}" staged ${import_chalk25.default.gray(createStamp())}`),printActionImpactWarning(rule.action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:opts.skipPrompts}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let msg=e.message||"Failed to stage rule";return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"staging_failed",message:msg,next:[{command:withGlobalFlags(client,"firewall rules add --yes"),when:"try again"}]},1),output_manager_default.error(msg),1}}async function add2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesAddSubcommand,client,"rules add");if(typeof parsed=="number")return parsed;let aiPrompt=parsed.flags["--ai"],jsonInput=getRulePayload(parsed.flags);if(typeof jsonInput=="number")return jsonInput;let conditionFlags=parsed.flags["--condition"];if([aiPrompt,jsonInput,conditionFlags].filter(Boolean).length>1)return output_manager_default.error("Cannot use --ai, --data, and --condition together. Use only one mode."),1;if(aiPrompt){if(parsed.flags["--team-level"])return output_manager_default.error("AI mode is not available with --team-level. Use --data or --condition options instead."),1;if(client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ai_not_available",message:"AI mode is not available in non-interactive mode. AI-generated rules require human review before staging. Use --data or --condition options instead.",next:[{command:withGlobalFlags(client,`firewall rules add "Name" --condition '{"type":"path","op":"pre","value":"/api"}' --action deny --yes`),when:"create with options"},{command:withGlobalFlags(client,`firewall rules add --data '{"name":"...","conditionGroup":[...],"action":{...}}' --yes`),when:"create with JSON"}]}),output_manager_default.error("AI mode is not available in non-interactive mode. Use --data or --condition options instead."),1;let scope=await resolveFirewallScope(client,parsed.flags);return typeof scope=="number"?scope:scope.type==="team"?(output_manager_default.error("AI mode is not available with --team-level. Use --data or --condition options instead."),1):handleAIAdd(client,{id:scope.projectId,name:scope.displayName},scope.teamId,{prompt:aiPrompt,name:parsed.args[0],skipPrompts:!!parsed.flags["--yes"],teamSlug:scope.teamSlug})}if(jsonInput)return handleJsonAdd(client,parsed,jsonInput);if(conditionFlags)return handleFlagAdd(client,parsed,conditionFlags);if(client.stdin.isTTY&&!client.nonInteractive){let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let mode=await client.input.select({message:"How would you like to create the rule?",choices:[...scope.type==="project"?[{value:"ai",name:"Describe what you want (AI-powered)"}]:[],{value:"manual",name:"Build manually (step by step)"},{value:"json",name:"Paste JSON"}]});if(mode==="ai"&&scope.type==="project")return handleAIAdd(client,{id:scope.projectId,name:scope.displayName},scope.teamId,{skipPrompts:!1,teamSlug:scope.teamSlug});if(mode==="json"){let jsonStr=await client.input.text({message:"Paste the JSON rule definition:"});return handleJsonAdd(client,parsed,jsonStr)}return addInteractive(client,scope,{skipPrompts:!!parsed.flags["--yes"]})}return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_flags",message:"No rule definition provided. Use --data or --condition options.",next:[{command:withGlobalFlags(client,`firewall rules add "Name" --condition '{"type":"path","op":"pre","value":"/api"}' --action deny --yes`),when:"create with options"},{command:withGlobalFlags(client,`firewall rules add --data '{"name":"Name","conditionGroup":[...],"action":{"mitigate":{"action":"deny"}}}' --yes`),when:"create with JSON"}]}),output_manager_default.error("Interactive mode is not available. Use --ai, --data, or --condition options to create a rule."),2}async function handleJsonAdd(client,parsed,jsonStr){let ruleData;try{ruleData=JSON.parse(jsonStr)}catch{return output_manager_default.error("Invalid JSON. Please provide a valid JSON object."),2}if(!ruleData.name||typeof ruleData.name!="string")return output_manager_default.error('JSON must include a "name" field (string).'),1;if(!ruleData.conditionGroup||!Array.isArray(ruleData.conditionGroup))return output_manager_default.error('JSON must include a "conditionGroup" field (array).'),1;for(let i=0;i<ruleData.conditionGroup.length;i++){let group=ruleData.conditionGroup[i];if(!group.conditions||!Array.isArray(group.conditions))return output_manager_default.error(`conditionGroup[${i}] must have a "conditions" array.`),1;for(let j=0;j<group.conditions.length;j++){let cond=group.conditions[j];if(!cond.type||typeof cond.type!="string")return output_manager_default.error(`conditionGroup[${i}].conditions[${j}] must have a "type" field.`),1;if(!cond.op||typeof cond.op!="string")return output_manager_default.error(`conditionGroup[${i}].conditions[${j}] must have an "op" field.`),1}}if(!ruleData.action||typeof ruleData.action!="object")return output_manager_default.error('JSON must include an "action" field (object).'),1;let actionObj=ruleData.action;if(!actionObj.mitigate||typeof actionObj.mitigate!="object")return output_manager_default.error('action must have a "mitigate" field. Example: { "mitigate": { "action": "deny" } }'),1;let mitigateObj=actionObj.mitigate;if(!mitigateObj.action||typeof mitigateObj.action!="string")return output_manager_default.error('action.mitigate must have an "action" field (string). Valid: deny, challenge, rate_limit, log, redirect.'),1;if(ruleData.name.length>160)return output_manager_default.error("Rule name must be 160 characters or less."),1;if(ruleData.description&&ruleData.description.length>256)return output_manager_default.error("Rule description must be 256 characters or less."),1;if(ruleData.conditionGroup.length>25)return output_manager_default.error("Maximum 25 condition groups allowed."),1;let rule={name:ruleData.name,description:ruleData.description,active:ruleData.active!==!1,conditionGroup:ruleData.conditionGroup,action:ruleData.action};return createRule(client,parsed,rule)}async function handleFlagAdd(client,parsed,conditionFlags){let name=parsed.args[0];if(!name)return output_manager_default.error(`Missing rule name. Provide as the first argument: ${import_chalk26.default.cyan(withGlobalFlags(client,'firewall rules add "Rule name" --condition ...'))}`),1;if(name.length>160)return output_manager_default.error("Rule name must be 160 characters or less."),1;let rawArgs=parsed.flags["--condition"];if(!rawArgs||rawArgs.length===0)return output_manager_default.error("At least one --condition is required."),2;let hasOr=parsed.flags["--or"],conditionGroups;if(hasOr){let interleaved=[],condValues=[...rawArgs],condIdx=0;for(let arg of client.argv)arg==="--or"?interleaved.push("--or"):(arg==="--condition"||arg.startsWith("--condition="))&&condIdx<condValues.length&&(interleaved.push(condValues[condIdx]),condIdx++);let result=parseConditionFlags(interleaved);if(typeof result=="string")return output_manager_default.error(result),1;conditionGroups=result.groups}else{let result=parseConditionFlags(rawArgs);if(typeof result=="string")return output_manager_default.error(result),1;conditionGroups=result.groups}let actionType=parsed.flags["--action"];if(!actionType)return output_manager_default.error(`Missing --action. Valid actions: ${VALID_ACTIONS.join(", ")}`),1;if(!VALID_ACTIONS.includes(actionType))return output_manager_default.error(`Invalid action "${actionType}". Valid actions: ${VALID_ACTIONS.join(", ")}`),1;let action=buildActionFromFlags(parsed.flags,actionType);if(typeof action=="string")return output_manager_default.error(action),1;let description=parsed.flags["--description"];if(description&&description.length>256)return output_manager_default.error("Rule description must be 256 characters or less."),1;parsed.flags["--disabled"]&&warnDeprecatedInput(client,"--disabled","--no-enable");let active=!(parsed.flags["--no-enable"]||parsed.flags["--disabled"]);return createRule(client,parsed,{name,description,active,conditionGroup:conditionGroups,action})}async function createRule(client,parsed,rule){let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let reserved=refuseManagedBotMutation(client,scope,rule.name,"add a custom rule named");if(reserved!==null)return reserved;let previewRule={...rule,id:"(new)"};if(output_manager_default.print(`
|
|
130
130
|
${formatRuleExpanded(previewRule)}
|
|
131
131
|
|
|
132
132
|
`),!await confirmAction(client,parsed.flags["--yes"],"Create this rule?"))return output_manager_default.log("Canceled"),0;let createStamp=stamp_default();output_manager_default.spinner("Staging rule");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.insert",id:null,value:rule}),output_manager_default.log(`${import_chalk26.default.cyan("Success!")} Rule "${import_chalk26.default.bold(rule.name)}" staged ${import_chalk26.default.gray(createStamp())}`),printActionImpactWarning(rule.action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let msg=mapFirewallApiError(e,scope,"Failed to stage rule");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,"firewall rules add --yes",scope)}]}),1):(output_manager_default.error(msg),1)}}var import_chalk28=__toESM(require_source(),1);var import_chalk27=__toESM(require_source(),1);var UNSUPPORTED_FLAGS=["--ai","--data","--json","--condition","--name","--description","--duration","--enable","--no-enable","--enabled","--disabled","--rate-limit-algo","--rate-limit-window","--rate-limit-requests","--rate-limit-keys","--rate-limit-action","--redirect-url","--redirect-permanent","--or"];async function editManagedBotRule(client,opts){let used=UNSUPPORTED_FLAGS.filter(flag=>{let value=opts.flags[flag];return Array.isArray(value)?value.length>0:!!value});if(used.length>0){let command=`firewall rules update ${opts.id} --action <action>`;return failFirewall(client,{message:`Can't use ${used.join(", ")} on managed bot rules. Use --action.`,reason:AGENT_REASON.INVALID_ARGUMENTS,fix:{command,hint:`Use ${import_chalk27.default.cyan(withGlobalFlags(client,command,opts.scope))} to change it.`,when:"edit with --action"}})}let current=getManagedBotRule(opts.config,opts.id),rawAction=opts.flags["--action"],hasActionFlag=!!rawAction;if(!rawAction){if(client.nonInteractive||!client.stdin.isTTY){let command=`firewall rules update ${opts.id} --action <action>`;return failFirewall(client,{message:`Specify --action for ${current.name}. Run ${import_chalk27.default.cyan(withGlobalFlags(client,`firewall rules inspect ${opts.id}`,opts.scope))} to see the current value.`,reason:AGENT_REASON.MISSING_ARGUMENTS,fix:{command,hint:`Use ${import_chalk27.default.cyan(withGlobalFlags(client,command,opts.scope))}.`,when:"set --action"}})}output_manager_default.print(`
|
|
@@ -137,11 +137,11 @@ ${formatManagedBotRuleDetail({...current,action:parsedAction.action})}
|
|
|
137
137
|
|
|
138
138
|
`),!await confirmAction(client,opts.flags["--yes"],`Save ${current.name} \u2192 ${formatManagedBotAction(parsedAction.action)}?`,warning))return output_manager_default.log("Canceled"),0;let editStamp=stamp_default();output_manager_default.spinner("Staging changes");try{let hadExistingDraft=await detectExistingDraft(client,opts.scope);return await patchFirewallDraft(client,opts.scope,buildManagedBotPatch(opts.id,parsedAction.action)),output_manager_default.log(`${import_chalk27.default.cyan("Success!")} ${current.name} updated to ${import_chalk27.default.bold(formatManagedBotAction(parsedAction.action))} and staged ${import_chalk27.default.gray(editStamp())}`),opts.id==="bot-id"&&parsedAction.action==="deep-analysis"&&output_manager_default.print(`
|
|
139
139
|
${import_chalk27.default.dim("Install the BotID SDK in your app:")} ${import_chalk27.default.cyan("npm i botid")}
|
|
140
|
-
`),await offerAutoPublish(client,opts.scope,hadExistingDraft,{skipPrompts:opts.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,opts.scope);if(priority!==null)return priority;let command=`firewall rules update ${opts.id} --action ${parsedAction.action}`;return failFirewall(client,{message:mapFirewallApiError(e,opts.scope,"Failed to stage bot rule changes"),nextCommand:command,reason:AGENT_REASON.API_ERROR})}}async function edit(client,argv){let parsed=await parseSubcommandArgs(argv,rulesEditSubcommand,client,"rules update");if(typeof parsed=="number")return parsed;let identifier=parsed.args[0],scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching rules for ${import_chalk28.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),config=draft??active,currentRules=draft?.rules||active?.rules||[],managedRules=scope.type==="project"?getManagedBotRules(config):[];if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return output_manager_default.error(`Missing required argument: <name-or-id>. Run ${import_chalk28.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to see all rules.`),2;if(currentRules.length===0&&managedRules.length===0)return output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;let selectedId=await client.input.select({message:"Select a rule to update:",choices:[...managedRules.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatManagedBotAction(r.action)} (${r.id})`})),...currentRules.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))]}),selectedManaged=resolveManagedBotRuleId(selectedId);if(selectedManaged)return editManagedBotRule(client,{id:selectedManaged,flags:parsed.flags,scope,config});let selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.id}let managedId=scope.type==="project"?resolveManagedBotRuleId(identifier):void 0;if(managedId)return output_manager_default.stopSpinner(),editManagedBotRule(client,{id:managedId,flags:parsed.flags,scope,config});let matches=resolveRule(currentRules,identifier);if(matches.length===0)return output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk28.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let originalRule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] (${r.id})`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;originalRule=selected}output_manager_default.stopSpinner();let aiPrompt=parsed.flags["--ai"],jsonInput=getRulePayload(parsed.flags);if(typeof jsonInput=="number")return jsonInput;let conditionFlags=parsed.flags["--condition"];if([aiPrompt,jsonInput,conditionFlags].filter(Boolean).length>1)return output_manager_default.error("Cannot use --ai, --data, and --condition together. Use only one mode."),1;if(aiPrompt)return scope.type==="team"?(output_manager_default.error("AI mode is not available with --team-level. Use --data or
|
|
140
|
+
`),await offerAutoPublish(client,opts.scope,hadExistingDraft,{skipPrompts:opts.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,opts.scope);if(priority!==null)return priority;let command=`firewall rules update ${opts.id} --action ${parsedAction.action}`;return failFirewall(client,{message:mapFirewallApiError(e,opts.scope,"Failed to stage bot rule changes"),nextCommand:command,reason:AGENT_REASON.API_ERROR})}}async function edit(client,argv){let parsed=await parseSubcommandArgs(argv,rulesEditSubcommand,client,"rules update");if(typeof parsed=="number")return parsed;let identifier=parsed.args[0],scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;output_manager_default.spinner(`Fetching rules for ${import_chalk28.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),config=draft??active,currentRules=draft?.rules||active?.rules||[],managedRules=scope.type==="project"?getManagedBotRules(config):[];if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return output_manager_default.error(`Missing required argument: <name-or-id>. Run ${import_chalk28.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to see all rules.`),2;if(currentRules.length===0&&managedRules.length===0)return output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;let selectedId=await client.input.select({message:"Select a rule to update:",choices:[...managedRules.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatManagedBotAction(r.action)} (${r.id})`})),...currentRules.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))]}),selectedManaged=resolveManagedBotRuleId(selectedId);if(selectedManaged)return editManagedBotRule(client,{id:selectedManaged,flags:parsed.flags,scope,config});let selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.id}let managedId=scope.type==="project"?resolveManagedBotRuleId(identifier):void 0;if(managedId)return output_manager_default.stopSpinner(),editManagedBotRule(client,{id:managedId,flags:parsed.flags,scope,config});let matches=resolveRule(currentRules,identifier);if(matches.length===0)return output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk28.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let originalRule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] (${r.id})`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;originalRule=selected}output_manager_default.stopSpinner();let aiPrompt=parsed.flags["--ai"],jsonInput=getRulePayload(parsed.flags);if(typeof jsonInput=="number")return jsonInput;let conditionFlags=parsed.flags["--condition"];if([aiPrompt,jsonInput,conditionFlags].filter(Boolean).length>1)return output_manager_default.error("Cannot use --ai, --data, and --condition together. Use only one mode."),1;if(aiPrompt)return scope.type==="team"?(output_manager_default.error("AI mode is not available with --team-level. Use --data or option-based editing instead."),1):client.nonInteractive||!client.stdin.isTTY?(client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ai_not_available",message:"AI mode is not available in non-interactive mode. AI-generated changes require human review. Use --data or option-based editing instead.",next:[{command:withGlobalFlags(client,`firewall rules update "${identifier}" --action challenge --yes`),when:"edit with options"},{command:withGlobalFlags(client,`firewall rules update "${identifier}" --data '{"name":"...","conditionGroup":[...],"action":{...}}' --yes`),when:"edit with JSON"}]}),output_manager_default.error("AI mode is not available in non-interactive mode. Use --data or option-based editing instead."),1):handleAIEdit(client,{id:scope.projectId,name:scope.displayName},scope.teamId,originalRule,{prompt:aiPrompt,skipPrompts:!!parsed.flags["--yes"]});if(jsonInput)return handleJsonEdit(client,parsed,originalRule,jsonInput,scope);if(conditionFlags||parsed.flags["--action"]||parsed.flags["--name"]||parsed.flags["--description"]!==void 0||parsed.flags["--duration"]||parsed.flags["--enable"]||parsed.flags["--no-enable"]||parsed.flags["--enabled"]||parsed.flags["--disabled"]||parsed.flags["--rate-limit-algo"]||parsed.flags["--rate-limit-window"]||parsed.flags["--rate-limit-requests"]||parsed.flags["--rate-limit-keys"]||parsed.flags["--rate-limit-action"]||parsed.flags["--redirect-url"]||parsed.flags["--redirect-permanent"])return handleFlagEdit(client,parsed,originalRule,argv,scope);if(client.stdin.isTTY&&!client.nonInteractive){if(output_manager_default.print(`
|
|
141
141
|
${import_chalk28.default.bold("Current rule:")}
|
|
142
142
|
`),output_manager_default.print(`${formatRuleExpanded(originalRule)}
|
|
143
143
|
|
|
144
|
-
`),await client.input.select({message:"How would you like to update this rule?",choices:[...scope.type==="project"?[{value:"ai",name:"Describe changes (AI-powered)"}]:[],{value:"manual",name:"Edit manually (field by field)"}]})==="ai"&&scope.type==="project")return handleAIEdit(client,{id:scope.projectId,name:scope.displayName},scope.teamId,originalRule,{skipPrompts:!1});let modified=await runInteractiveEditLoop(client,originalRule);return modified?JSON.stringify(modified)===JSON.stringify(originalRule)?(output_manager_default.log("No changes detected."),0):saveEdit(client,scope,originalRule,modified,parsed,{skipConfirm:!0}):(output_manager_default.log("Canceled"),0)}return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_flags",message:"No edit
|
|
144
|
+
`),await client.input.select({message:"How would you like to update this rule?",choices:[...scope.type==="project"?[{value:"ai",name:"Describe changes (AI-powered)"}]:[],{value:"manual",name:"Edit manually (field by field)"}]})==="ai"&&scope.type==="project")return handleAIEdit(client,{id:scope.projectId,name:scope.displayName},scope.teamId,originalRule,{skipPrompts:!1});let modified=await runInteractiveEditLoop(client,originalRule);return modified?JSON.stringify(modified)===JSON.stringify(originalRule)?(output_manager_default.log("No changes detected."),0):saveEdit(client,scope,originalRule,modified,parsed,{skipConfirm:!0}):(output_manager_default.log("Canceled"),0)}return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_flags",message:"No edit options provided. Use --data, --condition, --action, --name, etc.",next:[{command:withGlobalFlags(client,`firewall rules update "${identifier}" --action challenge --yes`),when:"edit with options"},{command:withGlobalFlags(client,`firewall rules update "${identifier}" --data '{"name":"...","conditionGroup":[...],"action":{"mitigate":{"action":"deny"}}}' --yes`),when:"edit with JSON"}]}),output_manager_default.error("Interactive mode is not available. Use --data or option-based editing."),2}async function handleAIEdit(client,project,teamId,originalRule,opts){let prompt=opts.prompt;if(!prompt){if(!client.stdin.isTTY||client.nonInteractive)return output_manager_default.error("--ai requires a description."),1;prompt=await client.input.text({message:"Describe the changes you want:",validate:val=>val.trim()?!0:"Please describe the changes."})}let currentRule=JSON.parse(JSON.stringify(originalRule));for(;;){output_manager_default.spinner("Generating changes with AI...");try{let response=await generateFirewallRule(client,project.id,{prompt,currentRule},{teamId});if(output_manager_default.stopSpinner(),response.error){if(client.stdin.isTTY&&!client.nonInteractive&&!opts.skipPrompts){if(await client.input.select({message:`AI could not update the rule: ${response.error}`,choices:[{value:"retry",name:"Try again with a different description"},{value:"cancel",name:"Cancel"}]})==="cancel")return output_manager_default.log("Canceled"),0;prompt=await client.input.text({message:"Describe the changes you want:",validate:val=>val.trim()?!0:"Please describe the changes."});continue}return output_manager_default.error(`AI could not update the rule: ${response.error}`),1}if(!response.rule){if(client.stdin.isTTY&&!client.nonInteractive&&!opts.skipPrompts){if(await client.input.select({message:"AI did not return a rule.",choices:[{value:"retry",name:"Try again with a different description"},{value:"cancel",name:"Cancel"}]})==="cancel")return output_manager_default.log("Canceled"),0;prompt=await client.input.text({message:"Describe the changes you want:",validate:val=>val.trim()?!0:"Please describe the changes."});continue}return output_manager_default.error("AI did not return a rule."),1}currentRule={...response.rule,id:originalRule.id};break}catch(e){output_manager_default.stopSpinner();let error=e;if(!client.stdin.isTTY||client.nonInteractive)return output_manager_default.error(error.message||"Failed to generate changes"),1;if(await client.input.select({message:`Generation failed: ${error.message||"Unknown error"}`,choices:[{value:"retry",name:"Try again"},{value:"cancel",name:"Cancel"}]})==="cancel")return output_manager_default.log("Canceled"),0}}if(output_manager_default.print(`
|
|
145
145
|
${formatRuleExpanded(currentRule)}
|
|
146
146
|
|
|
147
147
|
`),opts.skipPrompts)return saveEdit(client,projectScope(project,teamId),originalRule,currentRule,{flags:{"--yes":!0}});for(;;){let choice;try{choice=await client.input.select({message:"What would you like to do?",choices:[{value:"save",name:"Save changes"},{value:"edit-ai",name:"Edit with AI (describe more changes)"},{value:"edit-manual",name:"Edit manually (field by field)"},{value:"discard",name:"Discard"}]})}catch{return 1}if(choice==="save")return saveEdit(client,projectScope(project,teamId),originalRule,currentRule,{flags:{}},{skipConfirm:!0});if(choice==="edit-ai"){prompt=await client.input.text({message:"Describe the changes you want:",validate:val=>val.trim()?!0:"Please describe the changes."}),output_manager_default.spinner("Regenerating...");try{let response=await generateFirewallRule(client,project.id,{prompt,currentRule},{teamId});if(output_manager_default.stopSpinner(),response.error||!response.rule){output_manager_default.error(`AI could not update the rule: ${response.error||"No rule returned"}`);continue}currentRule={...response.rule,id:originalRule.id},output_manager_default.print(`
|
|
@@ -153,11 +153,11 @@ ${formatRuleExpanded(currentRule)}
|
|
|
153
153
|
`);continue}if(choice==="discard")return output_manager_default.log("Discarded"),0}}async function handleJsonEdit(client,parsed,originalRule,jsonStr,scope){let ruleData;try{ruleData=JSON.parse(jsonStr)}catch{return output_manager_default.error("Invalid JSON. Please provide a valid JSON object."),2}if(!ruleData.name||typeof ruleData.name!="string")return output_manager_default.error('JSON must include a "name" field (string).'),1;if(!ruleData.conditionGroup||!Array.isArray(ruleData.conditionGroup))return output_manager_default.error('JSON must include a "conditionGroup" field (array).'),1;if(!ruleData.action||typeof ruleData.action!="object")return output_manager_default.error('JSON must include an "action" field (object).'),1;if(ruleData.name.length>160)return output_manager_default.error("Rule name must be 160 characters or less."),1;if(ruleData.description!==void 0&&ruleData.description!==null){if(typeof ruleData.description!="string")return output_manager_default.error('JSON "description" field must be a string.'),2;if(ruleData.description.length>256)return output_manager_default.error("Rule description must be 256 characters or less."),1}let actionObj=ruleData.action;if(!actionObj.mitigate||typeof actionObj.mitigate!="object")return output_manager_default.error('action must have a "mitigate" field. Example: { "mitigate": { "action": "deny" } }'),1;let mitigateObj=actionObj.mitigate;if(!mitigateObj.action||typeof mitigateObj.action!="string")return output_manager_default.error('action.mitigate must have an "action" field (string). Valid: deny, challenge, rate_limit, log, redirect.'),1;let modified={id:originalRule.id,name:ruleData.name,description:ruleData.description,active:ruleData.active!==void 0?ruleData.active!==!1:originalRule.active!==!1,conditionGroup:ruleData.conditionGroup,action:ruleData.action};return saveEdit(client,scope,originalRule,modified,parsed)}function extractConditionFlags(argv){let result=[],i=0;for(;i<argv.length;)argv[i]==="--or"?(result.push("--or"),i++):argv[i]==="--condition"&&i+1<argv.length?(result.push(argv[i+1]),i+=2):(argv[i].startsWith("--condition=")&&result.push(argv[i].slice(12)),i++);return result}async function handleFlagEdit(client,parsed,originalRule,rawArgv,scope){let modified=JSON.parse(JSON.stringify(originalRule)),newName=parsed.flags["--name"];if(newName){if(newName.length>160)return output_manager_default.error("Rule name must be 160 characters or less."),1;modified.name=newName}if(parsed.flags["--description"]!==void 0){let desc=parsed.flags["--description"];if(desc.length>256)return output_manager_default.error("Description must be 256 characters or less."),1;modified.description=desc===""?void 0:desc}let enable4=readOnOffOption(client,parsed.flags,{on:"--enable",off:"--no-enable",oldOn:"--enabled",oldOff:"--disabled"});if("error"in enable4)return output_manager_default.error(enable4.error),2;if(enable4.value!==void 0&&(modified.active=enable4.value),parsed.flags["--condition"]){let interleaved=extractConditionFlags(rawArgv);if(interleaved.length===0)return output_manager_default.error("At least one --condition is required."),2;let condResult=parseConditionFlags(interleaved);if(typeof condResult=="string")return output_manager_default.error(condResult),1;modified.conditionGroup=condResult.groups}let actionType=parsed.flags["--action"];if(actionType){if(!VALID_ACTIONS.includes(actionType))return output_manager_default.error(`Invalid action "${actionType}". Valid actions: ${VALID_ACTIONS.join(", ")}`),1;let actionResult=buildActionFromFlags(parsed.flags,actionType);if(typeof actionResult=="string")return output_manager_default.error(actionResult),1;modified.action=actionResult}else{let duration=parsed.flags["--duration"];if(duration){if(!VALID_DURATIONS.includes(duration))return output_manager_default.error(`Invalid duration "${duration}". Valid durations: ${VALID_DURATIONS.join(", ")}`),1;modified.action.mitigate&&(modified.action.mitigate.actionDuration=duration)}}return JSON.stringify(modified)===JSON.stringify(originalRule)?(output_manager_default.log("No changes detected."),0):saveEdit(client,scope,originalRule,modified,parsed)}async function saveEdit(client,scope,originalRule,modified,parsed,opts){if(!opts?.skipConfirm&&(output_manager_default.print(`
|
|
154
154
|
${formatRuleExpanded(modified)}
|
|
155
155
|
|
|
156
|
-
`),!await confirmAction(client,parsed.flags["--yes"],`Save changes to "${modified.name}"?`)))return output_manager_default.log("Canceled"),0;let editStamp=stamp_default();output_manager_default.spinner("Staging changes");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.update",id:originalRule.id,value:{name:modified.name,description:modified.description,active:modified.active,conditionGroup:modified.conditionGroup,action:modified.action}}),output_manager_default.log(`${import_chalk28.default.cyan("Success!")} Rule "${import_chalk28.default.bold(modified.name)}" updated and staged ${import_chalk28.default.gray(editStamp())}`),printActionImpactWarning(modified.action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let msg=mapFirewallApiError(e,scope,"Failed to stage rule changes");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall rules update "${originalRule.name}" --yes`,scope)}]}),1):(output_manager_default.error(msg),1)}}var import_chalk29=__toESM(require_source(),1);async function enable2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesEnableSubcommand,client,"rules enable");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"enable");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk29.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length===0)return output_manager_default.stopSpinner(),output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules enable <name-or-id>"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules enable <name-or-id>",scope)}`),2;let disabledRules=currentRules.filter(r=>r.active===!1);if(disabledRules.length===0)return output_manager_default.log("All rules are already enabled."),0;let selectedId=await client.input.select({message:"Select a rule to enable:",choices:disabledRules.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let allMatches=resolveRule(currentRules,identifier);if(allMatches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk29.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let matches=allMatches.filter(r=>r.active===!1);if(matches.length===0)return output_manager_default.stopSpinner(),allMatches.length===1?output_manager_default.log(`Rule "${allMatches[0].name}" is already enabled.`):output_manager_default.log("All matching rules are already enabled."),0;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules enable "${r.id}" --yes`,scope),when:`enable "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let enableStamp=stamp_default();output_manager_default.spinner("Staging changes");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.update",id:rule.id,value:{name:rule.name,description:rule.description,active:!0,conditionGroup:rule.conditionGroup,action:rule.action}}),output_manager_default.log(`${import_chalk29.default.cyan("Enabled")} rule "${import_chalk29.default.bold(rule.name)}" ${import_chalk29.default.gray(enableStamp())}`),printActionImpactWarning(rule.action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);return priority!==null?priority:(output_manager_default.error(mapFirewallApiError(e,scope,"Failed to enable rule")),1)}}var import_chalk30=__toESM(require_source(),1);async function disable2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesDisableSubcommand,client,"rules disable");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"disable");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk30.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length===0)return output_manager_default.stopSpinner(),output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules disable <name-or-id>"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules disable <name-or-id>",scope)}`),2;let enabledRules=currentRules.filter(r=>r.active!==!1);if(enabledRules.length===0)return output_manager_default.log("All rules are already disabled."),0;let selectedId=await client.input.select({message:"Select a rule to disable:",choices:enabledRules.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let allMatches=resolveRule(currentRules,identifier);if(allMatches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk30.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let matches=allMatches.filter(r=>r.active!==!1);if(matches.length===0)return output_manager_default.stopSpinner(),allMatches.length===1?output_manager_default.log(`Rule "${allMatches[0].name}" is already disabled.`):output_manager_default.log("All matching rules are already disabled."),0;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules disable "${r.id}" --yes`,scope),when:`disable "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let disableStamp=stamp_default();output_manager_default.spinner("Staging changes");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.update",id:rule.id,value:{name:rule.name,description:rule.description,active:!1,conditionGroup:rule.conditionGroup,action:rule.action}}),output_manager_default.log(`${import_chalk30.default.cyan("Disabled")} rule "${import_chalk30.default.bold(rule.name)}" ${import_chalk30.default.gray(disableStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityDisable(client,e,scope,rule);return priority!==null?priority:(output_manager_default.error(mapFirewallApiError(e,scope,"Failed to disable rule")),1)}}function failPriorityDisable(client,error,scope,rule){let serverMessage=apiServerMessage(error);if(!serverMessage||!mentionsPriorityProject(serverMessage))return null;let cached=scope.teamId?teamCache.get(scope.teamId):void 0,scopeArg=scope.type==="team"?scope.displayName:scope.teamSlug??cached?.slug??scope.teamId,scopeFlag=scopeArg?` --scope ${quoteArg(scopeArg)}`:"",command=`firewall rules remove ${quoteArg(rule.name)}${scopeFlag}`,message=`This rule cannot be disabled while ${scope.displayName} is not a Priority project. Remove it instead.`,nextCommand=withGlobalFlags(client,command,scope,{preserveProject:!0,excludeFlags:["--non-interactive","--yes","--scope","--team"]}),payload={status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message,userActionRequired:!0,hint:nextCommand,retryable:!1,...scopeArg?{scope:scopeArg}:{},next:[{command:nextCommand,when:"remove the rule instead of disabling it"}]};return shouldEmitNonInteractiveCommandError(client)&&outputAgentError(client,payload,1),output_manager_default.error(message),output_manager_default.log(nextCommand),1}var import_chalk31=__toESM(require_source(),1);async function remove2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesRemoveSubcommand,client,"rules remove");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"remove");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk31.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length===0)return output_manager_default.stopSpinner(),output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules remove <name-or-id> --yes"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules remove <name-or-id> --yes",scope)}`),2;let selectedId=await client.input.select({message:"Select a rule to remove:",choices:currentRules.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let matches=resolveRule(currentRules,identifier);if(matches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk31.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules remove "${r.id}" --yes`,scope),when:`remove "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let action=formatActionDisplay(rule.action),conditionCount=rule.conditionGroup.reduce((sum,g)=>sum+g.conditions.length,0);if(output_manager_default.log(`Rule: ${import_chalk31.default.bold(rule.name)} [${rule.active?"Enabled":"Disabled"}] \u2014 ${action} (${conditionCount} condition${conditionCount!==1?"s":""})`),!await confirmAction(client,parsed.flags["--yes"],`Remove rule "${rule.name}"?`))return output_manager_default.log("Canceled"),0;let removeStamp=stamp_default();output_manager_default.spinner("Staging removal");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.remove",id:rule.id,value:null}),output_manager_default.log(`${import_chalk31.default.cyan("Removed")} rule "${import_chalk31.default.bold(rule.name)}" ${import_chalk31.default.gray(removeStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){return output_manager_default.error(mapFirewallApiError(e,scope,"Failed to remove rule")),1}}var import_chalk32=__toESM(require_source(),1);async function reorder(client,argv){let parsed=await parseSubcommandArgs(argv,rulesReorderSubcommand,client,"rules move");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"move");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk32.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length<2)return output_manager_default.stopSpinner(),output_manager_default.error("Need at least 2 rules to move one."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules move <name-or-id> --first --yes"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules move <name-or-id> --position N --yes",scope)}`),2;let selectedId=await client.input.select({message:"Select a rule to move:",choices:currentRules.map((r,i)=>({value:r.id,name:`${i+1}. ${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let matches=resolveRule(currentRules,identifier);if(matches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk32.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules move "${r.id}" --first --yes`,scope),when:`move "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let currentIndex=currentRules.findIndex(r=>r.id===rule.id),flagFirst=parsed.flags["--first"],flagLast=parsed.flags["--last"],flagPosition=parsed.flags["--position"];if([flagFirst,flagLast,flagPosition].filter(Boolean).length>1)return output_manager_default.error("Cannot use --first, --last, and --position together. Use only one."),1;let targetIndex;if(flagFirst)targetIndex=0;else if(flagLast)targetIndex=currentRules.length-1;else if(flagPosition!==void 0){if(flagPosition<1)return output_manager_default.error("Position must be at least 1."),2;if(flagPosition>currentRules.length)return output_manager_default.error(`Position ${flagPosition} exceeds the number of rules (${currentRules.length}).`),1;targetIndex=flagPosition-1}else{if(client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"A position flag is required. Use --position N, --first, or --last.",next:[{command:withGlobalFlags(client,`firewall rules move "${rule.name}" --first --yes`,scope),when:"move to first position"},{command:withGlobalFlags(client,`firewall rules move "${rule.name}" --last --yes`,scope),when:"move to last position"}]},2),output_manager_default.error("A position flag is required. Use --position N, --first, or --last."),2;output_manager_default.print(`
|
|
156
|
+
`),!await confirmAction(client,parsed.flags["--yes"],`Save changes to "${modified.name}"?`)))return output_manager_default.log("Canceled"),0;let editStamp=stamp_default();output_manager_default.spinner("Staging changes");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.update",id:originalRule.id,value:{name:modified.name,description:modified.description,active:modified.active,conditionGroup:modified.conditionGroup,action:modified.action}}),output_manager_default.log(`${import_chalk28.default.cyan("Success!")} Rule "${import_chalk28.default.bold(modified.name)}" updated and staged ${import_chalk28.default.gray(editStamp())}`),printActionImpactWarning(modified.action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);if(priority!==null)return priority;let msg=mapFirewallApiError(e,scope,"Failed to stage rule changes");return client.nonInteractive?(outputAgentError(client,{status:"error",reason:"api_error",message:msg,next:[{command:withGlobalFlags(client,`firewall rules update "${originalRule.name}" --yes`,scope)}]}),1):(output_manager_default.error(msg),1)}}var import_chalk29=__toESM(require_source(),1);async function enable2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesEnableSubcommand,client,"rules enable");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"enable");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk29.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length===0)return output_manager_default.stopSpinner(),output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules enable <name-or-id>"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules enable <name-or-id>",scope)}`),2;let disabledRules=currentRules.filter(r=>r.active===!1);if(disabledRules.length===0)return output_manager_default.log("All rules are already enabled."),0;let selectedId=await client.input.select({message:"Select a rule to enable:",choices:disabledRules.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let allMatches=resolveRule(currentRules,identifier);if(allMatches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk29.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let matches=allMatches.filter(r=>r.active===!1);if(matches.length===0)return output_manager_default.stopSpinner(),allMatches.length===1?output_manager_default.log(`Rule "${allMatches[0].name}" is already enabled.`):output_manager_default.log("All matching rules are already enabled."),0;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules enable "${r.id}" --yes`,scope),when:`enable "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let enableStamp=stamp_default();output_manager_default.spinner("Staging changes");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.update",id:rule.id,value:{name:rule.name,description:rule.description,active:!0,conditionGroup:rule.conditionGroup,action:rule.action}}),output_manager_default.log(`${import_chalk29.default.cyan("Enabled")} rule "${import_chalk29.default.bold(rule.name)}" ${import_chalk29.default.gray(enableStamp())}`),printActionImpactWarning(rule.action),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityProjectGate(client,e,scope);return priority!==null?priority:(output_manager_default.error(mapFirewallApiError(e,scope,"Failed to enable rule")),1)}}var import_chalk30=__toESM(require_source(),1);async function disable2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesDisableSubcommand,client,"rules disable");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"disable");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk30.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length===0)return output_manager_default.stopSpinner(),output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules disable <name-or-id>"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules disable <name-or-id>",scope)}`),2;let enabledRules=currentRules.filter(r=>r.active!==!1);if(enabledRules.length===0)return output_manager_default.log("All rules are already disabled."),0;let selectedId=await client.input.select({message:"Select a rule to disable:",choices:enabledRules.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let allMatches=resolveRule(currentRules,identifier);if(allMatches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk30.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let matches=allMatches.filter(r=>r.active!==!1);if(matches.length===0)return output_manager_default.stopSpinner(),allMatches.length===1?output_manager_default.log(`Rule "${allMatches[0].name}" is already disabled.`):output_manager_default.log("All matching rules are already disabled."),0;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules disable "${r.id}" --yes`,scope),when:`disable "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let disableStamp=stamp_default();output_manager_default.spinner("Staging changes");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.update",id:rule.id,value:{name:rule.name,description:rule.description,active:!1,conditionGroup:rule.conditionGroup,action:rule.action}}),output_manager_default.log(`${import_chalk30.default.cyan("Disabled")} rule "${import_chalk30.default.bold(rule.name)}" ${import_chalk30.default.gray(disableStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){output_manager_default.stopSpinner();let priority=failPriorityDisable(client,e,scope,rule);return priority!==null?priority:(output_manager_default.error(mapFirewallApiError(e,scope,"Failed to disable rule")),1)}}function failPriorityDisable(client,error,scope,rule){let serverMessage=apiServerMessage(error);if(!serverMessage||!mentionsPriorityProject(serverMessage))return null;let cached=scope.teamId?teamCache.get(scope.teamId):void 0,scopeArg=scope.type==="team"?scope.displayName:scope.teamSlug??cached?.slug??scope.teamId,scopeFlag=scopeArg?` --scope ${quoteArg(scopeArg)}`:"",command=`firewall rules remove ${quoteArg(rule.name)}${scopeFlag}`,message=`This rule cannot be disabled while ${scope.displayName} is not a Priority project. Remove it instead.`,nextCommand=withGlobalFlags(client,command,scope,{preserveProject:!0,excludeFlags:["--non-interactive","--yes","--scope","--team"]}),payload={status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message,userActionRequired:!0,hint:nextCommand,retryable:!1,...scopeArg?{scope:scopeArg}:{},next:[{command:nextCommand,when:"remove the rule instead of disabling it"}]};return shouldEmitNonInteractiveCommandError(client)&&outputAgentError(client,payload,1),output_manager_default.error(message),output_manager_default.log(nextCommand),1}var import_chalk31=__toESM(require_source(),1);async function remove2(client,argv){let parsed=await parseSubcommandArgs(argv,rulesRemoveSubcommand,client,"rules remove");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"remove");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk31.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length===0)return output_manager_default.stopSpinner(),output_manager_default.error("No custom rules configured. Create one first with `vercel firewall rules add`."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules remove <name-or-id> --yes"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules remove <name-or-id> --yes",scope)}`),2;let selectedId=await client.input.select({message:"Select a rule to remove:",choices:currentRules.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let matches=resolveRule(currentRules,identifier);if(matches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk31.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules remove "${r.id}" --yes`,scope),when:`remove "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let action=formatActionDisplay(rule.action),conditionCount=rule.conditionGroup.reduce((sum,g)=>sum+g.conditions.length,0);if(output_manager_default.log(`Rule: ${import_chalk31.default.bold(rule.name)} [${rule.active?"Enabled":"Disabled"}] \u2014 ${action} (${conditionCount} condition${conditionCount!==1?"s":""})`),!await confirmAction(client,parsed.flags["--yes"],`Remove rule "${rule.name}"?`))return output_manager_default.log("Canceled"),0;let removeStamp=stamp_default();output_manager_default.spinner("Staging removal");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.remove",id:rule.id,value:null}),output_manager_default.log(`${import_chalk31.default.cyan("Removed")} rule "${import_chalk31.default.bold(rule.name)}" ${import_chalk31.default.gray(removeStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){return output_manager_default.error(mapFirewallApiError(e,scope,"Failed to remove rule")),1}}var import_chalk32=__toESM(require_source(),1);async function reorder(client,argv){let parsed=await parseSubcommandArgs(argv,rulesReorderSubcommand,client,"rules move");if(typeof parsed=="number")return parsed;let scope=await resolveFirewallScope(client,parsed.flags);if(typeof scope=="number")return scope;let identifier=parsed.args[0],reserved=refuseManagedBotMutation(client,scope,identifier,"move");if(reserved!==null)return reserved;output_manager_default.spinner(`Fetching rules for ${import_chalk32.default.bold(scope.displayName)}`);let{active,draft}=await listFirewallConfigs(client,scope),currentRules=draft?.rules||active?.rules||[];if(currentRules.length<2)return output_manager_default.stopSpinner(),output_manager_default.error("Need at least 2 rules to move one."),1;if(!identifier){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"Rule name or ID is required.",next:[{command:withGlobalFlags(client,"firewall rules move <name-or-id> --first --yes"),when:"replace <name-or-id>"},{command:withGlobalFlags(client,"firewall rules list",scope),when:"list rules"}]},2),output_manager_default.error(`Rule name or ID is required. Usage: ${withGlobalFlags(client,"firewall rules move <name-or-id> --position N --yes",scope)}`),2;let selectedId=await client.input.select({message:"Select a rule to move:",choices:currentRules.map((r,i)=>({value:r.id,name:`${i+1}. ${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=currentRules.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;identifier=selected.name}let matches=resolveRule(currentRules,identifier);if(matches.length===0)return output_manager_default.stopSpinner(),output_manager_default.error(`No rule found for "${identifier}". Run ${import_chalk32.default.cyan(withGlobalFlags(client,"firewall rules list",scope))} to view all rules.`),1;let rule=matches[0];if(matches.length>1){if(output_manager_default.stopSpinner(),client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"ambiguous_match",message:`Multiple rules match "${identifier}". Specify the full rule ID.`,next:matches.map(r=>({command:withGlobalFlags(client,`firewall rules move "${r.id}" --first --yes`,scope),when:`move "${r.name}"`}))}),output_manager_default.error(`Multiple rules match "${identifier}". Specify the full rule ID to disambiguate.`),1;let selectedId=await client.input.select({message:`Multiple rules match "${identifier}". Select one:`,choices:matches.map(r=>({value:r.id,name:`${r.name} [${r.active?"Enabled":"Disabled"}] \u2014 ${formatActionDisplay(r.action)}`}))}),selected=matches.find(r=>r.id===selectedId);if(!selected)return output_manager_default.error("No rule selected"),1;rule=selected}output_manager_default.stopSpinner();let currentIndex=currentRules.findIndex(r=>r.id===rule.id),flagFirst=parsed.flags["--first"],flagLast=parsed.flags["--last"],flagPosition=parsed.flags["--position"];if([flagFirst,flagLast,flagPosition].filter(Boolean).length>1)return output_manager_default.error("Cannot use --first, --last, and --position together. Use only one."),1;let targetIndex;if(flagFirst)targetIndex=0;else if(flagLast)targetIndex=currentRules.length-1;else if(flagPosition!==void 0){if(flagPosition<1)return output_manager_default.error("Position must be at least 1."),2;if(flagPosition>currentRules.length)return output_manager_default.error(`Position ${flagPosition} exceeds the number of rules (${currentRules.length}).`),1;targetIndex=flagPosition-1}else{if(client.nonInteractive||!client.stdin.isTTY)return client.nonInteractive&&outputAgentError(client,{status:"error",reason:"missing_arguments",message:"A position option is required. Use --position N, --first, or --last.",next:[{command:withGlobalFlags(client,`firewall rules move "${rule.name}" --first --yes`,scope),when:"move to first position"},{command:withGlobalFlags(client,`firewall rules move "${rule.name}" --last --yes`,scope),when:"move to last position"}]},2),output_manager_default.error("A position option is required. Use --position N, --first, or --last."),2;output_manager_default.print(`
|
|
157
157
|
Current rule order:
|
|
158
158
|
`);for(let i=0;i<currentRules.length;i++){let r=currentRules[i],marker=r.id===rule.id?"\u2192":" ";output_manager_default.print(` ${marker} ${i+1}. ${r.name} [${r.active?"Enabled":"Disabled"}]
|
|
159
159
|
`)}output_manager_default.print(`
|
|
160
|
-
`);let positionStr=await client.input.text({message:`Move "${rule.name}" to position (1-${currentRules.length}):`,validate:val=>{let num=Number(val);return Number.isNaN(num)||!Number.isInteger(num)?"Enter a number.":num<1||num>currentRules.length?`Position must be between 1 and ${currentRules.length}.`:!0}});targetIndex=Number(positionStr)-1}if(currentIndex===targetIndex)return output_manager_default.log(`Rule "${rule.name}" is already at position ${targetIndex+1}.`),0;if(!await confirmAction(client,parsed.flags["--yes"],`Move "${rule.name}" from position ${currentIndex+1} to position ${targetIndex+1}?`))return output_manager_default.log("Canceled"),0;let reorderStamp=stamp_default();output_manager_default.spinner("Staging move");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.priority",id:rule.id,value:targetIndex}),output_manager_default.log(`${import_chalk32.default.cyan("Moved")} rule "${import_chalk32.default.bold(rule.name)}" to position ${targetIndex+1} ${import_chalk32.default.gray(reorderStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){return output_manager_default.error(mapFirewallApiError(e,scope,"Failed to move rule")),1}}var COMMAND_CONFIG5={list:getCommandAliases(rulesListSubcommand),inspect:getCommandAliases(rulesInspectSubcommand),add:getCommandAliases(rulesAddSubcommand),update:getCommandAliases(rulesEditSubcommand),enable:getCommandAliases(rulesEnableSubcommand),disable:getCommandAliases(rulesDisableSubcommand),remove:getCommandAliases(rulesRemoveSubcommand),move:getCommandAliases(rulesReorderSubcommand)};async function main5(client,args,telemetry){let flagsSpecification=getFlagsSpecification(rulesSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG5),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","rules"),output_manager_default.print(help(rulesSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesListSubcommand),0):(telemetry.trackCliSubcommandRulesList(subcommandOriginal),list3(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesInspectSubcommand),0):(telemetry.trackCliSubcommandRulesInspect(subcommandOriginal),inspect(client,subArgs));case"add":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesAddSubcommand),0):(telemetry.trackCliSubcommandRulesAdd(subcommandOriginal),add2(client,subArgs));case"update":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesEditSubcommand),0):(telemetry.trackCliSubcommandRulesUpdate(subcommandOriginal),subcommandOriginal==="edit"&&warnDeprecatedSubcommand(client,"firewall rules edit","firewall rules update"),edit(client,subArgs));case"enable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesEnableSubcommand),0):(telemetry.trackCliSubcommandRulesEnable(subcommandOriginal),enable2(client,subArgs));case"disable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesDisableSubcommand),0):(telemetry.trackCliSubcommandRulesDisable(subcommandOriginal),disable2(client,subArgs));case"remove":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesRemoveSubcommand),0):(telemetry.trackCliSubcommandRulesRemove(subcommandOriginal),subcommandOriginal==="delete"&&warnDeprecatedSubcommand(client,"firewall rules delete","firewall rules remove"),remove2(client,subArgs));case"move":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesReorderSubcommand),0):(telemetry.trackCliSubcommandRulesMove(subcommandOriginal),subcommandOriginal==="reorder"&&warnDeprecatedSubcommand(client,"firewall rules reorder","firewall rules move"),reorder(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG5)),output_manager_default.print(help(rulesSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk34=__toESM(require_source(),1);var import_chalk33=__toESM(require_source(),1);function splitAlertSections(alerts){let active=[],resolved=[];for(let alert of alerts)alert.resolvedAt?resolved.push(alert):active.push(alert);return{active,resolved}}function alertRow(alert){return[alert.resolvedAt?import_chalk33.default.dim("Resolved"):import_chalk33.default.yellow("Active"),alert.title,alert.detail?colorizeDetail(alert.detail):"",alert.count!==void 0?formatCount(alert.count):"\u2014",`${formatUtcTime(alert.startedAt,!0)} UTC`,relativeTime(alert.startedAt),alert.id]}function formatAlertsList(opts){let lines=[],window=`${formatUtcTime(opts.from.getTime(),!0)} \u2013 ${formatUtcTime(opts.to.getTime(),!0)} UTC`;lines.push(` ${import_chalk33.default.bold("Firewall alerts")} ${import_chalk33.default.dim(`(${window})`)}`),lines.push("");let alerts=[...opts.active,...opts.resolved];if(alerts.length===0)return lines.push(import_chalk33.default.dim(" No alerts in this window.")),lines.push(""),lines.join(`
|
|
160
|
+
`);let positionStr=await client.input.text({message:`Move "${rule.name}" to position (1-${currentRules.length}):`,validate:val=>{let num=Number(val);return Number.isNaN(num)||!Number.isInteger(num)?"Enter a number.":num<1||num>currentRules.length?`Position must be between 1 and ${currentRules.length}.`:!0}});targetIndex=Number(positionStr)-1}if(currentIndex===targetIndex)return output_manager_default.log(`Rule "${rule.name}" is already at position ${targetIndex+1}.`),0;if(!await confirmAction(client,parsed.flags["--yes"],`Move "${rule.name}" from position ${currentIndex+1} to position ${targetIndex+1}?`))return output_manager_default.log("Canceled"),0;let reorderStamp=stamp_default();output_manager_default.spinner("Staging move");try{let hadExistingDraft=await detectExistingDraft(client,scope);return await patchFirewallDraft(client,scope,{action:"rules.priority",id:rule.id,value:targetIndex}),output_manager_default.log(`${import_chalk32.default.cyan("Moved")} rule "${import_chalk32.default.bold(rule.name)}" to position ${targetIndex+1} ${import_chalk32.default.gray(reorderStamp())}`),await offerAutoPublish(client,scope,hadExistingDraft,{skipPrompts:parsed.flags["--yes"]}),0}catch(e){return output_manager_default.error(mapFirewallApiError(e,scope,"Failed to move rule")),1}}var COMMAND_CONFIG5={list:getCommandAliases(rulesListSubcommand),inspect:getCommandAliases(rulesInspectSubcommand),add:getCommandAliases(rulesAddSubcommand),update:getCommandAliases(rulesEditSubcommand),enable:getCommandAliases(rulesEnableSubcommand),disable:getCommandAliases(rulesDisableSubcommand),remove:getCommandAliases(rulesRemoveSubcommand),move:getCommandAliases(rulesReorderSubcommand)};async function main5(client,args,telemetry){let flagsSpecification=getFlagsSpecification(rulesSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG5),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","rules"),output_manager_default.print(help(rulesSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesListSubcommand),0):(telemetry.trackCliSubcommandRulesList(subcommandOriginal),list3(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesInspectSubcommand),0):(telemetry.trackCliSubcommandRulesInspect(subcommandOriginal),inspect(client,subArgs));case"add":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesAddSubcommand),0):(telemetry.trackCliSubcommandRulesAdd(subcommandOriginal),add2(client,subArgs));case"update":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesEditSubcommand),0):(telemetry.trackCliSubcommandRulesUpdate(subcommandOriginal),subcommandOriginal==="edit"&&warnDeprecatedSubcommand(client,"firewall rules edit","firewall rules update"),edit(client,subArgs));case"enable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesEnableSubcommand),0):(telemetry.trackCliSubcommandRulesEnable(subcommandOriginal),enable2(client,subArgs));case"disable":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesDisableSubcommand),0):(telemetry.trackCliSubcommandRulesDisable(subcommandOriginal),disable2(client,subArgs));case"remove":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesRemoveSubcommand),0):(telemetry.trackCliSubcommandRulesRemove(subcommandOriginal),subcommandOriginal==="delete"&&warnDeprecatedSubcommand(client,"firewall rules delete","firewall rules remove"),remove2(client,subArgs));case"move":return needHelp?(telemetry.trackCliFlagHelp("firewall",`rules:${subcommandOriginal}`),printHelp(rulesReorderSubcommand),0):(telemetry.trackCliSubcommandRulesMove(subcommandOriginal),subcommandOriginal==="reorder"&&warnDeprecatedSubcommand(client,"firewall rules reorder","firewall rules move"),reorder(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG5)),output_manager_default.print(help(rulesSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk34=__toESM(require_source(),1);var import_chalk33=__toESM(require_source(),1);function splitAlertSections(alerts){let active=[],resolved=[];for(let alert of alerts)alert.resolvedAt?resolved.push(alert):active.push(alert);return{active,resolved}}function alertRow(alert){return[alert.resolvedAt?import_chalk33.default.dim("Resolved"):import_chalk33.default.yellow("Active"),alert.title,alert.detail?colorizeDetail(alert.detail):"",alert.count!==void 0?formatCount(alert.count):"\u2014",`${formatUtcTime(alert.startedAt,!0)} UTC`,relativeTime(alert.startedAt),alert.id]}function formatAlertsList(opts){let lines=[],window=`${formatUtcTime(opts.from.getTime(),!0)} \u2013 ${formatUtcTime(opts.to.getTime(),!0)} UTC`;lines.push(` ${import_chalk33.default.bold("Firewall alerts")} ${import_chalk33.default.dim(`(${window})`)}`),lines.push("");let alerts=[...opts.active,...opts.resolved];if(alerts.length===0)return lines.push(import_chalk33.default.dim(" No alerts in this window.")),lines.push(""),lines.join(`
|
|
161
161
|
`);let header=["Status","Alert","Detail","Requests","Started","Age","Id"].map(h=>import_chalk33.default.bold(import_chalk33.default.cyan(h))),rendered=table([header,...alerts.map(alertRow)],{align:["l","l","l","r","l","r","l"],hsep:3});for(let line2 of rendered.split(`
|
|
162
162
|
`))lines.push(` ${line2}`.trimEnd());return lines.push(""),lines.join(`
|
|
163
163
|
`)}function formatNamedCounts(rows){let nameWidth=Math.max(...rows.map(r=>r.name.length),0),countWidth=Math.max(...rows.map(r=>formatCount(r.count).length),0);return rows.map(row=>` ${row.name.padEnd(nameWidth)} ${formatCount(row.count).padStart(countWidth)}`).join(`
|
|
@@ -171,7 +171,7 @@ ${formatAlertInspect({alert,rates,timeseries,ips,hosts})}`),!metrics)output_mana
|
|
|
171
171
|
`);else if(eventsIssue?.reason==="plan")output_manager_default.print(` ${FIREWALL_ACTIVITY_PLAN_MESSAGE}
|
|
172
172
|
`);else if(eventsIssue){let haveHosts=!!(hosts&&hosts.length>0);output_manager_default.print(` Couldn't load denied IPs${haveHosts?"":" and hosts"}.
|
|
173
173
|
`)}return output_manager_default.print(`
|
|
174
|
-
`),0}catch(e){return isActivityUnavailable2(e)?failFirewallObservabilityPlan(client,e,project.name):failFirewallApi(client,e,{fallback:"Failed to fetch firewall alert",nextCommand:suggestedCommand,permissionAction:"read firewall alerts",projectName:project.name,timeoutJob:"firewall alert"})}}var COMMAND_CONFIG6={list:getCommandAliases(alertsListSubcommand),inspect:getCommandAliases(alertsInspectSubcommand)};async function main6(client,args,telemetry){let flagsSpecification=getFlagsSpecification(alertsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG6),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","alerts"),output_manager_default.print(help(alertsSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`alerts:${subcommandOriginal}`),printHelp(alertsListSubcommand),0):(telemetry.trackCliSubcommandAlertsList(subcommandOriginal),list4(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`alerts:${subcommandOriginal}`),printHelp(alertsInspectSubcommand),0):(telemetry.trackCliSubcommandAlertsInspect(subcommandOriginal),inspect2(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG6)),output_manager_default.print(help(alertsSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk37=__toESM(require_source(),1);var import_chalk36=__toESM(require_source(),1);var DEFAULT_PERSISTENT_ACTION_LIMIT=10,DEFAULT_PERSISTENT_ACTION_WINDOW_MS=60*60*1e3;function persistentActionWindow(since,until){let to=until??new Date;return{from:since??new Date(to.getTime()-DEFAULT_PERSISTENT_ACTION_WINDOW_MS),to}}function formatPersistentActionWindowLabel(from,to){let hours=(to.getTime()-from.getTime())/36e5,untilIsNow=Date.now()-to.getTime()<6e4;return untilIsNow&&hours>.9&&hours<1.1?"past 1h, UTC":untilIsNow&&Number.isInteger(hours)&&hours>=1&&hours<=48?`past ${hours}h, UTC`:`${formatUtcTime(from.getTime(),!0)} \u2013 ${formatUtcTime(to.getTime(),!0)} UTC`}function actionMs(value){return apiTimestampMs(value)}function formatEnd(action){return action.isActive?import_chalk36.default.blue("Ongoing"):`${formatUtcTime(actionMs(action.endTime),!0)} UTC`}function colorAction(action){return(ACTION_COLORS[action]??(s=>s))(labelForAction(action))}function pluralize(count,singular){return count===1?singular:`${singular}s`}function formatNamedCounts2(rows){let nameWidth=Math.max(...rows.map(r=>r.name.length),0),countWidth=Math.max(...rows.map(r=>formatCount(r.count).length),0);return rows.map(row=>` ${row.name.padEnd(nameWidth)} ${formatCount(row.count).padStart(countWidth)}`).join(`
|
|
174
|
+
`),0}catch(e){return isActivityUnavailable2(e)?failFirewallObservabilityPlan(client,e,project.name):failFirewallApi(client,e,{fallback:"Failed to fetch firewall alert",nextCommand:suggestedCommand,permissionAction:"read firewall alerts",projectName:project.name,timeoutJob:"firewall alert"})}}var COMMAND_CONFIG6={list:getCommandAliases(alertsListSubcommand),inspect:getCommandAliases(alertsInspectSubcommand)};async function main6(client,args,telemetry){let flagsSpecification=getFlagsSpecification(alertsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG6),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","alerts"),output_manager_default.print(help(alertsSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`alerts:${subcommandOriginal}`),printHelp(alertsListSubcommand),0):(telemetry.trackCliSubcommandAlertsList(subcommandOriginal),list4(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`alerts:${subcommandOriginal}`),printHelp(alertsInspectSubcommand),0):(telemetry.trackCliSubcommandAlertsInspect(subcommandOriginal),inspect2(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG6)),output_manager_default.print(help(alertsSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk37=__toESM(require_source(),1);var import_chalk36=__toESM(require_source(),1);var DEFAULT_PERSISTENT_ACTION_LIMIT=10,DEFAULT_PERSISTENT_ACTION_WINDOW_MS=60*60*1e3;function persistentActionWindow(since,until){let to=until??new Date;return{from:since??new Date(to.getTime()-DEFAULT_PERSISTENT_ACTION_WINDOW_MS),to}}function formatPersistentActionWindowLabel(from,to){let hours=(to.getTime()-from.getTime())/36e5,untilIsNow=Date.now()-to.getTime()<6e4;return untilIsNow&&hours>.9&&hours<1.1?"past 1h, UTC":untilIsNow&&Number.isInteger(hours)&&hours>=1&&hours<=48?`past ${hours}h, UTC`:`${formatUtcTime(from.getTime(),!0)} \u2013 ${formatUtcTime(to.getTime(),!0)} UTC`}function actionMs(value){return apiTimestampMs(value)}function formatEnd(action){return action.isActive?import_chalk36.default.blue("Ongoing"):`${formatUtcTime(actionMs(action.endTime),!0)} UTC`}function colorAction(action){return(ACTION_COLORS[action]??(s=>s))(labelForAction(action))}function pluralize(count,singular){return count===1?singular:`${singular}s`}function formatNamedCounts2(rows){let nameWidth=Math.max(...rows.map(r=>r.name.length),0),countWidth=Math.max(...rows.map(r=>formatCount(r.count).length),0);return rows.map(row=>` ${row.name.padEnd(nameWidth)} ${formatCount(row.count).padStart(countWidth)}`).join(`
|
|
175
175
|
`)}function formatPersistentActionsList(opts){let lines=[` ${import_chalk36.default.bold("Persistent actions")} (${formatPersistentActionWindowLabel(opts.from,opts.to)})`],summary=opts.summary;if(summary){let parts=[summary.challengingIps>0?`Challenging ${summary.challengingIps} ${pluralize(summary.challengingIps,"IP")}`:null,summary.blockingIps>0?`Blocking ${summary.blockingIps} ${pluralize(summary.blockingIps,"IP")}`:null,summary.otherActions>0?`${summary.otherActions} other ${pluralize(summary.otherActions,"action")}`:null,summary.withheldActions>0?`${summary.withheldActions} on hidden ${pluralize(summary.withheldActions,"IP")}`:null].filter(part=>!!part);lines.push(` ${parts.join(" \xB7 ")} ${import_chalk36.default.dim(`\xB7 ${summary.activeTotal} currently applied`)}`)}if(lines.push(""),opts.actions.length===0)return lines.push(import_chalk36.default.dim(" No persistent actions in this window.")),lines.push(""),lines.join(`
|
|
176
176
|
`);let rows=[["Type","Action","Hostname","IP Address","Start","End","Requests"].map(h=>import_chalk36.default.bold(import_chalk36.default.cyan(h)))];for(let action of opts.actions)rows.push([ruleTypeLabel(action.action_type),colorAction(action.action),action.host,action.public_ip,`${formatUtcTime(actionMs(action.startTime),!0)} UTC`,formatEnd(action),formatCount(action.count)]);let rendered=table(rows,{align:["l","l","l","l","l","l","r"],hsep:3});for(let line2 of rendered.split(`
|
|
177
177
|
`))lines.push(` ${line2}`.trimEnd());return opts.actions.some(action=>isRedacted(action.public_ip)||isRedacted(action.host)||isRedacted(action.action_type))&&(lines.push(""),lines.push(import_chalk36.default.dim(" *** marks detail this plan withholds for actions older than an hour."))),opts.actions.length<opts.total&&(lines.push(""),lines.push(` Showing ${opts.actions.length} of ${opts.total}. Raise --limit, or narrow with --since and --until.`)),lines.push(""),lines.join(`
|
|
@@ -181,7 +181,7 @@ ${formatPersistentActionsList({actions:shown,total:actions.length,summary,from,t
|
|
|
181
181
|
`),0)}catch(e){return isAPIError(e)&&e.status===402?failFirewallObservabilityPlan(client,e,project.name):failFirewallApi(client,e,{fallback:"Failed to fetch persistent firewall actions",nextCommand:suggestedCommand,permissionAction:"read firewall persistent actions",projectName:project.name,timeoutJob:"firewall persistent actions"})}}var import_chalk38=__toESM(require_source(),1);import{isIP as isIP3}from"node:net";var TOP_PATHS=8,MIN_TRAFFIC_WINDOW_MS=6e4;function isActivityUnavailable3(error){return isAPIError(error)&&error.status===402}function inspectGranularity(from,to){let hours=(to.getTime()-from.getTime())/36e5;return hours<=3?{minutes:1}:hours<=24?{minutes:5}:{hours:1}}function matchesInspectFilters(action,opts){return!(action.public_ip!==opts.ip||opts.host&&action.host!==opts.host||opts.action&&action.action!==opts.action)}async function inspect3(client,argv){let startedAt=Date.now(),parsed=await parseSubcommandArgs(argv,persistentActionsInspectSubcommand,client,"persistent-actions inspect");if(typeof parsed=="number")return parsed;let ip=parsed.args[0];if(!ip)return failFirewall(client,{message:`IP is required. Usage: ${withGlobalFlags(client,"firewall persistent-actions inspect <ip>")}`,nextCommand:"firewall persistent-actions inspect <ip>",reason:AGENT_REASON.MISSING_ARGUMENTS});if(!isIP3(ip))return failFirewall(client,{message:"Please enter a valid IP address.",reason:AGENT_REASON.INVALID_ARGUMENTS});let sinceResult=validateTimeBound(parsed.flags["--since"]);if(!sinceResult.valid)return failFirewall(client,{message:sinceResult.message,reason:AGENT_REASON.INVALID_ARGUMENTS});let untilResult=validateTimeBound(parsed.flags["--until"]);if(!untilResult.valid)return failFirewall(client,{message:untilResult.message,reason:AGENT_REASON.INVALID_ARGUMENTS});let order=validateTimeOrder(sinceResult.value,untilResult.value);if(!order.valid)return failFirewall(client,{message:order.message,reason:AGENT_REASON.INVALID_ARGUMENTS});let requested=persistentActionWindow(sinceResult.value,untilResult.value),host=parsed.flags["--host"],actionFilter=parsed.flags["--action"],link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;if(!teamId)return failFirewall(client,{message:"Firewall persistent actions need a team. Run `vercel switch` to select a team or pass --scope <team>.",reason:AGENT_REASON.MISSING_SCOPE});let asJson=!!parsed.flags["--json"],suggestedCommand=`firewall persistent-actions inspect ${ip}${asJson?" --json":""}`,{isEnterprise,known}=await fetchPlanInfo(client),window=clampPersistentActionWindow({...requested,isEnterprise,planKnown:known,now:startedAt}),{from,to}=window;if(window.empty)return failFirewall(client,{message:`This plan keeps ${retentionLabel(isEnterprise)} of persistent-action history, and the requested window is entirely older than that. Narrow it with --since and --until.`,reason:AGENT_REASON.INVALID_ARGUMENTS});output_manager_default.spinner(`Fetching persistent action ${import_chalk38.default.bold(ip)}`);try{let matches=(await fetchFirewallPersistentActions(client,{projectId:project.id,teamId,startTime:from,endTime:to,host})).filter(action=>matchesInspectFilters(action,{ip,host,action:actionFilter})),selected=matches[0];if(!selected)return failFirewall(client,{message:`No persistent action found for "${ip}". Run ${withGlobalFlags(client,"firewall persistent-actions list")} to view recent actions.`,nextCommand:"firewall persistent-actions list",reason:AGENT_REASON.NOT_FOUND});output_manager_default.spinner(`Fetching traffic for ${import_chalk38.default.bold(ip)}`);let requestedStart=new Date(apiTimestampMs(selected.startTime)),requestedEnd=new Date(Math.max(Math.min(apiTimestampMs(selected.endTime),Date.now()),requestedStart.getTime()+MIN_TRAFFIC_WINDOW_MS)),wantPaths=!!parsed.flags["--paths"],filter=persistentActionFilter({ip:selected.public_ip,host:selected.host}),pathsFilter=persistentActionFilter({ip:selected.public_ip,host:selected.host,withPath:!0}),scopable=!isRedacted(selected.public_ip),granularity=inspectGranularity(requestedStart,requestedEnd),{startTime:actionStart,endTime:actionEnd}=alignQueryWindow(requestedStart,requestedEnd,granularity),[metrics,paths]=await Promise.all([scopable?getFirewallMetrics(client,{projectId:project.id,ownerId:teamId,startTime:actionStart,endTime:actionEnd,granularity,filter}).catch(err=>{if(isActivityUnavailable3(err))return null;throw err}):Promise.resolve(null),wantPaths&&scopable?getTopList(client,{projectId:project.id,ownerId:teamId,startTime:actionStart,endTime:actionEnd,groupBy:[PATH_DIMENSION],filter:pathsFilter,top:TOP_PATHS}).catch(err=>{if(isActivityUnavailable3(err))return null;throw err}):Promise.resolve(null)]),pathRows=paths?.map(row=>({name:row.values[PATH_DIMENSION]||"/",count:row.total}));return asJson?(outputJson(client,{action:toPersistentAction(selected),matchCount:matches.length,series:metrics?.series??null,...wantPaths?{paths:pathRows??null}:{},...metrics?{}:{activityUnavailable:{reason:"plan",message:FIREWALL_ACTIVITY_PLAN_MESSAGE}}}),0):(output_manager_default.print(`
|
|
182
182
|
${formatPersistentActionInspect({action:selected,matchCount:matches.length,series:metrics?.series,paths:pathRows,pathsAvailable:!wantPaths})}`),metrics||output_manager_default.print(` ${FIREWALL_ACTIVITY_PLAN_MESSAGE}
|
|
183
183
|
`),output_manager_default.print(`
|
|
184
|
-
`),0)}catch(e){return isActivityUnavailable3(e)?failFirewallObservabilityPlan(client,e,project.name):failFirewallApi(client,e,{fallback:"Failed to fetch persistent firewall action",nextCommand:suggestedCommand,permissionAction:"read firewall persistent actions",projectName:project.name,timeoutJob:"firewall persistent action"})}}var COMMAND_CONFIG7={list:getCommandAliases(persistentActionsListSubcommand),inspect:getCommandAliases(persistentActionsInspectSubcommand)};async function main7(client,args,telemetry){let flagsSpecification=getFlagsSpecification(persistentActionsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG7),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","persistent-actions"),output_manager_default.print(help(persistentActionsSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`persistent-actions:${subcommandOriginal}`),printHelp(persistentActionsListSubcommand),0):(telemetry.trackCliSubcommandPersistentActionsList(subcommandOriginal),list5(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`persistent-actions:${subcommandOriginal}`),printHelp(persistentActionsInspectSubcommand),0):(telemetry.trackCliSubcommandPersistentActionsInspect(subcommandOriginal),inspect3(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG7)),output_manager_default.print(help(persistentActionsSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk39=__toESM(require_source(),1);var DEFAULT_TRAFFIC_WINDOW_MS=24*60*60*1e3;function requireTrafficTeam(client,org,what){return org.type==="team"?org.id:failFirewall(client,{message:`${what} needs a team. Run \`vercel switch\` to select a team or pass --scope <team>.`,reason:AGENT_REASON.MISSING_SCOPE})}function resolveTrafficWindow(since,until,scope){let sinceResult=validateTimeBound(since);if(!sinceResult.valid)return{valid:!1,message:sinceResult.message};let untilResult=validateTimeBound(until);if(!untilResult.valid)return{valid:!1,message:untilResult.message};let order=validateTimeOrder(sinceResult.value,untilResult.value);if(!order.valid)return{valid:!1,message:order.message};if(!sinceResult.value&&!untilResult.value&&scope)return{valid:!0,startTime:scope.startTime,endTime:scope.endTime};let endTime=untilResult.value??new Date,startTime=sinceResult.value??scope?.startTime??new Date(endTime.getTime()-DEFAULT_TRAFFIC_WINDOW_MS);return startTime.getTime()>endTime.getTime()?{valid:!1,message:sinceResult.value?"`--since` is in the future. Pass a past time, such as `24h` or an earlier date.":"The alert began after `--until`. Widen the window with `--since`, or drop `--until`."}:{valid:!0,startTime,endTime}}function buildTrafficFilter(flags){let parts=[];for(let dimension of TRAFFIC_DIMENSIONS){let value=flags[`--${dimension.alias}`];typeof value=="string"&&value.length>0&&parts.push(eqFilter(dimension.field,value))}let raw=flags["--query"],rawExpressions=[];if(Array.isArray(raw))for(let expression of raw)typeof expression=="string"&&expression.length>0&&(rawExpressions.push(expression),parts.push(expression));return usesODataSyntax(rawExpressions)&&output_manager_default.warn(FILTER_DEPRECATION_WARNING),andFilters(...parts)}function unknownDimensionMessage(flag,value){return`Unknown ${flag} "${value}". Dimensions: ${dimensionAliases().join(", ")}.`}var WAF_ONLY_ALIASES=new Set(["action","rule"]);function hasStringFlag(flags,flag){let value=flags[flag];return typeof value=="string"&&value.length>0}function requestCountFilterFlags(flags){return TRAFFIC_DIMENSIONS.filter(d=>d.metric&&hasStringFlag(flags,`--${d.alias}`)).map(d=>`--${d.alias}`)}function mixedTrafficMetricError(opts){let requestFilters=requestCountFilterFlags(opts.flags),queryingRequestCount=!!opts.dimension?.metric;if(!queryingRequestCount&&requestFilters.length>0)return`Can't combine ${requestFilters.join(", ")} with firewall-action data. Inspect unknown-bot <category> instead.`;if(!queryingRequestCount||!opts.dimension)return;let unsupported=[];if(hasStringFlag(opts.flags,"--action")&&unsupported.push("--action"),hasStringFlag(opts.flags,"--rule")&&unsupported.push("--rule"),opts.groupBy&&WAF_ONLY_ALIASES.has(opts.groupBy.alias)&&unsupported.push(`--group-by ${opts.groupBy.alias}`),unsupported.length!==0)return`${opts.dimension.label} uses request-count data and cannot be combined with ${unsupported.join(", ")}. Use a request dimension such as path, ip, host, country, asn, ja4, or user-agent instead.`}var TOP_LIMITS={min:1,max:100};function trendBuckets(client){let columns=client.stderr.columns||80;return Math.max(12,Math.min(96,columns-56))}async function runWithConcurrency(tasks,limit){let results=new Array(tasks.length),next=0,workers=Array.from({length:Math.min(limit,tasks.length)},async()=>{for(;next<tasks.length;){let index=next++;results[index]=await tasks[index]()}});return await Promise.all(workers),results}var AlertNotFoundError=class extends Error{constructor(alertId){super(`No firewall alert found for "${alertId}". Run \`vercel firewall alerts list\` to view recent alerts.`),this.name="AlertNotFoundError"}};async function resolveAlertScope(client,opts){let resolved=await findFirewallAlert(client,opts);if(!resolved)throw new AlertNotFoundError(opts.alertId);let{alert}=resolved;return{alert,startTime:new Date(alert.startedAt),endTime:new Date(alert.resolvedAt??Date.now()),filter:alert.ruleId?eqFilter(RULE_ID_DIMENSION,alert.ruleId):void 0}}var DEFAULT_TOP=5,DEFAULT_DIMENSIONS=["ip","ja4","asn","user-agent","path","rule","host","bot"],LIST_CONCURRENCY=8;function isActivityUnavailable4(error){return isAPIError(error)&&error.status===402}async function list6(client,argv){let parsed=await parseSubcommandArgs(argv,trafficListSubcommand,client,"traffic list");if(typeof parsed=="number")return parsed;let json=!!parsed.flags["--json"],query=getRenamedOption(parsed.flags,"--query","--filter",{json});if("error"in query)return failFirewall(client,{message:query.error,reason:AGENT_REASON.INVALID_ARGUMENTS});parsed.flags["--query"]=query.value;let limit=getRenamedOption(parsed.flags,"--limit","--top",{json});if("error"in limit)return failFirewall(client,{message:limit.error,reason:AGENT_REASON.INVALID_ARGUMENTS});let topResult=validateIntegerRangeWithDefault(limit.value,{flag:"--limit",...TOP_LIMITS,defaultValue:DEFAULT_TOP});if(!topResult.valid)return failFirewall(client,{message:topResult.message,reason:AGENT_REASON.INVALID_ARGUMENTS});let top=topResult.value,requested=normalizeRepeatableStringFilters(parsed.flags["--dimension"]),dimensions=[];for(let alias of requested.length>0?requested:DEFAULT_DIMENSIONS){let dimension=getDimension(alias);if(!dimension)return failFirewall(client,{message:unknownDimensionMessage("--dimension",alias),reason:AGENT_REASON.INVALID_ARGUMENTS});dimensions.includes(dimension)||dimensions.push(dimension)}let mixedMetricError=mixedTrafficMetricError({flags:parsed.flags});if(mixedMetricError)return failFirewall(client,{message:mixedMetricError,nextCommand:"firewall traffic inspect unknown-bot <category>",reason:AGENT_REASON.INVALID_ARGUMENTS});let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=requireTrafficTeam(client,org,"Firewall traffic");if(typeof teamId=="number")return teamId;let asJson=!!parsed.flags["--json"],suggestedCommand=`firewall traffic list${asJson?" --json":""}`,alertScope,alertId=parsed.flags["--alert"];if(alertId){output_manager_default.spinner(`Fetching alert ${import_chalk39.default.bold(alertId)}`);try{alertScope=await resolveAlertScope(client,{alertId,projectId:project.id,teamId})}catch(e){return e instanceof AlertNotFoundError?failFirewall(client,{message:e.message,nextCommand:"firewall alerts list",reason:AGENT_REASON.NOT_FOUND}):failFirewallApi(client,e,{fallback:"Failed to fetch firewall alert",nextCommand:suggestedCommand,permissionAction:"read firewall alerts",projectName:project.name,timeoutJob:"firewall alert"})}}let window=resolveTrafficWindow(parsed.flags["--since"],parsed.flags["--until"],alertScope);if(!window.valid)return failFirewall(client,{message:window.message,reason:AGENT_REASON.INVALID_ARGUMENTS});let filter=andFilters(alertScope?.filter,buildTrafficFilter(parsed.flags)),filtered=!!filter;output_manager_default.spinner(`Fetching firewall traffic for ${import_chalk39.default.bold(project.name)}`);let granularity=pickGranularity(window.endTime.getTime()-window.startTime.getTime(),asJson?DEFAULT_MAX_BUCKETS:trendBuckets(client)),{startTime,endTime}=alignQueryWindow(window.startTime,window.endTime,granularity),activeConfig=dimensions.some(d=>d.alias==="rule")?listFirewallConfigs(client,projectScope(project,teamId)).then(configs=>configs.active).catch(()=>null):Promise.resolve(null);try{let[metrics,topLists,config]=await Promise.all([getFirewallMetrics(client,{projectId:project.id,ownerId:teamId,startTime,endTime,granularity,filter}),runWithConcurrency(dimensions.map(dimension=>async()=>{let title=dimension.widgetTitle;try{let groupBy=dimension.groupBy??[dimension.field],rows=await getTopList(client,{projectId:project.id,ownerId:teamId,startTime,endTime,metric:dimension.metric,groupBy,filter:andFilters(filter,dimension.excludeFilter,dimension.extraFilter),top:topListFetchCount(top,groupBy)});return{dimension:dimension.alias,title,rows:toTopListRows(rows,dimension.field,dimension.labelFields).slice(0,top)}}catch(e){return{dimension:dimension.alias,title,rows:[],unavailable:isActivityUnavailable4(e)?"plan":isUnsupportedDimension(e)?"filter":isRateLimited(e)?"rate-limit":isActivityTimeout(e)?"timeout":"error",retrySeconds:rateLimitRetrySeconds(e),message:isRateLimited(e)?apiServerMessage(e):void 0}}}),LIST_CONCURRENCY),activeConfig]);for(let list7 of topLists)list7.dimension==="rule"&&(list7.rows=list7.rows.map(row=>({...row,label:resolveRuleDisplayName(row.value,config)})));let allFailed=allTopListsUnavailable(topLists);return asJson?(outputJson(client,withWarnings({period:{start:metrics.startTime,end:metrics.endTime,granularity:metrics.granularity},filter:filter??null,...alertScope?{alert:{id:alertScope.alert.id,title:alertScope.alert.title,startedAt:alertScope.alert.startedAt,resolvedAt:alertScope.alert.resolvedAt??null}}:{},stats:metrics.totals,series:metrics.series.map(({action,timeseries})=>({action,timeseries})),topLists:topLists.map(list7=>({dimension:list7.dimension,rows:list7.rows,...list7.unavailable?{unavailable:list7.unavailable}:{},...list7.retrySeconds?{retrySeconds:list7.retrySeconds}:{}}))},[query.warning,limit.warning])),allFailed?1:0):(output_manager_default.print(`
|
|
184
|
+
`),0)}catch(e){return isActivityUnavailable3(e)?failFirewallObservabilityPlan(client,e,project.name):failFirewallApi(client,e,{fallback:"Failed to fetch persistent firewall action",nextCommand:suggestedCommand,permissionAction:"read firewall persistent actions",projectName:project.name,timeoutJob:"firewall persistent action"})}}var COMMAND_CONFIG7={list:getCommandAliases(persistentActionsListSubcommand),inspect:getCommandAliases(persistentActionsInspectSubcommand)};async function main7(client,args,telemetry){let flagsSpecification=getFlagsSpecification(persistentActionsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG7),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","persistent-actions"),output_manager_default.print(help(persistentActionsSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`persistent-actions:${subcommandOriginal}`),printHelp(persistentActionsListSubcommand),0):(telemetry.trackCliSubcommandPersistentActionsList(subcommandOriginal),list5(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`persistent-actions:${subcommandOriginal}`),printHelp(persistentActionsInspectSubcommand),0):(telemetry.trackCliSubcommandPersistentActionsInspect(subcommandOriginal),inspect3(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG7)),output_manager_default.print(help(persistentActionsSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk39=__toESM(require_source(),1);var DEFAULT_TRAFFIC_WINDOW_MS=24*60*60*1e3;function requireTrafficTeam(client,org,what){return org.type==="team"?org.id:failFirewall(client,{message:`${what} needs a team. Run \`vercel switch\` to select a team or pass --scope <team>.`,reason:AGENT_REASON.MISSING_SCOPE})}function resolveTrafficWindow(since,until,scope){let sinceResult=validateTimeBound(since);if(!sinceResult.valid)return{valid:!1,message:sinceResult.message};let untilResult=validateTimeBound(until);if(!untilResult.valid)return{valid:!1,message:untilResult.message};let order=validateTimeOrder(sinceResult.value,untilResult.value);if(!order.valid)return{valid:!1,message:order.message};if(!sinceResult.value&&!untilResult.value&&scope)return{valid:!0,startTime:scope.startTime,endTime:scope.endTime};let endTime=untilResult.value??new Date,startTime=sinceResult.value??scope?.startTime??new Date(endTime.getTime()-DEFAULT_TRAFFIC_WINDOW_MS);return startTime.getTime()>endTime.getTime()?{valid:!1,message:sinceResult.value?"`--since` is in the future. Pass a past time, such as `24h` or an earlier date.":"The alert began after `--until`. Widen the window with `--since`, or drop `--until`."}:{valid:!0,startTime,endTime}}function buildTrafficFilter(flags){let parts=[];for(let dimension of TRAFFIC_DIMENSIONS){let value=flags[`--${dimension.alias}`];typeof value=="string"&&value.length>0&&parts.push(eqFilter(dimension.field,value))}let raw=flags["--query"],rawExpressions=[];if(Array.isArray(raw))for(let expression of raw)typeof expression=="string"&&expression.length>0&&(rawExpressions.push(expression),parts.push(expression));return usesODataSyntax(rawExpressions)&&output_manager_default.warn(FILTER_DEPRECATION_WARNING),andFilters(...parts)}function unknownDimensionMessage(flag,value){return`Unknown ${flag} "${value}". Dimensions: ${dimensionAliases().join(", ")}.`}var WAF_ONLY_ALIASES=new Set(["action","rule"]);function hasStringFlag(flags,flag){let value=flags[flag];return typeof value=="string"&&value.length>0}function requestCountFilterFlags(flags){return TRAFFIC_DIMENSIONS.filter(d=>d.metric&&hasStringFlag(flags,`--${d.alias}`)).map(d=>`--${d.alias}`)}function mixedTrafficMetricError(opts){let requestFilters=requestCountFilterFlags(opts.flags),queryingRequestCount=!!opts.dimension?.metric;if(!queryingRequestCount&&requestFilters.length>0)return`Can't combine ${requestFilters.join(", ")} with firewall-action data. Inspect unknown-bot <category> instead.`;if(!queryingRequestCount||!opts.dimension)return;let unsupported=[];if(hasStringFlag(opts.flags,"--action")&&unsupported.push("--action"),hasStringFlag(opts.flags,"--rule")&&unsupported.push("--rule"),opts.groupBy&&WAF_ONLY_ALIASES.has(opts.groupBy.alias)&&unsupported.push(`--group-by ${opts.groupBy.alias}`),unsupported.length!==0)return`${opts.dimension.label} uses request-count data and cannot be combined with ${unsupported.join(", ")}. Use a request dimension such as path, ip, host, country, asn, ja4, or user-agent instead.`}var TOP_LIMITS={min:1,max:100};function trendBuckets(client){let columns=client.stderr.columns||80;return Math.max(12,Math.min(96,columns-56))}async function runWithConcurrency(tasks,limit){let results=new Array(tasks.length),next=0,workers=Array.from({length:Math.min(limit,tasks.length)},async()=>{for(;next<tasks.length;){let index=next++;results[index]=await tasks[index]()}});return await Promise.all(workers),results}var AlertNotFoundError=class extends Error{constructor(alertId){super(`No firewall alert found for "${alertId}". Run \`vercel firewall alerts list\` to view recent alerts.`),this.name="AlertNotFoundError"}};async function resolveAlertScope(client,opts){let resolved=await findFirewallAlert(client,opts);if(!resolved)throw new AlertNotFoundError(opts.alertId);let{alert}=resolved;return{alert,startTime:new Date(alert.startedAt),endTime:new Date(alert.resolvedAt??Date.now()),filter:alert.ruleId?eqFilter(RULE_ID_DIMENSION,alert.ruleId):void 0}}var DEFAULT_TOP=5,DEFAULT_DIMENSIONS=["ip","ja4","asn","user-agent","path","rule","host","bot"],LIST_CONCURRENCY=8;function isActivityUnavailable4(error){return isAPIError(error)&&error.status===402}async function list6(client,argv){let parsed=await parseSubcommandArgs(argv,trafficListSubcommand,client,"traffic list");if(typeof parsed=="number")return parsed;let json=!!parsed.flags["--json"],query=getRenamedOption(parsed.flags,"--query","--filter",{json});if("error"in query)return failFirewall(client,{message:query.error,reason:AGENT_REASON.INVALID_ARGUMENTS});parsed.flags["--query"]=query.value;let limit=getRenamedOption(parsed.flags,"--limit","--top",{json});if("error"in limit)return failFirewall(client,{message:limit.error,reason:AGENT_REASON.INVALID_ARGUMENTS});let topResult=validateIntegerRangeWithDefault(limit.value,{flag:"--limit",...TOP_LIMITS,defaultValue:DEFAULT_TOP});if(!topResult.valid)return failFirewall(client,{message:topResult.message,reason:AGENT_REASON.INVALID_ARGUMENTS});let top=topResult.value,requested=normalizeRepeatableStringFilters(parsed.flags["--dimension"]),dimensions=[];for(let alias of requested.length>0?requested:DEFAULT_DIMENSIONS){let dimension=getDimension(alias);if(!dimension)return failFirewall(client,{message:unknownDimensionMessage("--dimension",alias),reason:AGENT_REASON.INVALID_ARGUMENTS});dimensions.includes(dimension)||dimensions.push(dimension)}let mixedMetricError=mixedTrafficMetricError({flags:parsed.flags});if(mixedMetricError)return failFirewall(client,{message:mixedMetricError,nextCommand:"firewall traffic inspect unknown-bot <category>",reason:AGENT_REASON.INVALID_ARGUMENTS});let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=requireTrafficTeam(client,org,"Firewall traffic");if(typeof teamId=="number")return teamId;let asJson=!!parsed.flags["--json"],suggestedCommand=`firewall traffic list${asJson?" --json":""}`,alertScope,alertId=parsed.flags["--alert"];if(alertId){output_manager_default.spinner(`Fetching alert ${import_chalk39.default.bold(alertId)}`);try{alertScope=await resolveAlertScope(client,{alertId,projectId:project.id,teamId})}catch(e){return e instanceof AlertNotFoundError?failFirewall(client,{message:e.message,nextCommand:"firewall alerts list",reason:AGENT_REASON.NOT_FOUND}):failFirewallApi(client,e,{fallback:"Failed to fetch firewall alert",nextCommand:suggestedCommand,permissionAction:"read firewall alerts",projectName:project.name,timeoutJob:"firewall alert"})}}let window=resolveTrafficWindow(parsed.flags["--since"],parsed.flags["--until"],alertScope);if(!window.valid)return failFirewall(client,{message:window.message,reason:AGENT_REASON.INVALID_ARGUMENTS});let filter=andFilters(alertScope?.filter,buildTrafficFilter(parsed.flags)),filtered=!!filter;output_manager_default.spinner(`Fetching firewall traffic for ${import_chalk39.default.bold(project.name)}`);let granularity=pickGranularity(window.endTime.getTime()-window.startTime.getTime(),asJson?DEFAULT_MAX_BUCKETS:trendBuckets(client)),{startTime,endTime}=alignQueryWindow(window.startTime,window.endTime,granularity),activeConfig=dimensions.some(d=>d.alias==="rule")?listFirewallConfigs(client,projectScope(project,teamId)).then(configs=>configs.active).catch(()=>null):Promise.resolve(null);try{let[metrics,topLists,config]=await Promise.all([getFirewallMetrics(client,{projectId:project.id,ownerId:teamId,startTime,endTime,granularity,filter}),runWithConcurrency(dimensions.map(dimension=>async()=>{let title=dimension.widgetTitle;try{let groupBy=dimension.groupBy??[dimension.field],rows=await getTopList(client,{projectId:project.id,ownerId:teamId,startTime,endTime,metric:dimension.metric,groupBy,filter:andFilters(filter,dimension.excludeFilter,dimension.extraFilter),top:topListFetchCount(top,groupBy)});return{dimension:dimension.alias,title,rows:toTopListRows(rows,dimension.field,dimension.labelFields).slice(0,top)}}catch(e){return{dimension:dimension.alias,title,rows:[],unavailable:isActivityUnavailable4(e)?"plan":isUnsupportedDimension(e)?"filter":isRateLimited(e)?"rate-limit":isActivityTimeout(e)?"timeout":"error",retrySeconds:rateLimitRetrySeconds(e),message:isRateLimited(e)?apiServerMessage(e):void 0}}}),LIST_CONCURRENCY),activeConfig]);for(let list7 of topLists)list7.dimension==="rule"&&(list7.rows=list7.rows.map(row=>({...row,label:resolveRuleDisplayName(row.value,config)})));let allFailed=allTopListsUnavailable(topLists);return asJson?(outputJson(client,withWarnings({period:{start:metrics.startTime,end:metrics.endTime,granularity:metrics.granularity},filter:filter??null,...alertScope?{alert:{id:alertScope.alert.id,title:alertScope.alert.title,startedAt:alertScope.alert.startedAt,resolvedAt:alertScope.alert.resolvedAt??null}}:{},stats:metrics.totals,series:metrics.series.map(({action,timeseries})=>({action,timeseries})),topLists:topLists.map(list7=>({dimension:list7.dimension,rows:list7.rows,...list7.unavailable?{unavailable:list7.unavailable}:{},...list7.retrySeconds?{retrySeconds:list7.retrySeconds}:{}}))},[query.warning,limit.warning])),allFailed?1:0):(output_manager_default.print(`
|
|
185
185
|
`),output_manager_default.print(formatTrafficList({series:metrics.series,topLists,startTime:metrics.startTime,endTime:metrics.endTime,granularity:metrics.granularity,filtered})),allFailed||output_manager_default.print(`
|
|
186
186
|
${import_chalk39.default.dim(" Break any of these values down further:")}
|
|
187
187
|
${withGlobalFlags(client,"firewall traffic inspect <dimension> <value>")}
|
|
@@ -192,7 +192,7 @@ ${nextSteps(client,dimension.alias)}
|
|
|
192
192
|
`),0)}catch(e){return isActivityUnavailable5(e)?failFirewallObservabilityPlan(client,e,project.name):failFirewallApi(client,e,{fallback:"Failed to fetch firewall traffic",nextCommand:suggestedCommand,permissionAction:"query firewall traffic",projectName:project.name,timeoutJob:"firewall traffic"})}}async function requestCountMetrics(client,opts){let result=await getGroupedTimeseries(client,opts),group=result.groups[0],total=group?.total??0,timeseries=result.axis.map((timestamp,i)=>({timestamp,value:group?.series[i]??0}));return{startTime:result.startTime,endTime:result.endTime,granularity:result.granularity,series:total>0?[{action:"requests",total,timeseries}]:[],totals:total>0?{requests:total}:{}}}function nextSteps(client,alias){let steps=[];if(alias==="ip"?steps.push(["Block this client on every host","firewall ip-blocks block <ip>"]):alias==="rule"&&steps.push(["Change what this rule does","firewall rules update <rule>"]),steps.push(["Break the same traffic down another way",`firewall traffic inspect ${alias} <value> --group-by <dimension>`]),steps.length===1){let[why,command]=steps[0];return`${import_chalk40.default.dim(` ${why}:`)}
|
|
193
193
|
${withGlobalFlags(client,command)}
|
|
194
194
|
`}return[` ${import_chalk40.default.bold("Next steps:")}`,...steps.flatMap(([why,command])=>[import_chalk40.default.dim(` ${why}`),` ${withGlobalFlags(client,command)}`]),""].join(`
|
|
195
|
-
`)}var COMMAND_CONFIG8={list:getCommandAliases(trafficListSubcommand),inspect:getCommandAliases(trafficInspectSubcommand)};async function main8(client,args,telemetry){let flagsSpecification=getFlagsSpecification(trafficSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG8),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","traffic"),output_manager_default.print(help(trafficSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`traffic:${subcommandOriginal}`),printHelp(trafficListSubcommand),0):(telemetry.trackCliSubcommandTrafficList(subcommandOriginal),list6(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`traffic:${subcommandOriginal}`),printHelp(trafficInspectSubcommand),0):(telemetry.trackCliSubcommandTrafficInspect(subcommandOriginal),inspect4(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG8)),output_manager_default.print(help(trafficSubcommand,{parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk41=__toESM(require_source(),1);var UNKNOWN_BOT_TOP=5;function isActivityUnavailable6(error){return isAPIError(error)&&error.status===402}async function botManagement(client,argv){let parsed=await parseSubcommandArgs(argv,botManagementSubcommand,client,"bot-management");if(typeof parsed=="number")return parsed;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;output_manager_default.spinner(`Fetching bot management for ${import_chalk41.default.bold(project.name)}`);try{let[{active,draft},unknownBotTraffic]=await Promise.all([listFirewallConfigs(client,projectScope(project,teamId)),teamId?loadUnknownBotTraffic(client,project.id,teamId):Promise.resolve(void 0)]),managed=getManagedBotRules(draft??active);if(parsed.flags["--json"])return outputJson(client,{managed:managed.map(managedBotJson),...unknownBotTraffic?{unknownBotTraffic:{rows:unknownBotTraffic.rows,...unknownBotTraffic.unavailable?{unavailable:unknownBotTraffic.unavailable}:{},...unknownBotTraffic.retrySeconds?{retrySeconds:unknownBotTraffic.retrySeconds}:{}}}:{}}),0;output_manager_default.print(`
|
|
195
|
+
`)}var COMMAND_CONFIG8={list:getCommandAliases(trafficListSubcommand),inspect:getCommandAliases(trafficInspectSubcommand)};async function main8(client,args,telemetry){let flagsSpecification=getFlagsSpecification(trafficSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(args,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG8),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall","traffic"),output_manager_default.print(help(trafficSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand){case"list":return needHelp?(telemetry.trackCliFlagHelp("firewall",`traffic:${subcommandOriginal}`),printHelp(trafficListSubcommand),0):(telemetry.trackCliSubcommandTrafficList(subcommandOriginal),list6(client,subArgs));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("firewall",`traffic:${subcommandOriginal}`),printHelp(trafficInspectSubcommand),0):(telemetry.trackCliSubcommandTrafficInspect(subcommandOriginal),inspect4(client,subArgs));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG8)),output_manager_default.print(help(trafficSubcommand,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns})),2}}var import_chalk41=__toESM(require_source(),1);var UNKNOWN_BOT_TOP=5;function isActivityUnavailable6(error){return isAPIError(error)&&error.status===402}async function botManagement(client,argv){let parsed=await parseSubcommandArgs(argv,botManagementSubcommand,client,"bot-management");if(typeof parsed=="number")return parsed;let link=await requireProjectContext(client,"firewall",parsed.flags["--project"]);if(typeof link=="number")return link;let{project,org}=link,teamId=org.type==="team"?org.id:void 0;output_manager_default.spinner(`Fetching bot management for ${import_chalk41.default.bold(project.name)}`);try{let[{active,draft},unknownBotTraffic]=await Promise.all([listFirewallConfigs(client,projectScope(project,teamId)),teamId?loadUnknownBotTraffic(client,project.id,teamId):Promise.resolve(void 0)]),managed=getManagedBotRules(draft??active);if(parsed.flags["--json"])return outputJson(client,{managed:managed.map(managedBotJson),...unknownBotTraffic?{unknownBotTraffic:{rows:unknownBotTraffic.rows,...unknownBotTraffic.unavailable?{unavailable:unknownBotTraffic.unavailable}:{},...unknownBotTraffic.retrySeconds?{retrySeconds:unknownBotTraffic.retrySeconds}:{}}}:{}}),0;output_manager_default.print(`
|
|
196
196
|
${formatManagedBotRulesTable(managed)}
|
|
197
197
|
`),unknownBotTraffic&&output_manager_default.print(`
|
|
198
198
|
${formatTrafficTopList(unknownBotTraffic)}
|
|
@@ -201,7 +201,7 @@ ${formatTrafficTopList(unknownBotTraffic)}
|
|
|
201
201
|
${steps.flatMap(([why,command])=>[import_chalk41.default.dim(` ${why}`),` ${withGlobalFlags(client,command)}`]).join(`
|
|
202
202
|
`)}
|
|
203
203
|
|
|
204
|
-
`),0}catch(e){return failFirewallApi(client,e,{fallback:"Failed to fetch bot management",nextCommand:"firewall bot-management",permissionAction:"read firewall config",projectName:project.name,timeoutJob:"bot management"})}finally{output_manager_default.stopSpinner()}}async function loadUnknownBotTraffic(client,projectId,teamId){let dimension=getDimension("unknown-bot"),title=dimension?.widgetTitle??"Unknown Bot Traffic",unavailable=error=>({dimension:"unknown-bot",title,rows:[],unavailable:isActivityUnavailable6(error)?"plan":isUnsupportedDimension(error)?"filter":isRateLimited(error)?"rate-limit":isActivityTimeout(error)?"timeout":"error",retrySeconds:rateLimitRetrySeconds(error),message:isRateLimited(error)?apiServerMessage(error):void 0});if(!dimension)return unavailable(new Error("unknown-bot dimension missing"));let endTime=new Date,startTime=new Date(endTime.getTime()-DEFAULT_TRAFFIC_WINDOW_MS);try{let rows=await getTopList(client,{projectId,ownerId:teamId,startTime,endTime,metric:dimension.metric,groupBy:[dimension.field],filter:andFilters(dimension.excludeFilter,dimension.extraFilter),top:topListFetchCount(UNKNOWN_BOT_TOP)});return{dimension:dimension.alias,title,rows:toTopListRows(rows,dimension.field).slice(0,UNKNOWN_BOT_TOP)}}catch(e){return output_manager_default.debug(isAPIError(e)?`Unknown bot traffic query failed: status=${e.status} code=${e.code??"(none)"} message=${e.serverMessage}`:`Unknown bot traffic query failed: ${e instanceof Error?e.message:String(e)}`),unavailable(e)}}var FirewallTelemetryClient=class extends TelemetryClient{trackCliFlagTeamLevel(value){value&&this.trackCliFlag("team-level")}trackCliSubcommandStatus(actual){this.trackCliSubcommand({subcommand:"status",value:actual})}trackCliSubcommandOverview(actual){this.trackCliSubcommand({subcommand:"overview",value:actual})}trackCliSubcommandDiff(actual){this.trackCliSubcommand({subcommand:"diff",value:actual})}trackCliSubcommandPublish(actual){this.trackCliSubcommand({subcommand:"publish",value:actual})}trackCliSubcommandDiscard(actual){this.trackCliSubcommand({subcommand:"discard",value:actual})}trackCliSubcommandRules(actual){this.trackCliSubcommand({subcommand:"rules",value:actual})}trackCliSubcommandRulesList(actual){this.trackCliSubcommand({subcommand:"rules:list",value:actual})}trackCliSubcommandRulesInspect(actual){this.trackCliSubcommand({subcommand:"rules:inspect",value:actual})}trackCliSubcommandRulesAdd(actual){this.trackCliSubcommand({subcommand:"rules:add",value:actual})}trackCliSubcommandRulesUpdate(actual){this.trackCliSubcommand({subcommand:"rules:update",value:actual})}trackCliSubcommandRulesEnable(actual){this.trackCliSubcommand({subcommand:"rules:enable",value:actual})}trackCliSubcommandRulesDisable(actual){this.trackCliSubcommand({subcommand:"rules:disable",value:actual})}trackCliSubcommandRulesRemove(actual){this.trackCliSubcommand({subcommand:"rules:remove",value:actual})}trackCliSubcommandRulesReorder(actual){this.trackCliSubcommand({subcommand:"rules:reorder",value:actual})}trackCliSubcommandRulesMove(actual){this.trackCliSubcommand({subcommand:"rules:move",value:actual})}trackCliSubcommandIpBlocks(actual){this.trackCliSubcommand({subcommand:"ip-blocks",value:actual})}trackCliSubcommandIpBlocksList(actual){this.trackCliSubcommand({subcommand:"ip-blocks:list",value:actual})}trackCliSubcommandIpBlocksBlock(actual){this.trackCliSubcommand({subcommand:"ip-blocks:block",value:actual})}trackCliSubcommandIpBlocksUnblock(actual){this.trackCliSubcommand({subcommand:"ip-blocks:unblock",value:actual})}trackCliSubcommandSystemBypass(actual){this.trackCliSubcommand({subcommand:"system-bypass",value:actual})}trackCliSubcommandSystemBypassList(actual){this.trackCliSubcommand({subcommand:"system-bypass:list",value:actual})}trackCliSubcommandSystemBypassAdd(actual){this.trackCliSubcommand({subcommand:"system-bypass:add",value:actual})}trackCliSubcommandSystemBypassRemove(actual){this.trackCliSubcommand({subcommand:"system-bypass:remove",value:actual})}trackCliSubcommandAttackMode(actual){this.trackCliSubcommand({subcommand:"attack-mode",value:actual})}trackCliSubcommandAttackModeEnable(actual){this.trackCliSubcommand({subcommand:"attack-mode:enable",value:actual})}trackCliSubcommandAttackModeDisable(actual){this.trackCliSubcommand({subcommand:"attack-mode:disable",value:actual})}trackCliSubcommandSystemMitigations(actual){this.trackCliSubcommand({subcommand:"system-mitigations",value:actual})}trackCliSubcommandSystemMitigationsPause(actual){this.trackCliSubcommand({subcommand:"system-mitigations:pause",value:actual})}trackCliSubcommandSystemMitigationsResume(actual){this.trackCliSubcommand({subcommand:"system-mitigations:resume",value:actual})}trackCliSubcommandAlerts(actual){this.trackCliSubcommand({subcommand:"alerts",value:actual})}trackCliSubcommandAlertsList(actual){this.trackCliSubcommand({subcommand:"alerts:list",value:actual})}trackCliSubcommandAlertsInspect(actual){this.trackCliSubcommand({subcommand:"alerts:inspect",value:actual})}trackCliSubcommandPersistentActions(actual){this.trackCliSubcommand({subcommand:"persistent-actions",value:actual})}trackCliSubcommandPersistentActionsList(actual){this.trackCliSubcommand({subcommand:"persistent-actions:list",value:actual})}trackCliSubcommandPersistentActionsInspect(actual){this.trackCliSubcommand({subcommand:"persistent-actions:inspect",value:actual})}trackCliSubcommandTraffic(actual){this.trackCliSubcommand({subcommand:"traffic",value:actual})}trackCliSubcommandTrafficList(actual){this.trackCliSubcommand({subcommand:"traffic:list",value:actual})}trackCliSubcommandTrafficInspect(actual){this.trackCliSubcommand({subcommand:"traffic:inspect",value:actual})}trackCliSubcommandBotManagement(actual){this.trackCliSubcommand({subcommand:"bot-management",value:actual})}};var COMMAND_CONFIG9={overview:getCommandAliases(overviewSubcommand),status:getCommandAliases(statusSubcommand),rules:getCommandAliases(rulesSubcommand),diff:getCommandAliases(diffSubcommand),publish:getCommandAliases(publishSubcommand),discard:getCommandAliases(discardSubcommand),"ip-blocks":getCommandAliases(ipBlocksSubcommand),"system-bypass":getCommandAliases(systemBypassSubcommand),"attack-mode":getCommandAliases(attackModeSubcommand),"system-mitigations":getCommandAliases(systemMitigationsSubcommand),alerts:getCommandAliases(alertsSubcommand),"persistent-actions":getCommandAliases(persistentActionsSubcommand),traffic:getCommandAliases(trafficSubcommand),"bot-management":getCommandAliases(botManagementSubcommand)};async function main9(client){let telemetry=new FirewallTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(firewallCommand.options);try{parsedArgs=parseArguments(client.argv.slice(2),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let subArgs=parsedArgs.args.slice(1),{subcommand,args,subcommandOriginal}=getSubcommand(subArgs,COMMAND_CONFIG9),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall"),output_manager_default.print(help(firewallCommand,{columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand&&!needHelp&&(telemetry.trackCliOptionProject(getProjectOptionFromArgs(args)),telemetry.trackCliFlagTeamLevel(args.includes("--team-level"))),subcommand){case"status":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(statusSubcommand),0):(telemetry.trackCliSubcommandStatus(subcommandOriginal),status(client,args));case"overview":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(overviewSubcommand),0):(telemetry.trackCliSubcommandOverview(subcommandOriginal),overview(client,args));case"diff":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(diffSubcommand),0):(telemetry.trackCliSubcommandDiff(subcommandOriginal),diff(client,args));case"publish":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(publishSubcommand),0):(telemetry.trackCliSubcommandPublish(subcommandOriginal),publish(client,args));case"discard":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(discardSubcommand),0):(telemetry.trackCliSubcommandDiscard(subcommandOriginal),discard(client,args));case"rules":{telemetry.trackCliSubcommandRules(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main5(client,nestedArgs,telemetry)}case"ip-blocks":{telemetry.trackCliSubcommandIpBlocks(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main4(client,nestedArgs,telemetry)}case"system-bypass":{telemetry.trackCliSubcommandSystemBypass(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main(client,nestedArgs,telemetry)}case"attack-mode":{telemetry.trackCliSubcommandAttackMode(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main2(client,nestedArgs,telemetry)}case"system-mitigations":{telemetry.trackCliSubcommandSystemMitigations(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main3(client,nestedArgs,telemetry)}case"alerts":{telemetry.trackCliSubcommandAlerts(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main6(client,nestedArgs,telemetry)}case"persistent-actions":{telemetry.trackCliSubcommandPersistentActions(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main7(client,nestedArgs,telemetry)}case"traffic":{telemetry.trackCliSubcommandTraffic(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main8(client,nestedArgs,telemetry)}case"bot-management":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(botManagementSubcommand),0):(telemetry.trackCliSubcommandBotManagement(subcommandOriginal),botManagement(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG9)),output_manager_default.print(help(firewallCommand,{columns:client.stderr.columns})),2}}var FlagsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandInspect(actual){this.trackCliSubcommand({subcommand:"inspect",value:actual})}trackCliSubcommandVersions(actual){this.trackCliSubcommand({subcommand:"versions",value:actual})}trackCliSubcommandEvaluations(actual){this.trackCliSubcommand({subcommand:"evaluations",value:actual})}trackCliSubcommandStale(actual){this.trackCliSubcommand({subcommand:"stale",value:actual})}trackCliSubcommandOpen(actual){this.trackCliSubcommand({subcommand:"open",value:actual})}trackCliSubcommandCreate(actual){this.trackCliSubcommand({subcommand:"create",value:actual})}trackCliSubcommandUpdate(actual){this.trackCliSubcommand({subcommand:"update",value:actual})}trackCliSubcommandSet(actual){this.trackCliSubcommand({subcommand:"set",value:actual})}trackCliSubcommandTargeting(actual){this.trackCliSubcommand({subcommand:"targeting",value:actual})}trackCliSubcommandUseTargeting(actual){this.trackCliSubcommand({subcommand:"use-targeting",value:actual})}trackCliSubcommandSplit(actual){this.trackCliSubcommand({subcommand:"split",value:actual})}trackCliSubcommandRollout(actual){this.trackCliSubcommand({subcommand:"rollout",value:actual})}trackCliSubcommandDelete(actual){this.trackCliSubcommand({subcommand:"delete",value:actual})}trackCliSubcommandArchive(actual){this.trackCliSubcommand({subcommand:"archive",value:actual})}trackCliSubcommandUnarchive(actual){this.trackCliSubcommand({subcommand:"unarchive",value:actual})}trackCliSubcommandDisable(actual){this.trackCliSubcommand({subcommand:"disable",value:actual})}trackCliSubcommandEnable(actual){this.trackCliSubcommand({subcommand:"enable",value:actual})}trackCliSubcommandSdkKeys(actual){this.trackCliSubcommand({subcommand:"sdk-keys",value:actual})}trackCliSubcommandConnections(actual){this.trackCliSubcommand({subcommand:"connections",value:actual})}trackCliSubcommandSegments(actual){this.trackCliSubcommand({subcommand:"segments",value:actual})}trackCliSubcommandEntities(actual){this.trackCliSubcommand({subcommand:"entities",value:actual})}trackCliSubcommandLabels(actual){this.trackCliSubcommand({subcommand:"labels",value:actual})}trackCliSubcommandRules(actual){this.trackCliSubcommand({subcommand:"rules",value:actual})}trackCliSubcommandTargets(actual){this.trackCliSubcommand({subcommand:"targets",value:actual})}trackCliSubcommandPrepare(actual){this.trackCliSubcommand({subcommand:"prepare",value:actual})}trackCliSubcommandDatafile(actual){this.trackCliSubcommand({subcommand:"datafile",value:actual})}trackCliSubcommandOverride(actual){this.trackCliSubcommand({subcommand:"override",value:actual})}};var import_chalk42=__toESM(require_source(),1),import_ms=__toESM(require_ms(),1),import_pluralize=__toESM(require_pluralize(),1);function flagUrl(projectId,flagIdOrSlug){return`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags/${encodeURIComponent(flagIdOrSlug)}`}async function fetchFlagForUpdate(client,projectId,flagIdOrSlug){output_manager_default.debug(`Fetching feature flag ${flagIdOrSlug} for project ${projectId} with ETag`);let response=await client.fetch(flagUrl(projectId,flagIdOrSlug),{json:!1}),etag=response.headers.get("etag");if(!etag)throw new Error("Unable to update flag safely because the flag ETag is missing.");return{flag:await response.json(),etag}}async function updateFlag(client,projectId,flagIdOrSlug,request,options){output_manager_default.debug(`Updating feature flag ${flagIdOrSlug} for project ${projectId}`);let url=flagUrl(projectId,flagIdOrSlug);return await client.fetch(url,{method:"PATCH",headers:options?.ifMatch?{"If-Match":options.ifMatch}:void 0,body:request})}var MAX_FLAGS_PAGE_LIMIT=100,MAX_FLAG_VERSIONS_PAGE_LIMIT=100;async function getFlags(client,projectId,options={}){let{state="active",tags,createdBy,maintainerIds,limit,cursor}=options;output_manager_default.debug(`Fetching feature flags for project ${projectId}`);let basePath=`/v2/projects/${encodeURIComponent(projectId)}/feature-flags/flags`,buildQuery=(pageLimit,pageCursor2)=>{let query=new URLSearchParams;query.set("state",state),query.set("limit",String(pageLimit)),pageCursor2&&query.set("cursor",pageCursor2),createdBy&&query.set("createdBy",createdBy);for(let tag of tags??[])query.append("tags",tag);for(let maintainerId of maintainerIds??[])query.append("maintainerIds",maintainerId);return query.toString()};if(limit!==void 0||cursor!==void 0){let pageLimit=Math.min(limit??MAX_FLAGS_PAGE_LIMIT,MAX_FLAGS_PAGE_LIMIT),response=await client.fetch(`${basePath}?${buildQuery(pageLimit,cursor)}`);return{flags:response.data,next:response.pagination?.next??null}}let flags=[],pageCursor;do{let response=await client.fetch(`${basePath}?${buildQuery(MAX_FLAGS_PAGE_LIMIT,pageCursor)}`);flags.push(...response.data),pageCursor=response.pagination?.next??void 0}while(pageCursor);return{flags,next:null}}async function getFlag(client,projectId,flagIdOrSlug){output_manager_default.debug(`Fetching feature flag ${flagIdOrSlug} for project ${projectId}`);let url=flagUrl(projectId,flagIdOrSlug);return await client.fetch(url)}async function getFlagSettings(client,projectId){return output_manager_default.debug(`Fetching feature flag settings for project ${projectId}`),await client.fetch(flagSettingsUrl(projectId))}async function updateFlagSettings(client,projectId,request){return output_manager_default.debug(`Updating feature flag settings for project ${projectId}`),client.fetch(flagSettingsUrl(projectId),{method:"PATCH",body:request})}function flagSettingsUrl(projectId){return`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/settings`}async function getFlagVersions(client,projectId,flagIdOrSlug,options={}){output_manager_default.debug(`Fetching feature flag versions for ${flagIdOrSlug} in project ${projectId}`);let query=new URLSearchParams;query.set("withMetadata","true"),options.environment&&query.set("environment",options.environment),options.limit!==void 0&&query.set("limit",String(options.limit)),options.cursor&&query.set("cursor",options.cursor);let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags/${encodeURIComponent(flagIdOrSlug)}/versions?${query.toString()}`,response=await client.fetch(url),next=response.pagination?.next??(response.pagination?.hasNext?response.pagination.cursor:null)??null;return{versions:response.versions,next}}var FlagsLsTelemetryClient=class extends TelemetryClient{trackCliOptionState(state){state&&this.trackCliOption({option:"state",value:state})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}trackCliOptionTag(tags){tags&&tags.length>0&&this.trackCliOption({option:"tag",value:this.redactedValue})}trackCliOptionCreatedBy(createdBy){createdBy&&this.trackCliOption({option:"created-by",value:this.redactedValue})}trackCliOptionMaintainer(maintainerIds){maintainerIds&&maintainerIds.length>0&&this.trackCliOption({option:"maintainer",value:this.redactedValue})}trackCliOptionMaintainerId(maintainerIds){maintainerIds&&maintainerIds.length>0&&this.trackCliOption({option:"maintainer-id",value:this.redactedValue})}trackCliOptionLimit(limit){limit!==void 0&&this.trackCliOption({option:"limit",value:String(limit)})}trackCliOptionNext(next){next&&this.trackCliOption({option:"next",value:this.redactedValue})}};async function ls(client,argv){let telemetryClient=new FlagsLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(listSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,state=flags["--state"]||"active",tags=flags["--tag"],createdBy=flags["--created-by"],limit=flags["--limit"],next=flags["--next"],json=flags["--json"],projectName=getProjectNameFromFlags(flags),maintainer=getRenamedOption(flags,"--maintainer","--maintainer-id",{json});if(telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionState(state),telemetryClient.trackCliOptionTag(tags),telemetryClient.trackCliOptionCreatedBy(createdBy),telemetryClient.trackCliOptionMaintainer(flags["--maintainer"]),telemetryClient.trackCliOptionMaintainerId(flags["--maintainer-id"]),telemetryClient.trackCliOptionLimit(limit),telemetryClient.trackCliOptionNext(next),telemetryClient.trackCliFlagJson(json),"error"in maintainer)return reportRenamedOptionError(client,maintainer.error,{json});let maintainerIds=maintainer.value;if(limit!==void 0&&(!Number.isInteger(limit)||limit<1||limit>MAX_FLAGS_PAGE_LIMIT))return output_manager_default.error(`The --limit option must be an integer between 1 and ${MAX_FLAGS_PAGE_LIMIT}.`),2;let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),lsStamp=stamp_default();output_manager_default.spinner(`Fetching ${state} feature flags for ${projectSlugLink}`);try{let{flags:flagsList,next:nextCursor}=await getFlags(client,project.id,{state,tags,createdBy,maintainerIds,limit,cursor:next});if(output_manager_default.stopSpinner(),json)outputJson2(client,flagsList,nextCursor,[maintainer.warning]);else if(flagsList.length===0)output_manager_default.log(`No ${state} feature flags found for ${projectSlugLink} ${import_chalk42.default.gray(lsStamp())}`);else if(output_manager_default.log(`${(0,import_pluralize.default)("feature flag",flagsList.length,!0)} found for ${projectSlugLink} ${import_chalk42.default.gray(lsStamp())}`),printFlagsTable(flagsList),nextCursor){let nextCmd=buildNextPageCommand(flags,tags,maintainerIds,nextCursor);output_manager_default.print(`
|
|
204
|
+
`),0}catch(e){return failFirewallApi(client,e,{fallback:"Failed to fetch bot management",nextCommand:"firewall bot-management",permissionAction:"read firewall config",projectName:project.name,timeoutJob:"bot management"})}finally{output_manager_default.stopSpinner()}}async function loadUnknownBotTraffic(client,projectId,teamId){let dimension=getDimension("unknown-bot"),title=dimension?.widgetTitle??"Unknown Bot Traffic",unavailable=error=>({dimension:"unknown-bot",title,rows:[],unavailable:isActivityUnavailable6(error)?"plan":isUnsupportedDimension(error)?"filter":isRateLimited(error)?"rate-limit":isActivityTimeout(error)?"timeout":"error",retrySeconds:rateLimitRetrySeconds(error),message:isRateLimited(error)?apiServerMessage(error):void 0});if(!dimension)return unavailable(new Error("unknown-bot dimension missing"));let endTime=new Date,startTime=new Date(endTime.getTime()-DEFAULT_TRAFFIC_WINDOW_MS);try{let rows=await getTopList(client,{projectId,ownerId:teamId,startTime,endTime,metric:dimension.metric,groupBy:[dimension.field],filter:andFilters(dimension.excludeFilter,dimension.extraFilter),top:topListFetchCount(UNKNOWN_BOT_TOP)});return{dimension:dimension.alias,title,rows:toTopListRows(rows,dimension.field).slice(0,UNKNOWN_BOT_TOP)}}catch(e){return output_manager_default.debug(isAPIError(e)?`Unknown bot traffic query failed: status=${e.status} code=${e.code??"(none)"} message=${e.serverMessage}`:`Unknown bot traffic query failed: ${e instanceof Error?e.message:String(e)}`),unavailable(e)}}var FirewallTelemetryClient=class extends TelemetryClient{trackCliFlagTeamLevel(value){value&&this.trackCliFlag("team-level")}trackCliSubcommandStatus(actual){this.trackCliSubcommand({subcommand:"status",value:actual})}trackCliSubcommandOverview(actual){this.trackCliSubcommand({subcommand:"overview",value:actual})}trackCliSubcommandDiff(actual){this.trackCliSubcommand({subcommand:"diff",value:actual})}trackCliSubcommandPublish(actual){this.trackCliSubcommand({subcommand:"publish",value:actual})}trackCliSubcommandDiscard(actual){this.trackCliSubcommand({subcommand:"discard",value:actual})}trackCliSubcommandRules(actual){this.trackCliSubcommand({subcommand:"rules",value:actual})}trackCliSubcommandRulesList(actual){this.trackCliSubcommand({subcommand:"rules:list",value:actual})}trackCliSubcommandRulesInspect(actual){this.trackCliSubcommand({subcommand:"rules:inspect",value:actual})}trackCliSubcommandRulesAdd(actual){this.trackCliSubcommand({subcommand:"rules:add",value:actual})}trackCliSubcommandRulesUpdate(actual){this.trackCliSubcommand({subcommand:"rules:update",value:actual})}trackCliSubcommandRulesEnable(actual){this.trackCliSubcommand({subcommand:"rules:enable",value:actual})}trackCliSubcommandRulesDisable(actual){this.trackCliSubcommand({subcommand:"rules:disable",value:actual})}trackCliSubcommandRulesRemove(actual){this.trackCliSubcommand({subcommand:"rules:remove",value:actual})}trackCliSubcommandRulesReorder(actual){this.trackCliSubcommand({subcommand:"rules:reorder",value:actual})}trackCliSubcommandRulesMove(actual){this.trackCliSubcommand({subcommand:"rules:move",value:actual})}trackCliSubcommandIpBlocks(actual){this.trackCliSubcommand({subcommand:"ip-blocks",value:actual})}trackCliSubcommandIpBlocksList(actual){this.trackCliSubcommand({subcommand:"ip-blocks:list",value:actual})}trackCliSubcommandIpBlocksBlock(actual){this.trackCliSubcommand({subcommand:"ip-blocks:block",value:actual})}trackCliSubcommandIpBlocksUnblock(actual){this.trackCliSubcommand({subcommand:"ip-blocks:unblock",value:actual})}trackCliSubcommandSystemBypass(actual){this.trackCliSubcommand({subcommand:"system-bypass",value:actual})}trackCliSubcommandSystemBypassList(actual){this.trackCliSubcommand({subcommand:"system-bypass:list",value:actual})}trackCliSubcommandSystemBypassAdd(actual){this.trackCliSubcommand({subcommand:"system-bypass:add",value:actual})}trackCliSubcommandSystemBypassRemove(actual){this.trackCliSubcommand({subcommand:"system-bypass:remove",value:actual})}trackCliSubcommandAttackMode(actual){this.trackCliSubcommand({subcommand:"attack-mode",value:actual})}trackCliSubcommandAttackModeEnable(actual){this.trackCliSubcommand({subcommand:"attack-mode:enable",value:actual})}trackCliSubcommandAttackModeDisable(actual){this.trackCliSubcommand({subcommand:"attack-mode:disable",value:actual})}trackCliSubcommandSystemMitigations(actual){this.trackCliSubcommand({subcommand:"system-mitigations",value:actual})}trackCliSubcommandSystemMitigationsPause(actual){this.trackCliSubcommand({subcommand:"system-mitigations:pause",value:actual})}trackCliSubcommandSystemMitigationsResume(actual){this.trackCliSubcommand({subcommand:"system-mitigations:resume",value:actual})}trackCliSubcommandAlerts(actual){this.trackCliSubcommand({subcommand:"alerts",value:actual})}trackCliSubcommandAlertsList(actual){this.trackCliSubcommand({subcommand:"alerts:list",value:actual})}trackCliSubcommandAlertsInspect(actual){this.trackCliSubcommand({subcommand:"alerts:inspect",value:actual})}trackCliSubcommandPersistentActions(actual){this.trackCliSubcommand({subcommand:"persistent-actions",value:actual})}trackCliSubcommandPersistentActionsList(actual){this.trackCliSubcommand({subcommand:"persistent-actions:list",value:actual})}trackCliSubcommandPersistentActionsInspect(actual){this.trackCliSubcommand({subcommand:"persistent-actions:inspect",value:actual})}trackCliSubcommandTraffic(actual){this.trackCliSubcommand({subcommand:"traffic",value:actual})}trackCliSubcommandTrafficList(actual){this.trackCliSubcommand({subcommand:"traffic:list",value:actual})}trackCliSubcommandTrafficInspect(actual){this.trackCliSubcommand({subcommand:"traffic:inspect",value:actual})}trackCliSubcommandBotManagement(actual){this.trackCliSubcommand({subcommand:"bot-management",value:actual})}};var COMMAND_CONFIG9={overview:getCommandAliases(overviewSubcommand),status:getCommandAliases(statusSubcommand),rules:getCommandAliases(rulesSubcommand),diff:getCommandAliases(diffSubcommand),publish:getCommandAliases(publishSubcommand),discard:getCommandAliases(discardSubcommand),"ip-blocks":getCommandAliases(ipBlocksSubcommand),"system-bypass":getCommandAliases(systemBypassSubcommand),"attack-mode":getCommandAliases(attackModeSubcommand),"system-mitigations":getCommandAliases(systemMitigationsSubcommand),alerts:getCommandAliases(alertsSubcommand),"persistent-actions":getCommandAliases(persistentActionsSubcommand),traffic:getCommandAliases(trafficSubcommand),"bot-management":getCommandAliases(botManagementSubcommand)};async function main9(client){let telemetry=new FirewallTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(firewallCommand.options);try{parsedArgs=parseArguments(client.argv.slice(2),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let subArgs=parsedArgs.args.slice(1),{subcommand,args,subcommandOriginal}=getSubcommand(subArgs,COMMAND_CONFIG9),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("firewall"),output_manager_default.print(help(firewallCommand,{stream:client.stderr,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:firewallCommand,columns:client.stderr.columns}))}switch(subcommand&&!needHelp&&(telemetry.trackCliOptionProject(getProjectOptionFromArgs(args)),telemetry.trackCliFlagTeamLevel(args.includes("--team-level"))),subcommand){case"status":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(statusSubcommand),0):(telemetry.trackCliSubcommandStatus(subcommandOriginal),status(client,args));case"overview":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(overviewSubcommand),0):(telemetry.trackCliSubcommandOverview(subcommandOriginal),overview(client,args));case"diff":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(diffSubcommand),0):(telemetry.trackCliSubcommandDiff(subcommandOriginal),diff(client,args));case"publish":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(publishSubcommand),0):(telemetry.trackCliSubcommandPublish(subcommandOriginal),publish(client,args));case"discard":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(discardSubcommand),0):(telemetry.trackCliSubcommandDiscard(subcommandOriginal),discard(client,args));case"rules":{telemetry.trackCliSubcommandRules(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main5(client,nestedArgs,telemetry)}case"ip-blocks":{telemetry.trackCliSubcommandIpBlocks(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main4(client,nestedArgs,telemetry)}case"system-bypass":{telemetry.trackCliSubcommandSystemBypass(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main(client,nestedArgs,telemetry)}case"attack-mode":{telemetry.trackCliSubcommandAttackMode(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main2(client,nestedArgs,telemetry)}case"system-mitigations":{telemetry.trackCliSubcommandSystemMitigations(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main3(client,nestedArgs,telemetry)}case"alerts":{telemetry.trackCliSubcommandAlerts(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main6(client,nestedArgs,telemetry)}case"persistent-actions":{telemetry.trackCliSubcommandPersistentActions(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main7(client,nestedArgs,telemetry)}case"traffic":{telemetry.trackCliSubcommandTraffic(subcommandOriginal);let nestedArgs=needHelp?[...args,"--help"]:args;return main8(client,nestedArgs,telemetry)}case"bot-management":return needHelp?(telemetry.trackCliFlagHelp("firewall",subcommandOriginal),printHelp(botManagementSubcommand),0):(telemetry.trackCliSubcommandBotManagement(subcommandOriginal),botManagement(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG9)),output_manager_default.print(help(firewallCommand,{stream:client.stderr,columns:client.stderr.columns})),2}}var FlagsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandInspect(actual){this.trackCliSubcommand({subcommand:"inspect",value:actual})}trackCliSubcommandVersions(actual){this.trackCliSubcommand({subcommand:"versions",value:actual})}trackCliSubcommandEvaluations(actual){this.trackCliSubcommand({subcommand:"evaluations",value:actual})}trackCliSubcommandStale(actual){this.trackCliSubcommand({subcommand:"stale",value:actual})}trackCliSubcommandOpen(actual){this.trackCliSubcommand({subcommand:"open",value:actual})}trackCliSubcommandCreate(actual){this.trackCliSubcommand({subcommand:"create",value:actual})}trackCliSubcommandUpdate(actual){this.trackCliSubcommand({subcommand:"update",value:actual})}trackCliSubcommandSet(actual){this.trackCliSubcommand({subcommand:"set",value:actual})}trackCliSubcommandTargeting(actual){this.trackCliSubcommand({subcommand:"targeting",value:actual})}trackCliSubcommandUseTargeting(actual){this.trackCliSubcommand({subcommand:"use-targeting",value:actual})}trackCliSubcommandSplit(actual){this.trackCliSubcommand({subcommand:"split",value:actual})}trackCliSubcommandRollout(actual){this.trackCliSubcommand({subcommand:"rollout",value:actual})}trackCliSubcommandDelete(actual){this.trackCliSubcommand({subcommand:"delete",value:actual})}trackCliSubcommandArchive(actual){this.trackCliSubcommand({subcommand:"archive",value:actual})}trackCliSubcommandUnarchive(actual){this.trackCliSubcommand({subcommand:"unarchive",value:actual})}trackCliSubcommandDisable(actual){this.trackCliSubcommand({subcommand:"disable",value:actual})}trackCliSubcommandEnable(actual){this.trackCliSubcommand({subcommand:"enable",value:actual})}trackCliSubcommandSdkKeys(actual){this.trackCliSubcommand({subcommand:"sdk-keys",value:actual})}trackCliSubcommandConnections(actual){this.trackCliSubcommand({subcommand:"connections",value:actual})}trackCliSubcommandSegments(actual){this.trackCliSubcommand({subcommand:"segments",value:actual})}trackCliSubcommandEntities(actual){this.trackCliSubcommand({subcommand:"entities",value:actual})}trackCliSubcommandLabels(actual){this.trackCliSubcommand({subcommand:"labels",value:actual})}trackCliSubcommandRules(actual){this.trackCliSubcommand({subcommand:"rules",value:actual})}trackCliSubcommandTargets(actual){this.trackCliSubcommand({subcommand:"targets",value:actual})}trackCliSubcommandPrepare(actual){this.trackCliSubcommand({subcommand:"prepare",value:actual})}trackCliSubcommandDatafile(actual){this.trackCliSubcommand({subcommand:"datafile",value:actual})}trackCliSubcommandOverride(actual){this.trackCliSubcommand({subcommand:"override",value:actual})}};var import_chalk42=__toESM(require_source(),1),import_ms=__toESM(require_ms(),1),import_pluralize=__toESM(require_pluralize(),1);function flagUrl(projectId,flagIdOrSlug){return`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags/${encodeURIComponent(flagIdOrSlug)}`}async function fetchFlagForUpdate(client,projectId,flagIdOrSlug){output_manager_default.debug(`Fetching feature flag ${flagIdOrSlug} for project ${projectId} with ETag`);let response=await client.fetch(flagUrl(projectId,flagIdOrSlug),{json:!1}),etag=response.headers.get("etag");if(!etag)throw new Error("Unable to update flag safely because the flag ETag is missing.");return{flag:await response.json(),etag}}async function updateFlag(client,projectId,flagIdOrSlug,request,options){output_manager_default.debug(`Updating feature flag ${flagIdOrSlug} for project ${projectId}`);let url=flagUrl(projectId,flagIdOrSlug);return await client.fetch(url,{method:"PATCH",headers:options?.ifMatch?{"If-Match":options.ifMatch}:void 0,body:request})}var MAX_FLAGS_PAGE_LIMIT=100,MAX_FLAG_VERSIONS_PAGE_LIMIT=100;async function getFlags(client,projectId,options={}){let{state="active",tags,createdBy,maintainerIds,limit,cursor}=options;output_manager_default.debug(`Fetching feature flags for project ${projectId}`);let basePath=`/v2/projects/${encodeURIComponent(projectId)}/feature-flags/flags`,buildQuery=(pageLimit,pageCursor2)=>{let query=new URLSearchParams;query.set("state",state),query.set("limit",String(pageLimit)),pageCursor2&&query.set("cursor",pageCursor2),createdBy&&query.set("createdBy",createdBy);for(let tag of tags??[])query.append("tags",tag);for(let maintainerId of maintainerIds??[])query.append("maintainerIds",maintainerId);return query.toString()};if(limit!==void 0||cursor!==void 0){let pageLimit=Math.min(limit??MAX_FLAGS_PAGE_LIMIT,MAX_FLAGS_PAGE_LIMIT),response=await client.fetch(`${basePath}?${buildQuery(pageLimit,cursor)}`);return{flags:response.data,next:response.pagination?.next??null}}let flags=[],pageCursor;do{let response=await client.fetch(`${basePath}?${buildQuery(MAX_FLAGS_PAGE_LIMIT,pageCursor)}`);flags.push(...response.data),pageCursor=response.pagination?.next??void 0}while(pageCursor);return{flags,next:null}}async function getFlag(client,projectId,flagIdOrSlug){output_manager_default.debug(`Fetching feature flag ${flagIdOrSlug} for project ${projectId}`);let url=flagUrl(projectId,flagIdOrSlug);return await client.fetch(url)}async function getFlagSettings(client,projectId){return output_manager_default.debug(`Fetching feature flag settings for project ${projectId}`),await client.fetch(flagSettingsUrl(projectId))}async function updateFlagSettings(client,projectId,request){return output_manager_default.debug(`Updating feature flag settings for project ${projectId}`),client.fetch(flagSettingsUrl(projectId),{method:"PATCH",body:request})}function flagSettingsUrl(projectId){return`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/settings`}async function getFlagVersions(client,projectId,flagIdOrSlug,options={}){output_manager_default.debug(`Fetching feature flag versions for ${flagIdOrSlug} in project ${projectId}`);let query=new URLSearchParams;query.set("withMetadata","true"),options.environment&&query.set("environment",options.environment),options.limit!==void 0&&query.set("limit",String(options.limit)),options.cursor&&query.set("cursor",options.cursor);let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags/${encodeURIComponent(flagIdOrSlug)}/versions?${query.toString()}`,response=await client.fetch(url),next=response.pagination?.next??(response.pagination?.hasNext?response.pagination.cursor:null)??null;return{versions:response.versions,next}}var FlagsLsTelemetryClient=class extends TelemetryClient{trackCliOptionState(state){state&&this.trackCliOption({option:"state",value:state})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}trackCliOptionTag(tags){tags&&tags.length>0&&this.trackCliOption({option:"tag",value:this.redactedValue})}trackCliOptionCreatedBy(createdBy){createdBy&&this.trackCliOption({option:"created-by",value:this.redactedValue})}trackCliOptionMaintainer(maintainerIds){maintainerIds&&maintainerIds.length>0&&this.trackCliOption({option:"maintainer",value:this.redactedValue})}trackCliOptionMaintainerId(maintainerIds){maintainerIds&&maintainerIds.length>0&&this.trackCliOption({option:"maintainer-id",value:this.redactedValue})}trackCliOptionLimit(limit){limit!==void 0&&this.trackCliOption({option:"limit",value:String(limit)})}trackCliOptionNext(next){next&&this.trackCliOption({option:"next",value:this.redactedValue})}};async function ls(client,argv){let telemetryClient=new FlagsLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(listSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,state=flags["--state"]||"active",tags=flags["--tag"],createdBy=flags["--created-by"],limit=flags["--limit"],next=flags["--next"],json=flags["--json"],projectName=getProjectNameFromFlags(flags),maintainer=getRenamedOption(flags,"--maintainer","--maintainer-id",{json});if(telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionState(state),telemetryClient.trackCliOptionTag(tags),telemetryClient.trackCliOptionCreatedBy(createdBy),telemetryClient.trackCliOptionMaintainer(flags["--maintainer"]),telemetryClient.trackCliOptionMaintainerId(flags["--maintainer-id"]),telemetryClient.trackCliOptionLimit(limit),telemetryClient.trackCliOptionNext(next),telemetryClient.trackCliFlagJson(json),"error"in maintainer)return reportRenamedOptionError(client,maintainer.error,{json});let maintainerIds=maintainer.value;if(limit!==void 0&&(!Number.isInteger(limit)||limit<1||limit>MAX_FLAGS_PAGE_LIMIT))return output_manager_default.error(`The --limit option must be an integer between 1 and ${MAX_FLAGS_PAGE_LIMIT}.`),2;let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),lsStamp=stamp_default();output_manager_default.spinner(`Fetching ${state} feature flags for ${projectSlugLink}`);try{let{flags:flagsList,next:nextCursor}=await getFlags(client,project.id,{state,tags,createdBy,maintainerIds,limit,cursor:next});if(output_manager_default.stopSpinner(),json)outputJson2(client,flagsList,nextCursor,[maintainer.warning]);else if(flagsList.length===0)output_manager_default.log(`No ${state} feature flags found for ${projectSlugLink} ${import_chalk42.default.gray(lsStamp())}`);else if(output_manager_default.log(`${(0,import_pluralize.default)("feature flag",flagsList.length,!0)} found for ${projectSlugLink} ${import_chalk42.default.gray(lsStamp())}`),printFlagsTable(flagsList),nextCursor){let nextCmd=buildNextPageCommand(flags,tags,maintainerIds,nextCursor);output_manager_default.print(`
|
|
205
205
|
`),printNextPageCommand(getCommandNamePlain(nextCmd))}}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function buildNextPageCommand(flags,tags,maintainerIds,nextCursor){let baseFlags=getCommandFlags(flags,["_","--tag","--maintainer","--maintainer-id","--next","--json"]),repeatable=[...(tags??[]).map(tag=>`--tag ${quoteArg(tag)}`),...(maintainerIds??[]).map(id=>`--maintainer ${quoteArg(id)}`)],suffix=repeatable.length>0?` ${repeatable.join(" ")}`:"";return`flags ls${baseFlags}${suffix} --next ${nextCursor}`}function outputJson2(client,flags,next,warnings){let jsonOutput={flags:flags.map(flag=>({id:flag.id,slug:flag.slug,description:flag.description??null,kind:flag.kind,state:flag.state,variants:flag.variants,createdAt:flag.createdAt,updatedAt:flag.updatedAt})),pagination:{next}};client.stdout.write(`${JSON.stringify(withWarnings(jsonOutput,warnings),null,2)}
|
|
206
206
|
`)}function printFlagsTable(flags){let headers=["Name","Kind","State","Variants","Updated"],now=Date.now(),rows=flags.map(flag=>[import_chalk42.default.bold(flag.slug),flag.kind,flag.state==="active"?import_chalk42.default.green(flag.state):import_chalk42.default.gray(flag.state),String(flag.variants.length),(0,import_ms.default)(now-flag.updatedAt)+" ago"]),table2=formatTable(headers,["l","l","l","r","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
207
207
|
${table2}
|
|
@@ -250,7 +250,7 @@ Feature flag ${import_chalk47.default.bold(flag.slug)} for ${projectSlugLink}
|
|
|
250
250
|
`)}}output_manager_default.print(`
|
|
251
251
|
`)}function getSortedEnvironmentEntries(flag,environments){let envOrder=["production","preview","development"],selectedEnvironments=environments?new Set(environments):void 0;return Object.entries(flag.environments).filter(([envName])=>selectedEnvironments?selectedEnvironments.has(envName):!0).sort(([a],[b])=>{let aIndex=envOrder.indexOf(a),bIndex=envOrder.indexOf(b);return aIndex===-1&&bIndex===-1?a.localeCompare(b):aIndex===-1?1:bIndex===-1?-1:aIndex-bIndex})}function hasCustomConfigurationEnabled(envConfig){return!!(envConfig.targets&&Object.keys(envConfig.targets).length>0)||envConfig.rules.length>0||envConfig.fallthrough.type==="split"||envConfig.fallthrough.type==="rollout"||envConfig.fallthrough.type==="experiment"}async function inspect5(client,argv){let telemetryClient=new FlagsInspectTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(inspectSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,json=flags["--json"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error(`Missing required argument: flag. Usage: ${getCommandName("flags inspect <flag>")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagJson(json);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name);try{if(json){let flag2=await getFlag(client,project.id,flagArg);return client.stdout.write(`${JSON.stringify({flag:flag2},null,2)}
|
|
252
252
|
`),0}let[flag,settings]=await Promise.all([getFlag(client,project.id,flagArg),getFlagSettings(client,project.id)]);printFlagDetails({flag,settings,projectSlugLink,orgSlug:org.slug,projectName:project.name})}catch(err){return printError(err),1}return 0}var import_chalk49=__toESM(require_source(),1),import_pluralize3=__toESM(require_pluralize(),1);var FlagsVersionsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"list",value:actual})}trackCliSubcommandDiff(actual){this.trackCliSubcommand({subcommand:"diff",value:actual})}trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionLimit(limit){limit!==void 0&&this.trackCliOption({option:"limit",value:String(limit)})}trackCliOptionNext(next){next&&this.trackCliOption({option:"next",value:this.redactedValue})}trackCliOptionCursor(cursor){cursor&&this.trackCliOption({option:"cursor",value:this.redactedValue})}trackCliOptionRevision(revision){revision!==void 0&&this.trackCliOption({option:"revision",value:String(revision)})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}};var import_chalk48=__toESM(require_source(),1),import_fast_deep_equal2=__toESM(require_fast_deep_equal(),1);var ENVIRONMENT_ORDER=["production","preview","development"];function normalizeVersionDataForDiff(data){return{...data,permanent:data.permanent??!1,environments:Object.fromEntries(Object.entries(data.environments).map(([environment,config])=>{let diffConfig={...config};return delete diffConfig.revision,[environment,diffConfig]}))}}function diffVersionData(before,after){return diffValues(normalizeVersionDataForDiff(before),normalizeVersionDataForDiff(after))}function formatVersionDataDiff(before,after){let beforeData=normalizeVersionDataForDiff(before),afterData=normalizeVersionDataForDiff(after),lines=[];return appendGeneralChanges(lines,beforeData,afterData),appendEnvironmentChanges(lines,beforeData,afterData),appendUnknownChanges(lines,beforeData,afterData),lines.join(`
|
|
253
|
-
`)}function appendGeneralChanges(lines,before,after){let section=[];appendScalarChange(section,"Description",before.description,after.description),appendScalarChange(section,"State",before.state,after.state),appendScalarChange(section,"Permanent",before.permanent,after.permanent),appendListChange(section,"Tags",before.tags??[],after.tags??[]),appendListChange(section,"Maintainers",before.maintainerIds??[],after.maintainerIds??[]),appendScalarChange(section,"Seed",before.seed,after.seed),appendVariantChanges(section,before.variants,after.variants),appendSection(lines,"General",section)}function appendEnvironmentChanges(lines,before,after){let environments=new Set([...Object.keys(before.environments),...Object.keys(after.environments)]);for(let environment of Array.from(environments).sort(sortEnvironments)){let beforeEnvironment=before.environments[environment],afterEnvironment=after.environments[environment],section=[];if(!beforeEnvironment&&afterEnvironment){section.push(diffLine("+","Environment added",4)),appendEnvironmentSummary(section,afterEnvironment,after.variants,6),appendSection(lines,formatEnvironmentName(environment),section);continue}if(beforeEnvironment&&!afterEnvironment){section.push(diffLine("-","Environment removed",4)),appendEnvironmentSummary(section,beforeEnvironment,before.variants,6),appendSection(lines,formatEnvironmentName(environment),section);continue}!beforeEnvironment||!afterEnvironment||(0,import_fast_deep_equal2.default)(beforeEnvironment,afterEnvironment)||(appendScalarChange(section,"Status",formatEnvironmentStatus(beforeEnvironment,before.variants),formatEnvironmentStatus(afterEnvironment,after.variants)),appendReuseChange(section,beforeEnvironment,afterEnvironment),appendOutcomeChange(section,"Paused outcome",beforeEnvironment.pausedOutcome,afterEnvironment.pausedOutcome,before.variants,after.variants),appendOutcomeChange(section,"Fallthrough",beforeEnvironment.fallthrough,afterEnvironment.fallthrough,before.variants,after.variants),appendRuleChanges(section,beforeEnvironment.rules??[],afterEnvironment.rules??[],before.variants,after.variants),appendTargetChanges(section,beforeEnvironment.targets,afterEnvironment.targets,before.variants,after.variants),appendUnknownEnvironmentChanges(section,beforeEnvironment,afterEnvironment),appendSection(lines,formatEnvironmentName(environment),section))}}function appendUnknownChanges(lines,before,after){let beforeUnknown=omitKeys(before,["description","environments","maintainerIds","permanent","seed","state","tags","variants"]),afterUnknown=omitKeys(after,["description","environments","maintainerIds","permanent","seed","state","tags","variants"]),changes=diffValues(beforeUnknown,afterUnknown);changes.length>0&&appendFallbackChanges(lines,"Other",changes)}function appendUnknownEnvironmentChanges(section,before,after){let beforeUnknown=omitKeys(before,["active","fallthrough","pausedOutcome","reuse","rules","targets"]),afterUnknown=omitKeys(after,["active","fallthrough","pausedOutcome","reuse","rules","targets"]),changes=diffValues(beforeUnknown,afterUnknown);changes.length>0&&(section.push(line(import_chalk48.default.bold("Other"),4)),appendFallbackChangeLines(section,changes,6))}function appendVariantChanges(section,beforeVariants,afterVariants){if((0,import_fast_deep_equal2.default)(beforeVariants,afterVariants))return;let beforeById=new Map(beforeVariants.map(variant=>[variant.id,variant])),afterById=new Map(afterVariants.map(variant=>[variant.id,variant])),variantLines=[],beforeOrder=beforeVariants.map(variant=>variant.id),afterOrder=afterVariants.map(variant=>variant.id),commonBeforeOrder=beforeOrder.filter(id=>afterById.has(id)),commonAfterOrder=afterOrder.filter(id=>beforeById.has(id));commonBeforeOrder.length>1&&!(0,import_fast_deep_equal2.default)(commonBeforeOrder,commonAfterOrder)&&(variantLines.push(line(import_chalk48.default.bold("Order"),6)),variantLines.push(diffLine("-",formatItemOrder(beforeOrder),8)),variantLines.push(diffLine("+",formatItemOrder(afterOrder),8)));for(let id of Array.from(new Set([...beforeById.keys(),...afterById.keys()])).sort()){let before=beforeById.get(id),after=afterById.get(id);if(!before&&after){variantLines.push(diffLine("+",formatVariantSummary(after),6));continue}if(before&&!after){variantLines.push(diffLine("-",formatVariantSummary(before),6));continue}!before||!after||(0,import_fast_deep_equal2.default)(before,after)||(variantLines.push(diffLine("~",formatVariantChangeTitle(before,after),6)),appendScalarChange(variantLines,"Value",before.value,after.value,8),appendScalarChange(variantLines,"Label",before.label,after.label,8),appendScalarChange(variantLines,"Description",before.description,after.description,8))}variantLines.length>0&&(section.push(line(import_chalk48.default.bold("Variants"),4)),section.push(...variantLines))}function appendRuleChanges(section,beforeRules,afterRules,beforeVariants,afterVariants){if((0,import_fast_deep_equal2.default)(beforeRules,afterRules))return;let beforeById=new Map(beforeRules.map(rule=>[rule.id,rule])),afterById=new Map(afterRules.map(rule=>[rule.id,rule])),ruleLines=[],beforeOrder=beforeRules.map(rule=>rule.id),afterOrder=afterRules.map(rule=>rule.id),commonBeforeOrder=beforeOrder.filter(id=>afterById.has(id)),commonAfterOrder=afterOrder.filter(id=>beforeById.has(id));commonBeforeOrder.length>1&&!(0,import_fast_deep_equal2.default)(commonBeforeOrder,commonAfterOrder)&&(ruleLines.push(line(import_chalk48.default.bold("Order"),6)),ruleLines.push(diffLine("-",formatItemOrder(beforeOrder),8)),ruleLines.push(diffLine("+",formatItemOrder(afterOrder),8)));for(let id of Array.from(new Set([...beforeById.keys(),...afterById.keys()])).sort()){let before=beforeById.get(id),after=afterById.get(id);if(!before&&after){ruleLines.push(diffLine("+",formatRuleTitle(after.id,afterOrder.indexOf(after.id),afterOrder),6)),ruleLines.push(...formatRuleDetails(after,afterVariants,8));continue}if(before&&!after){ruleLines.push(diffLine("-",formatRuleTitle(before.id,beforeOrder.indexOf(before.id),beforeOrder),6)),ruleLines.push(...formatRuleDetails(before,beforeVariants,8));continue}!before||!after||(0,import_fast_deep_equal2.default)(before,after)||(ruleLines.push(diffLine("~",after.id,6)),appendConditionChanges(ruleLines,before.conditions,after.conditions,8),appendOutcomeChange(ruleLines,"Serve",before.outcome,after.outcome,beforeVariants,afterVariants,8,!1))}ruleLines.length>0&&(section.push(line(import_chalk48.default.bold("Rules"),4)),section.push(...ruleLines))}function appendConditionChanges(lines,beforeConditions,afterConditions,indent2){let before=beforeConditions.map(condition=>({condition,key:JSON.stringify(condition)})),after=afterConditions.map(condition=>({condition,key:JSON.stringify(condition)})),removed=before.filter(beforeCondition=>!after.some(afterCondition=>afterCondition.key===beforeCondition.key)),added=after.filter(afterCondition=>!before.some(beforeCondition=>beforeCondition.key===afterCondition.key));if(!(removed.length===0&&added.length===0)){lines.push(line(import_chalk48.default.bold("Conditions"),indent2));for(let{condition}of removed)appendConditionDiff(lines,"-",condition,indent2+2);for(let{condition}of added)appendConditionDiff(lines,"+",condition,indent2+2)}}function appendTargetChanges(section,beforeTargets,afterTargets,beforeVariants,afterVariants){if((0,import_fast_deep_equal2.default)(beforeTargets,afterTargets))return;let before=formatTargets(beforeTargets,beforeVariants),after=formatTargets(afterTargets,afterVariants);(0,import_fast_deep_equal2.default)(before,after)&&(before=formatTargets(beforeTargets,beforeVariants,!0),after=formatTargets(afterTargets,afterVariants,!0)),appendStringSetChange(section,"Targeting",before,after)}function appendOutcomeChange(lines,label,before,after,beforeVariants,afterVariants,indent2=4,includeServe=!0){if((0,import_fast_deep_equal2.default)(before,after))return;let beforeSummary=before?formatOutcome(before,beforeVariants,includeServe):void 0,afterSummary=after?formatOutcome(after,afterVariants,includeServe):void 0;(0,import_fast_deep_equal2.default)(beforeSummary,afterSummary)&&(beforeSummary=before?formatOutcome(before,beforeVariants,includeServe,!0):void 0,afterSummary=after?formatOutcome(after,afterVariants,includeServe,!0):void 0),appendScalarChange(lines,label,beforeSummary,afterSummary,indent2)}function appendReuseChange(section,before,after){appendScalarChange(section,"Reuse",formatReuse(before.reuse),formatReuse(after.reuse))}function appendEnvironmentSummary(lines,environment,variants,indent2){if(lines.push(line(`${import_chalk48.default.dim("Status:")} ${formatEnvironmentStatus(environment,variants)}`,indent2)),environment.reuse?.active){lines.push(line(`${import_chalk48.default.dim("Reuse:")} ${formatReuse(environment.reuse)}`,indent2));return}if(!environment.active&&environment.pausedOutcome){lines.push(line(`${import_chalk48.default.dim("Paused outcome:")} ${formatOutcome(environment.pausedOutcome,variants)}`,indent2));return}lines.push(line(`${import_chalk48.default.dim("Fallthrough:")} ${formatOutcome(environment.fallthrough,variants)}`,indent2));let ruleCount=environment.rules?.length??0;ruleCount>0&&lines.push(line(`${import_chalk48.default.dim("Rules:")} ${import_chalk48.default.bold(String(ruleCount))}`,indent2));let targets2=formatTargets(environment.targets,variants);targets2.length>0&&lines.push(line(`${import_chalk48.default.dim("Targets:")} ${import_chalk48.default.bold(String(targets2.length))}`,indent2))}function appendScalarChange(lines,label,before,after,indent2=4){(0,import_fast_deep_equal2.default)(before,after)||(lines.push(line(import_chalk48.default.bold(label),indent2)),lines.push(diffLine("-",formatScalarValue(before),indent2+2)),lines.push(diffLine("+",formatScalarValue(after),indent2+2)))}function appendListChange(lines,label,before,after,indent2=4){appendStringSetChange(lines,label,before,after,indent2)}function appendStringSetChange(lines,label,before,after,indent2=4){let removed=before.filter(item=>!after.includes(item)).sort(),added=after.filter(item=>!before.includes(item)).sort();if(!(removed.length===0&&added.length===0)){lines.push(line(import_chalk48.default.bold(label),indent2));for(let item of removed)lines.push(diffLine("-",item,indent2+2));for(let item of added)lines.push(diffLine("+",item,indent2+2))}}function appendSection(lines,title,section){section.length!==0&&(lines.length>0&&lines.push(""),lines.push(line(import_chalk48.default.bold(title),2)),lines.push(...section))}function appendFallbackChanges(lines,title,changes){let section=[];appendFallbackChangeLines(section,changes,4),appendSection(lines,title,section)}function appendFallbackChangeLines(lines,changes,indent2){for(let change of changes)lines.push(line(import_chalk48.default.bold(change.path||"value"),indent2)),change.action!=="added"&&lines.push(diffLine("-",formatScalarValue(change.before),indent2+2)),change.action!=="removed"&&lines.push(diffLine("+",formatScalarValue(change.after),indent2+2))}function formatRuleDetails(rule,variants,indent2){let lines=[];lines.push(line(`${import_chalk48.default.dim("\u2192")} ${formatOutcome(rule.outcome,variants,!1)}`,indent2));for(let condition of rule.conditions)appendConditionDetails(lines,condition,indent2+2);return lines}function appendConditionDetails(lines,condition,indent2){let{text,listItems}=formatFlagCondition(condition,void 0);lines.push(line(`${import_chalk48.default.dim("if")} ${text}`,indent2));for(let item of listItems??[])lines.push(line(`${import_chalk48.default.dim("-")} ${item}`,indent2+3))}function appendConditionDiff(lines,marker,condition,indent2){let{text,listItems}=formatFlagCondition(condition,void 0);lines.push(diffLine(marker,`${import_chalk48.default.dim("if")} ${text}`,indent2));for(let item of listItems??[])lines.push(line(`${import_chalk48.default.dim("-")} ${item}`,indent2+3))}function formatTargets(targets2,variants,includeVariantId=!1){let lines=[];for(let[variantId,entityKinds]of Object.entries(targets2??{}))for(let[entityKind,attributes]of Object.entries(entityKinds))for(let[attribute,values]of Object.entries(attributes))for(let target of values){let variant=variants.find(candidate=>candidate.id===variantId);lines.push(`${import_chalk48.default.dim(`${entityKind}.${attribute}:`)} ${formatTargetValue(target)} ${import_chalk48.default.dim("\u2192")} ${formatFlagVariantSummary(variant,variantId,includeVariantId)}`)}return lines.sort()}function formatTargetValue(target){return target.note?`${target.value} ${import_chalk48.default.gray(`(${target.note})`)}`:target.value}function formatEnvironmentStatus(environment,variants){return environment.active?import_chalk48.default.green("active"):environment.pausedOutcome?`${import_chalk48.default.gray("paused")}, ${import_chalk48.default.dim("serving")} ${formatOutcome(environment.pausedOutcome,variants,!1)}`:import_chalk48.default.gray("paused")}function formatReuse(reuse){return reuse?.active?`${import_chalk48.default.dim("reusing")} ${import_chalk48.default.cyan(formatEnvironmentName(reuse.environment))}`:import_chalk48.default.gray("none")}function formatOutcome(outcome,variants,includeServe=!0,includeVariantId=!1){let prefix=includeServe?`${import_chalk48.default.dim("Serve")} `:"",summary=formatFlagOutcome(outcome,variants,includeVariantId);if(outcome.type==="split"){let defaultVariant=variants.find(variant=>variant.id===outcome.defaultVariantId);return`${prefix}${summary}; ${import_chalk48.default.dim("by")} ${formatBucketingBase(outcome.base)}; ${import_chalk48.default.dim("Fallback:")} ${formatFlagVariantSummary(defaultVariant,outcome.defaultVariantId,includeVariantId)}`}return outcome.type==="rollout"?`${prefix}${summary}; ${import_chalk48.default.dim("by")} ${formatBucketingBase(outcome.base)}; ${import_chalk48.default.dim("Starts:")} ${formatTimestamp(outcome.startTimestamp)}`:`${prefix}${summary}`}function formatBucketingBase(base){return`${base.kind}.${base.attribute}`}function formatTimestamp(timestamp){let date=new Date(timestamp);return Number.isNaN(date.getTime())?String(timestamp):date.toISOString()}function formatItemOrder(ids){return ids.join(` ${import_chalk48.default.dim("\u2192")} `)}function formatRuleTitle(ruleId,index,ruleOrder){return ruleOrder.length===1?ruleId:`${ruleId} ${import_chalk48.default.dim(`(position ${index+1})`)}`}function formatVariantChangeTitle(before,after){let label=after.label??before.label;return label?`${import_chalk48.default.bold(label)} (${import_chalk48.default.dim(after.id)})`:after.id}function formatVariantSummary(variant){let details=[`${import_chalk48.default.dim("id:")} ${variant.id}`,`${import_chalk48.default.dim("value:")} ${import_chalk48.default.bold(formatVariantValue(variant.value))}`];return variant.label&&details.unshift(import_chalk48.default.bold(variant.label)),details.join(", ")}function formatScalarValue(value){return value==null||value===""?"-":typeof value=="string"?value:typeof value=="boolean"?value?"true":"false":JSON.stringify(sortObjectKeys(value),null,2)}function formatEnvironmentName(environment){return environment.charAt(0).toUpperCase()+environment.slice(1)}function line(text,indent2){return`${" ".repeat(indent2)}${text}`}function diffLine(marker,text,indent2){let color=marker==="+"?import_chalk48.default.green:marker==="-"?import_chalk48.default.red:import_chalk48.default.yellow;return line(color(`${marker} ${text}`),indent2)}function sortEnvironments(a,b){let aIndex=ENVIRONMENT_ORDER.indexOf(a),bIndex=ENVIRONMENT_ORDER.indexOf(b);return aIndex===-1&&bIndex===-1?a.localeCompare(b):aIndex===-1?1:bIndex===-1?-1:aIndex-bIndex}function omitKeys(value,keys){let omitted={...value};for(let key of keys)delete omitted[key];return omitted}function diffValues(before,after,path=""){return(0,import_fast_deep_equal2.default)(before,after)?[]:isPlainObject(before)&&isPlainObject(after)?Array.from(new Set([...Object.keys(before),...Object.keys(after)])).sort().flatMap(key=>diffValues(before[key],after[key],joinPath(path,key))):[{path,action:before===void 0?"added":after===void 0?"removed":"changed",before,after}]}function isPlainObject(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function joinPath(path,key){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)?path?`${path}.${key}`:key:`${path}[${JSON.stringify(key)}]`}function sortObjectKeys(value){return Array.isArray(value)?value.map(sortObjectKeys):isPlainObject(value)?Object.fromEntries(Object.keys(value).sort().map(key=>[key,sortObjectKeys(value[key])])):value}var COMMAND_CONFIG10={list:getCommandAliases(versionsListSubcommand),diff:getCommandAliases(versionsDiffSubcommand)};async function versions(client,argv){let telemetryClient=new FlagsVersionsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(versionsSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG10),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetryClient.trackCliFlagHelp("flags versions",subcommandOriginal),output_manager_default.print(help(parsedArgs.args.length>0?versionsListSubcommand:versionsSubcommand,{parent:parsedArgs.args.length>0?getVersionsHelpParent():flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:getVersionsHelpParent(),columns:client.stderr.columns}))}switch(subcommand){case"diff":return needHelp?(telemetryClient.trackCliFlagHelp("flags versions",subcommandOriginal),printHelp(versionsDiffSubcommand),0):(telemetryClient.trackCliSubcommandDiff(subcommandOriginal),diffVersions(client,args,telemetryClient));case"list":return needHelp?(telemetryClient.trackCliFlagHelp("flags versions",subcommandOriginal),printHelp(versionsListSubcommand),0):(telemetryClient.trackCliSubcommandList(subcommandOriginal),listVersions(client,args,telemetryClient));default:return telemetryClient.trackCliSubcommandList("default"),listVersions(client,argv,telemetryClient)}}async function listVersions(client,argv,telemetryClient){let parsedArgs,flagsSpecification=getFlagsSpecification(versionsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],limit=flags["--limit"],cursor=flags["--next"]??flags["--cursor"],json=flags["--json"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error(`Missing required argument: flag. Usage: ${getCommandName("flags versions <flag>")}`),2;if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionLimit(limit),telemetryClient.trackCliOptionNext(flags["--next"]),telemetryClient.trackCliOptionCursor(flags["--cursor"]),flags["--cursor"]!==void 0&&warnDeprecatedOption(client.argv,"--cursor","--next"),telemetryClient.trackCliFlagJson(json),limit!==void 0&&(!Number.isInteger(limit)||limit<1||limit>MAX_FLAG_VERSIONS_PAGE_LIMIT))return output_manager_default.error(`The --limit option must be an integer between 1 and ${MAX_FLAG_VERSIONS_PAGE_LIMIT}.`),2;let link=await resolveLinkedProject(client,projectName);if(typeof link=="number")return link;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),versionsStamp=stamp_default(),environmentLabel=environment?` in ${environment}`:"";output_manager_default.spinner(`Fetching version history for ${import_chalk49.default.bold(flagArg)}${environmentLabel} in ${projectSlugLink}`);try{let{versions:versionList,next}=await getFlagVersions(client,project.id,flagArg,{environment,limit,cursor});if(output_manager_default.stopSpinner(),json)outputJson4(client,versionList,next);else if(versionList.length===0)output_manager_default.log(`No versions found for ${import_chalk49.default.bold(flagArg)}${environmentLabel} in ${projectSlugLink} ${import_chalk49.default.gray(versionsStamp())}`);else if(output_manager_default.log(`${(0,import_pluralize3.default)("version",versionList.length,!0)} found for ${import_chalk49.default.bold(flagArg)}${environmentLabel} in ${projectSlugLink} ${import_chalk49.default.gray(versionsStamp())}`),printVersionsTable(versionList),next){let nextCmd=buildNextPageCommand3(flagArg,flags,next);output_manager_default.print(`
|
|
253
|
+
`)}function appendGeneralChanges(lines,before,after){let section=[];appendScalarChange(section,"Description",before.description,after.description),appendScalarChange(section,"State",before.state,after.state),appendScalarChange(section,"Permanent",before.permanent,after.permanent),appendListChange(section,"Tags",before.tags??[],after.tags??[]),appendListChange(section,"Maintainers",before.maintainerIds??[],after.maintainerIds??[]),appendScalarChange(section,"Seed",before.seed,after.seed),appendVariantChanges(section,before.variants,after.variants),appendSection(lines,"General",section)}function appendEnvironmentChanges(lines,before,after){let environments=new Set([...Object.keys(before.environments),...Object.keys(after.environments)]);for(let environment of Array.from(environments).sort(sortEnvironments)){let beforeEnvironment=before.environments[environment],afterEnvironment=after.environments[environment],section=[];if(!beforeEnvironment&&afterEnvironment){section.push(diffLine("+","Environment added",4)),appendEnvironmentSummary(section,afterEnvironment,after.variants,6),appendSection(lines,formatEnvironmentName(environment),section);continue}if(beforeEnvironment&&!afterEnvironment){section.push(diffLine("-","Environment removed",4)),appendEnvironmentSummary(section,beforeEnvironment,before.variants,6),appendSection(lines,formatEnvironmentName(environment),section);continue}!beforeEnvironment||!afterEnvironment||(0,import_fast_deep_equal2.default)(beforeEnvironment,afterEnvironment)||(appendScalarChange(section,"Status",formatEnvironmentStatus(beforeEnvironment,before.variants),formatEnvironmentStatus(afterEnvironment,after.variants)),appendReuseChange(section,beforeEnvironment,afterEnvironment),appendOutcomeChange(section,"Paused outcome",beforeEnvironment.pausedOutcome,afterEnvironment.pausedOutcome,before.variants,after.variants),appendOutcomeChange(section,"Fallthrough",beforeEnvironment.fallthrough,afterEnvironment.fallthrough,before.variants,after.variants),appendRuleChanges(section,beforeEnvironment.rules??[],afterEnvironment.rules??[],before.variants,after.variants),appendTargetChanges(section,beforeEnvironment.targets,afterEnvironment.targets,before.variants,after.variants),appendUnknownEnvironmentChanges(section,beforeEnvironment,afterEnvironment),appendSection(lines,formatEnvironmentName(environment),section))}}function appendUnknownChanges(lines,before,after){let beforeUnknown=omitKeys(before,["description","environments","maintainerIds","permanent","seed","state","tags","variants"]),afterUnknown=omitKeys(after,["description","environments","maintainerIds","permanent","seed","state","tags","variants"]),changes=diffValues(beforeUnknown,afterUnknown);changes.length>0&&appendFallbackChanges(lines,"Other",changes)}function appendUnknownEnvironmentChanges(section,before,after){let beforeUnknown=omitKeys(before,["active","fallthrough","pausedOutcome","reuse","rules","targets"]),afterUnknown=omitKeys(after,["active","fallthrough","pausedOutcome","reuse","rules","targets"]),changes=diffValues(beforeUnknown,afterUnknown);changes.length>0&&(section.push(line(import_chalk48.default.bold("Other"),4)),appendFallbackChangeLines(section,changes,6))}function appendVariantChanges(section,beforeVariants,afterVariants){if((0,import_fast_deep_equal2.default)(beforeVariants,afterVariants))return;let beforeById=new Map(beforeVariants.map(variant=>[variant.id,variant])),afterById=new Map(afterVariants.map(variant=>[variant.id,variant])),variantLines=[],beforeOrder=beforeVariants.map(variant=>variant.id),afterOrder=afterVariants.map(variant=>variant.id),commonBeforeOrder=beforeOrder.filter(id=>afterById.has(id)),commonAfterOrder=afterOrder.filter(id=>beforeById.has(id));commonBeforeOrder.length>1&&!(0,import_fast_deep_equal2.default)(commonBeforeOrder,commonAfterOrder)&&(variantLines.push(line(import_chalk48.default.bold("Order"),6)),variantLines.push(diffLine("-",formatItemOrder(beforeOrder),8)),variantLines.push(diffLine("+",formatItemOrder(afterOrder),8)));for(let id of Array.from(new Set([...beforeById.keys(),...afterById.keys()])).sort()){let before=beforeById.get(id),after=afterById.get(id);if(!before&&after){variantLines.push(diffLine("+",formatVariantSummary(after),6));continue}if(before&&!after){variantLines.push(diffLine("-",formatVariantSummary(before),6));continue}!before||!after||(0,import_fast_deep_equal2.default)(before,after)||(variantLines.push(diffLine("~",formatVariantChangeTitle(before,after),6)),appendScalarChange(variantLines,"Value",before.value,after.value,8),appendScalarChange(variantLines,"Label",before.label,after.label,8),appendScalarChange(variantLines,"Description",before.description,after.description,8))}variantLines.length>0&&(section.push(line(import_chalk48.default.bold("Variants"),4)),section.push(...variantLines))}function appendRuleChanges(section,beforeRules,afterRules,beforeVariants,afterVariants){if((0,import_fast_deep_equal2.default)(beforeRules,afterRules))return;let beforeById=new Map(beforeRules.map(rule=>[rule.id,rule])),afterById=new Map(afterRules.map(rule=>[rule.id,rule])),ruleLines=[],beforeOrder=beforeRules.map(rule=>rule.id),afterOrder=afterRules.map(rule=>rule.id),commonBeforeOrder=beforeOrder.filter(id=>afterById.has(id)),commonAfterOrder=afterOrder.filter(id=>beforeById.has(id));commonBeforeOrder.length>1&&!(0,import_fast_deep_equal2.default)(commonBeforeOrder,commonAfterOrder)&&(ruleLines.push(line(import_chalk48.default.bold("Order"),6)),ruleLines.push(diffLine("-",formatItemOrder(beforeOrder),8)),ruleLines.push(diffLine("+",formatItemOrder(afterOrder),8)));for(let id of Array.from(new Set([...beforeById.keys(),...afterById.keys()])).sort()){let before=beforeById.get(id),after=afterById.get(id);if(!before&&after){ruleLines.push(diffLine("+",formatRuleTitle(after.id,afterOrder.indexOf(after.id),afterOrder),6)),ruleLines.push(...formatRuleDetails(after,afterVariants,8));continue}if(before&&!after){ruleLines.push(diffLine("-",formatRuleTitle(before.id,beforeOrder.indexOf(before.id),beforeOrder),6)),ruleLines.push(...formatRuleDetails(before,beforeVariants,8));continue}!before||!after||(0,import_fast_deep_equal2.default)(before,after)||(ruleLines.push(diffLine("~",after.id,6)),appendConditionChanges(ruleLines,before.conditions,after.conditions,8),appendOutcomeChange(ruleLines,"Serve",before.outcome,after.outcome,beforeVariants,afterVariants,8,!1))}ruleLines.length>0&&(section.push(line(import_chalk48.default.bold("Rules"),4)),section.push(...ruleLines))}function appendConditionChanges(lines,beforeConditions,afterConditions,indent2){let before=beforeConditions.map(condition=>({condition,key:JSON.stringify(condition)})),after=afterConditions.map(condition=>({condition,key:JSON.stringify(condition)})),removed=before.filter(beforeCondition=>!after.some(afterCondition=>afterCondition.key===beforeCondition.key)),added=after.filter(afterCondition=>!before.some(beforeCondition=>beforeCondition.key===afterCondition.key));if(!(removed.length===0&&added.length===0)){lines.push(line(import_chalk48.default.bold("Conditions"),indent2));for(let{condition}of removed)appendConditionDiff(lines,"-",condition,indent2+2);for(let{condition}of added)appendConditionDiff(lines,"+",condition,indent2+2)}}function appendTargetChanges(section,beforeTargets,afterTargets,beforeVariants,afterVariants){if((0,import_fast_deep_equal2.default)(beforeTargets,afterTargets))return;let before=formatTargets(beforeTargets,beforeVariants),after=formatTargets(afterTargets,afterVariants);(0,import_fast_deep_equal2.default)(before,after)&&(before=formatTargets(beforeTargets,beforeVariants,!0),after=formatTargets(afterTargets,afterVariants,!0)),appendStringSetChange(section,"Targeting",before,after)}function appendOutcomeChange(lines,label,before,after,beforeVariants,afterVariants,indent2=4,includeServe=!0){if((0,import_fast_deep_equal2.default)(before,after))return;let beforeSummary=before?formatOutcome(before,beforeVariants,includeServe):void 0,afterSummary=after?formatOutcome(after,afterVariants,includeServe):void 0;(0,import_fast_deep_equal2.default)(beforeSummary,afterSummary)&&(beforeSummary=before?formatOutcome(before,beforeVariants,includeServe,!0):void 0,afterSummary=after?formatOutcome(after,afterVariants,includeServe,!0):void 0),appendScalarChange(lines,label,beforeSummary,afterSummary,indent2)}function appendReuseChange(section,before,after){appendScalarChange(section,"Reuse",formatReuse(before.reuse),formatReuse(after.reuse))}function appendEnvironmentSummary(lines,environment,variants,indent2){if(lines.push(line(`${import_chalk48.default.dim("Status:")} ${formatEnvironmentStatus(environment,variants)}`,indent2)),environment.reuse?.active){lines.push(line(`${import_chalk48.default.dim("Reuse:")} ${formatReuse(environment.reuse)}`,indent2));return}if(!environment.active&&environment.pausedOutcome){lines.push(line(`${import_chalk48.default.dim("Paused outcome:")} ${formatOutcome(environment.pausedOutcome,variants)}`,indent2));return}lines.push(line(`${import_chalk48.default.dim("Fallthrough:")} ${formatOutcome(environment.fallthrough,variants)}`,indent2));let ruleCount=environment.rules?.length??0;ruleCount>0&&lines.push(line(`${import_chalk48.default.dim("Rules:")} ${import_chalk48.default.bold(String(ruleCount))}`,indent2));let targets2=formatTargets(environment.targets,variants);targets2.length>0&&lines.push(line(`${import_chalk48.default.dim("Targets:")} ${import_chalk48.default.bold(String(targets2.length))}`,indent2))}function appendScalarChange(lines,label,before,after,indent2=4){(0,import_fast_deep_equal2.default)(before,after)||(lines.push(line(import_chalk48.default.bold(label),indent2)),lines.push(diffLine("-",formatScalarValue(before),indent2+2)),lines.push(diffLine("+",formatScalarValue(after),indent2+2)))}function appendListChange(lines,label,before,after,indent2=4){appendStringSetChange(lines,label,before,after,indent2)}function appendStringSetChange(lines,label,before,after,indent2=4){let removed=before.filter(item=>!after.includes(item)).sort(),added=after.filter(item=>!before.includes(item)).sort();if(!(removed.length===0&&added.length===0)){lines.push(line(import_chalk48.default.bold(label),indent2));for(let item of removed)lines.push(diffLine("-",item,indent2+2));for(let item of added)lines.push(diffLine("+",item,indent2+2))}}function appendSection(lines,title,section){section.length!==0&&(lines.length>0&&lines.push(""),lines.push(line(import_chalk48.default.bold(title),2)),lines.push(...section))}function appendFallbackChanges(lines,title,changes){let section=[];appendFallbackChangeLines(section,changes,4),appendSection(lines,title,section)}function appendFallbackChangeLines(lines,changes,indent2){for(let change of changes)lines.push(line(import_chalk48.default.bold(change.path||"value"),indent2)),change.action!=="added"&&lines.push(diffLine("-",formatScalarValue(change.before),indent2+2)),change.action!=="removed"&&lines.push(diffLine("+",formatScalarValue(change.after),indent2+2))}function formatRuleDetails(rule,variants,indent2){let lines=[];lines.push(line(`${import_chalk48.default.dim("\u2192")} ${formatOutcome(rule.outcome,variants,!1)}`,indent2));for(let condition of rule.conditions)appendConditionDetails(lines,condition,indent2+2);return lines}function appendConditionDetails(lines,condition,indent2){let{text,listItems}=formatFlagCondition(condition,void 0);lines.push(line(`${import_chalk48.default.dim("if")} ${text}`,indent2));for(let item of listItems??[])lines.push(line(`${import_chalk48.default.dim("-")} ${item}`,indent2+3))}function appendConditionDiff(lines,marker,condition,indent2){let{text,listItems}=formatFlagCondition(condition,void 0);lines.push(diffLine(marker,`${import_chalk48.default.dim("if")} ${text}`,indent2));for(let item of listItems??[])lines.push(line(`${import_chalk48.default.dim("-")} ${item}`,indent2+3))}function formatTargets(targets2,variants,includeVariantId=!1){let lines=[];for(let[variantId,entityKinds]of Object.entries(targets2??{}))for(let[entityKind,attributes]of Object.entries(entityKinds))for(let[attribute,values]of Object.entries(attributes))for(let target of values){let variant=variants.find(candidate=>candidate.id===variantId);lines.push(`${import_chalk48.default.dim(`${entityKind}.${attribute}:`)} ${formatTargetValue(target)} ${import_chalk48.default.dim("\u2192")} ${formatFlagVariantSummary(variant,variantId,includeVariantId)}`)}return lines.sort()}function formatTargetValue(target){return target.note?`${target.value} ${import_chalk48.default.gray(`(${target.note})`)}`:target.value}function formatEnvironmentStatus(environment,variants){return environment.active?import_chalk48.default.green("active"):environment.pausedOutcome?`${import_chalk48.default.gray("paused")}, ${import_chalk48.default.dim("serving")} ${formatOutcome(environment.pausedOutcome,variants,!1)}`:import_chalk48.default.gray("paused")}function formatReuse(reuse){return reuse?.active?`${import_chalk48.default.dim("reusing")} ${import_chalk48.default.cyan(formatEnvironmentName(reuse.environment))}`:import_chalk48.default.gray("none")}function formatOutcome(outcome,variants,includeServe=!0,includeVariantId=!1){let prefix=includeServe?`${import_chalk48.default.dim("Serve")} `:"",summary=formatFlagOutcome(outcome,variants,includeVariantId);if(outcome.type==="split"){let defaultVariant=variants.find(variant=>variant.id===outcome.defaultVariantId);return`${prefix}${summary}; ${import_chalk48.default.dim("by")} ${formatBucketingBase(outcome.base)}; ${import_chalk48.default.dim("Fallback:")} ${formatFlagVariantSummary(defaultVariant,outcome.defaultVariantId,includeVariantId)}`}return outcome.type==="rollout"?`${prefix}${summary}; ${import_chalk48.default.dim("by")} ${formatBucketingBase(outcome.base)}; ${import_chalk48.default.dim("Starts:")} ${formatTimestamp(outcome.startTimestamp)}`:`${prefix}${summary}`}function formatBucketingBase(base){return`${base.kind}.${base.attribute}`}function formatTimestamp(timestamp){let date=new Date(timestamp);return Number.isNaN(date.getTime())?String(timestamp):date.toISOString()}function formatItemOrder(ids){return ids.join(` ${import_chalk48.default.dim("\u2192")} `)}function formatRuleTitle(ruleId,index,ruleOrder){return ruleOrder.length===1?ruleId:`${ruleId} ${import_chalk48.default.dim(`(position ${index+1})`)}`}function formatVariantChangeTitle(before,after){let label=after.label??before.label;return label?`${import_chalk48.default.bold(label)} (${import_chalk48.default.dim(after.id)})`:after.id}function formatVariantSummary(variant){let details=[`${import_chalk48.default.dim("id:")} ${variant.id}`,`${import_chalk48.default.dim("value:")} ${import_chalk48.default.bold(formatVariantValue(variant.value))}`];return variant.label&&details.unshift(import_chalk48.default.bold(variant.label)),details.join(", ")}function formatScalarValue(value){return value==null||value===""?"-":typeof value=="string"?value:typeof value=="boolean"?value?"true":"false":JSON.stringify(sortObjectKeys(value),null,2)}function formatEnvironmentName(environment){return environment.charAt(0).toUpperCase()+environment.slice(1)}function line(text,indent2){return`${" ".repeat(indent2)}${text}`}function diffLine(marker,text,indent2){let color=marker==="+"?import_chalk48.default.green:marker==="-"?import_chalk48.default.red:import_chalk48.default.yellow;return line(color(`${marker} ${text}`),indent2)}function sortEnvironments(a,b){let aIndex=ENVIRONMENT_ORDER.indexOf(a),bIndex=ENVIRONMENT_ORDER.indexOf(b);return aIndex===-1&&bIndex===-1?a.localeCompare(b):aIndex===-1?1:bIndex===-1?-1:aIndex-bIndex}function omitKeys(value,keys){let omitted={...value};for(let key of keys)delete omitted[key];return omitted}function diffValues(before,after,path=""){return(0,import_fast_deep_equal2.default)(before,after)?[]:isPlainObject(before)&&isPlainObject(after)?Array.from(new Set([...Object.keys(before),...Object.keys(after)])).sort().flatMap(key=>diffValues(before[key],after[key],joinPath(path,key))):[{path,action:before===void 0?"added":after===void 0?"removed":"changed",before,after}]}function isPlainObject(value){return value!==null&&typeof value=="object"&&!Array.isArray(value)}function joinPath(path,key){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)?path?`${path}.${key}`:key:`${path}[${JSON.stringify(key)}]`}function sortObjectKeys(value){return Array.isArray(value)?value.map(sortObjectKeys):isPlainObject(value)?Object.fromEntries(Object.keys(value).sort().map(key=>[key,sortObjectKeys(value[key])])):value}var COMMAND_CONFIG10={list:getCommandAliases(versionsListSubcommand),diff:getCommandAliases(versionsDiffSubcommand)};async function versions(client,argv){let telemetryClient=new FlagsVersionsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(versionsSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG10),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetryClient.trackCliFlagHelp("flags versions",subcommandOriginal),output_manager_default.print(help(parsedArgs.args.length>0?versionsListSubcommand:versionsSubcommand,{stream:client.stderr,parent:parsedArgs.args.length>0?getVersionsHelpParent():flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:getVersionsHelpParent(),columns:client.stderr.columns}))}switch(subcommand){case"diff":return needHelp?(telemetryClient.trackCliFlagHelp("flags versions",subcommandOriginal),printHelp(versionsDiffSubcommand),0):(telemetryClient.trackCliSubcommandDiff(subcommandOriginal),diffVersions(client,args,telemetryClient));case"list":return needHelp?(telemetryClient.trackCliFlagHelp("flags versions",subcommandOriginal),printHelp(versionsListSubcommand),0):(telemetryClient.trackCliSubcommandList(subcommandOriginal),listVersions(client,args,telemetryClient));default:return telemetryClient.trackCliSubcommandList("default"),listVersions(client,argv,telemetryClient)}}async function listVersions(client,argv,telemetryClient){let parsedArgs,flagsSpecification=getFlagsSpecification(versionsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],limit=flags["--limit"],cursor=flags["--next"]??flags["--cursor"],json=flags["--json"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error(`Missing required argument: flag. Usage: ${getCommandName("flags versions <flag>")}`),2;if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionLimit(limit),telemetryClient.trackCliOptionNext(flags["--next"]),telemetryClient.trackCliOptionCursor(flags["--cursor"]),flags["--cursor"]!==void 0&&warnDeprecatedOption(client.argv,"--cursor","--next"),telemetryClient.trackCliFlagJson(json),limit!==void 0&&(!Number.isInteger(limit)||limit<1||limit>MAX_FLAG_VERSIONS_PAGE_LIMIT))return output_manager_default.error(`The --limit option must be an integer between 1 and ${MAX_FLAG_VERSIONS_PAGE_LIMIT}.`),2;let link=await resolveLinkedProject(client,projectName);if(typeof link=="number")return link;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),versionsStamp=stamp_default(),environmentLabel=environment?` in ${environment}`:"";output_manager_default.spinner(`Fetching version history for ${import_chalk49.default.bold(flagArg)}${environmentLabel} in ${projectSlugLink}`);try{let{versions:versionList,next}=await getFlagVersions(client,project.id,flagArg,{environment,limit,cursor});if(output_manager_default.stopSpinner(),json)outputJson4(client,versionList,next);else if(versionList.length===0)output_manager_default.log(`No versions found for ${import_chalk49.default.bold(flagArg)}${environmentLabel} in ${projectSlugLink} ${import_chalk49.default.gray(versionsStamp())}`);else if(output_manager_default.log(`${(0,import_pluralize3.default)("version",versionList.length,!0)} found for ${import_chalk49.default.bold(flagArg)}${environmentLabel} in ${projectSlugLink} ${import_chalk49.default.gray(versionsStamp())}`),printVersionsTable(versionList),next){let nextCmd=buildNextPageCommand3(flagArg,flags,next);output_manager_default.print(`
|
|
254
254
|
`),printNextPageCommand(getCommandNamePlain(nextCmd))}}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function diffVersions(client,argv,telemetryClient){let parsedArgs,flagsSpecification=getFlagsSpecification(versionsDiffSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,revision=flags["--revision"],json=flags["--json"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error(`Missing required argument: flag. Usage: ${getCommandName("flags versions diff <flag> --revision <number>")}`),2;if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionRevision(revision),telemetryClient.trackCliFlagJson(json),revision===void 0||!Number.isInteger(revision)||revision<0)return output_manager_default.error("The --revision option must be a non-negative integer."),2;if(revision===0)return output_manager_default.error("Revision 0 has no previous revision to compare."),1;let link=await resolveLinkedProject(client,projectName);if(typeof link=="number")return link;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),diffStamp=stamp_default();output_manager_default.spinner(`Fetching version diff for ${import_chalk49.default.bold(flagArg)} revision ${revision} in ${projectSlugLink}`);try{let{version,previousVersion,availableRevisionCount}=await getVersionPair(client,project.id,flagArg,revision);if(output_manager_default.stopSpinner(),!version)return output_manager_default.error(`${formatAvailableRevisionCount(availableRevisionCount)} Revision ${revision} was not found for ${import_chalk49.default.bold(flagArg)} in ${projectSlugLink}.`),1;if(!previousVersion)return output_manager_default.error(`${formatAvailableRevisionCount(availableRevisionCount)} Previous revision ${revision-1} was not found for ${import_chalk49.default.bold(flagArg)} in ${projectSlugLink}.`),1;json?outputDiffJson(client,flagArg,version,previousVersion,diffVersionData(previousVersion.data,version.data)):printVersionDiff({flagArg,projectSlugLink,version,previousVersion,diffStamp})}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveLinkedProject(client,projectName){let link=await getLinkedFlagsProject(client,projectName);return link.status==="error"?link.exitCode:link.status==="not_linked"?(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1):(client.config.currentTeam=link.org.type==="team"?link.org.id:void 0,link)}async function getVersionPair(client,projectId,flagArg,revision){let cursor,version,previousVersion,availableRevisions=new Set;do{let result=await getFlagVersions(client,projectId,flagArg,{limit:MAX_FLAG_VERSIONS_PAGE_LIMIT,cursor});for(let candidate of result.versions)availableRevisions.add(candidate.revision);if(version??=result.versions.find(candidate=>candidate.revision===revision),previousVersion??=result.versions.find(candidate=>candidate.revision===revision-1),version&&previousVersion)break;cursor=result.next??void 0}while(cursor);return{version,previousVersion,availableRevisionCount:availableRevisions.size}}function formatAvailableRevisionCount(count){return`Only ${(0,import_pluralize3.default)("revision",count,!0)} ${count===1?"is":"are"} available.`}function outputJson4(client,versions2,next){let jsonOutput={versions:versions2.map(version=>({...formatVersionSummary(version),data:version.data})),pagination:{next}};client.stdout.write(`${JSON.stringify(jsonOutput,null,2)}
|
|
255
255
|
`)}function outputDiffJson(client,flagArg,version,previousVersion,changes){let jsonOutput={flag:flagArg,revision:version.revision,previousRevision:previousVersion.revision,version:formatVersionSummary(version),previousVersion:formatVersionSummary(previousVersion),changes};client.stdout.write(`${JSON.stringify(jsonOutput,null,2)}
|
|
256
256
|
`)}function formatVersionSummary(version){return{id:version.id,flagId:version.flagId,revision:version.revision,author:getVersionAuthor(version),createdBy:version.createdBy??null,message:getVersionMessage(version),createdAt:version.createdAt,changedEnvironments:version.changedEnvironments}}function printVersionsTable(versions2){let headers=["Revision","Author","Message","Timestamp","Changed Environments"],rows=versions2.map(version=>[String(version.revision),getVersionAuthor(version)??import_chalk49.default.gray("-"),getVersionMessage(version)??import_chalk49.default.gray("-"),formatDate(version.createdAt),formatChangedEnvironments(version.changedEnvironments)]),table2=formatTable(headers,["r","l","l","l","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
@@ -266,13 +266,13 @@ ${table2}
|
|
|
266
266
|
${formattedDiff}
|
|
267
267
|
|
|
268
268
|
`)}function formatChangedEnvironments(environments){return environments.length===0?import_chalk49.default.gray("-"):environments.join(", ")}function getVersionAuthor(version){return version.metadata?.creator?.name??version.createdBy??null}function getVersionMessage(version){return version.message?version.message:version.revision===0?"Flag created":null}function getVersionsHelpParent(){return{...versionsSubcommand,name:"flags versions"}}function buildNextPageCommand3(flagArg,flags,nextCursor){let environment=flags["--environment"],baseFlags=getCommandFlags(flags,["_","--next","--cursor","--environment","--json"]),environmentFlag=environment?` --environment ${quoteArg(environment)}`:"";return`flags versions ${quoteArg(flagArg)}${baseFlags}${environmentFlag} --next ${quoteArg(nextCursor)}`}async function getSdkKeys(client,projectId){output_manager_default.debug(`Fetching SDK keys for project ${projectId}`);let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/sdk-keys`;return(await client.fetch(url)).data}async function createSdkKey(client,projectId,request){output_manager_default.debug(`Creating SDK key for project ${projectId}`);let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/sdk-keys`;return await client.fetch(url,{method:"PUT",body:request})}async function deleteSdkKey(client,projectId,hashKey){output_manager_default.debug(`Deleting SDK key ${hashKey} for project ${projectId}`);let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/sdk-keys/${encodeURIComponent(hashKey)}`;await client.fetch(url,{method:"DELETE",json:!1})}var FLAG_EVALUATIONS_METRIC="vercel.flags.evaluation",FLAG_EVALUATIONS_AGGREGATION="sum",EVALUATIONS_TIMEOUT_MS=5e3;async function countFlagEvaluations(client,options){let{ownerId,projectId,flagSlug,startTime,endTime}=options;try{let body={scope:{ownerId,projectIds:[projectId]},timeRange:{start:startTime.toISOString(),end:endTime.toISOString()},metrics:{value:{metric:FLAG_EVALUATIONS_METRIC,aggregation:FLAG_EVALUATIONS_AGGREGATION}},outputs:["value"],filter:`flagKey:${JSON.stringify(flagSlug)}`},response=await client.fetch(OBSERVABILITY_METRICS_PATH,{method:"POST",body:JSON.stringify(body),headers:{"Content-Type":"application/json"},accountId:ownerId,signal:AbortSignal.timeout(EVALUATIONS_TIMEOUT_MS),retry:{retries:0},bailOn429:!0}),total=0;for(let row of response.summary??[]){let value=Number(row.values.value);Number.isFinite(value)&&(total+=value)}return total}catch(err){return output_manager_default.debug(`Could not count evaluations for flag ${flagSlug}: ${err instanceof Error?err.message:String(err)}`),null}}var FlagsEvaluationsTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionSince(since){since&&this.trackCliOption({option:"since",value:this.redactedValue})}trackCliOptionUntil(until){until&&this.trackCliOption({option:"until",value:this.redactedValue})}trackCliOptionGranularity(granularity){granularity&&this.trackCliOption({option:"granularity",value:isFlagEvaluationsGranularity(granularity)?granularity:this.redactedValue})}trackCliOptionGroupBy(groupBy){groupBy&&groupBy.length>0&&this.trackCliOption({option:"group-by",value:groupBy.map(dimension=>isFlagEvaluationsDimension(dimension)?dimension:this.redactedValue).join(",")})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}};var FLAG_EVALUATIONS_ROLLUP=getRollupColumnName(FLAG_EVALUATIONS_METRIC,FLAG_EVALUATIONS_AGGREGATION),MAX_GROUPS=100,DEFAULT_IN_CODE_VARIANT="Default in Code",PERSONAL_ACCOUNT_MESSAGE="Flag evaluations are available for team-owned projects only. Select a team with --scope <team>.",FORBIDDEN_MESSAGE="You do not have permission to read feature flags for this project, which flag evaluations require.";function getCellValue(cell){return cell==null?"":String(cell)}function sanitizeGroupValue(value){return sanitizeForTerminal(value).replace(/\p{Cc}/gu,"")}function getEvaluationVariantValue(flag,variantId){return variantId?flag.variants.find(variant=>variant.id===variantId)?.value??null:DEFAULT_IN_CODE_VARIANT}function getVariantDisplayName(flag,variantId){if(!variantId||variantId==="(not set)"||variantId===DEFAULT_IN_CODE_VARIANT)return DEFAULT_IN_CODE_VARIANT;let variant=flag.variants.find(item=>item.id===variantId);return variant?formatVariantListSummary(variant):variantId}function getSdkKeyLabel(sdkKey){return sdkKey.label?`${sdkKey.label} (${sdkKey.environment})`:`${sdkKey.environment} ${sdkKey.type} key`}function getSdkKeyDisplayName(sdkKeys2,hashKey){if(!hashKey)return"(not set)";let sdkKey=sdkKeys2.get(hashKey);return sdkKey?getSdkKeyLabel(sdkKey):`${hashKey} (unknown or deleted key)`}function handleCommandError(client,error,jsonOutput){if(!jsonOutput)return printError(error),1;if(isAPIError(error))return outputError(client,!0,error.code||"API_ERROR",error.serverMessage||`API error (${error.status}).`);let message=error instanceof Error?error.message:String(error);return outputError(client,!0,"UNEXPECTED_ERROR",message)}function handleMetricsQueryError(client,error,jsonOutput){if(!isAPIError(error))return handleCommandError(client,error,jsonOutput);let genericForbidden=error.status===403&&(!error.serverMessage||error.serverMessage==="Forbidden"||error.serverMessage==="Response Error");return handleApiError(error,jsonOutput,client,genericForbidden?{403:{code:"FORBIDDEN",message:FORBIDDEN_MESSAGE}}:{})}function getGroupKey(row,fields){return JSON.stringify(fields.map(field=>getCellValue(row[field])))}function limitEvaluationGroups(response,fields){if(response.summary.length<=MAX_GROUPS)return{response,truncated:!1};let summary=response.summary.slice(0,MAX_GROUPS),visibleGroups=new Set(summary.map(row=>getGroupKey(row,fields)));return{response:{...response,summary,data:response.data?.filter(row=>visibleGroups.has(getGroupKey(row,fields)))},truncated:!0}}function formatEvaluationsJson(flag,dimensions,sdkKeys2,response,startTime,endTime,granularity,truncated){return`${JSON.stringify({flag:flag?.slug??null,...flag?{variants:Object.fromEntries(flag.variants.map(({id,value})=>[id,value]))}:{},groupBy:dimensions,startTime:startTime.toISOString(),endTime:endTime.toISOString(),granularity,truncated,buckets:(response.data??[]).map(row=>{let bucket={timestamp:row.timestamp};for(let dimension of dimensions){let value=getCellValue(row[FLAG_EVALUATIONS_DIMENSIONS[dimension].field]);switch(dimension){case"variant":bucket.variantId=value,bucket.variantValue=flag?getEvaluationVariantValue(flag,value):null;break;case"flag":bucket.flagKey=value;break;case"sdk-key":{let sdkKey=sdkKeys2.get(value);bucket.sdkKeyId=value,bucket.sdkKeyLabel=sdkKey?.label??null,bucket.sdkKeyEnvironment=sdkKey?.environment??null;break}case"client":bucket.clientName=value;break;case"environment":bucket.environment=value;break;case"reason":bucket.reason=value;break;case"datafile-revision":bucket.datafileRevision=value;break}}return bucket.evaluations=row[FLAG_EVALUATIONS_ROLLUP]??null,bucket})},null,2)}
|
|
269
|
-
`}async function evaluations(client,argv){let telemetry=new FlagsEvaluationsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(evaluationsSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(error){return printError(error),2}let{args,flags}=parsedArgs,[flagArgument]=args,projectName=getProjectNameFromFlags(flags),since=flags["--since"],until=flags["--until"],granularity=flags["--granularity"],groupByArguments=flags["--group-by"]??[];telemetry.trackCliArgumentFlag(flagArgument),telemetry.trackCliOptionProject(projectName),telemetry.trackCliOptionSince(since),telemetry.trackCliOptionUntil(until),telemetry.trackCliOptionGranularity(granularity),telemetry.trackCliOptionGroupBy(groupByArguments.length>0?groupByArguments:void 0),telemetry.trackCliFlagJson(flags["--json"]);let jsonOutput=flags["--json"]??!1;if(granularity&&!isFlagEvaluationsGranularity(granularity))return outputError(client,jsonOutput,"INVALID_GRANULARITY",`Invalid granularity "${granularity}". Use one of: ${FLAG_EVALUATIONS_GRANULARITIES.join(", ")}.`);let invalidDimension=groupByArguments.find(dimension=>!isFlagEvaluationsDimension(dimension));if(invalidDimension!==void 0)return outputError(client,jsonOutput,"INVALID_GROUP_BY",`Invalid group-by dimension "${invalidDimension}". Use one of: ${FLAG_EVALUATIONS_DIMENSION_NAMES.join(", ")}.`);let dimensions=Array.from(new Set(groupByArguments.filter(isFlagEvaluationsDimension)));if(dimensions.length===0&&dimensions.push(flagArgument?"variant":"flag"),!flagArgument&&dimensions.includes("variant"))return outputError(client,jsonOutput,"MISSING_FLAG",`Grouping by variant needs a flag, because variants belong to one flag. Pass a flag: ${getCommandName("flags evaluations <flag> --group-by variant")}, or group the whole project by another dimension.`);let startTime,endTime,resolvedGranularity;try{if({startTime,endTime}=resolveTimeRange(since,until),startTime.getTime()>=endTime.getTime())throw new Error("The start time must be before the end time.");resolvedGranularity=computeGranularity(endTime.getTime()-startTime.getTime(),granularity),{startTime,endTime}=alignTimeRangeToGranularity(startTime,endTime,resolvedGranularity.duration)}catch(error){let message=error instanceof Error?error.message:String(error);return outputError(client,jsonOutput,"INVALID_TIME",message)}!jsonOutput&&resolvedGranularity.adjusted&&resolvedGranularity.notice&&output_manager_default.log(`Notice: ${resolvedGranularity.notice}`);let link;try{link=await getLinkedFlagsProject(client,projectName,{projectNotFoundHandling:jsonOutput?"return":"report"})}catch(error){return handleCommandError(client,error,jsonOutput)}if(link.status==="error")return jsonOutput?outputError(client,!0,"PROJECT_RESOLUTION_FAILED","Unable to resolve the requested Vercel project."):link.exitCode;if(link.status==="not_linked"){let code=projectName?"PROJECT_NOT_FOUND":"NOT_LINKED",message=projectName?`Project "${projectName}" was not found in the current scope.`:`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`;return outputError(client,jsonOutput,code,message)}if(link.org.type!=="team")return outputError(client,jsonOutput,"MISSING_SCOPE",PERSONAL_ACCOUNT_MESSAGE);client.config.currentTeam=link.org.id;let{project,org}=link,flag,sdkKeys2=new Map;try{let[resolvedFlag,resolvedSdkKeys]=await Promise.all([flagArgument?getFlag(client,project.id,flagArgument):void 0,dimensions.includes("sdk-key")?getSdkKeys(client,project.id).catch(error=>(output_manager_default.debug(`Could not load SDK keys: ${String(error)}`),jsonOutput||output_manager_default.warn("Could not load SDK key labels; SDK keys are shown as hashes."),[])):[]]);flag=resolvedFlag;for(let sdkKey of resolvedSdkKeys)sdkKeys2.set(sdkKey.hashKey,sdkKey)}catch(error){return handleCommandError(client,error,jsonOutput)}jsonOutput||output_manager_default.spinner("Querying flag evaluations...");let scope={type:"project",ownerId:org.id,projectIds:[project.id]},groupByFields=dimensions.map(dimension=>FLAG_EVALUATIONS_DIMENSIONS[dimension].field),response;try{let body=createCanonicalMetricsRequest({scope,metric:FLAG_EVALUATIONS_METRIC,selection:{metric:FLAG_EVALUATIONS_METRIC,aggregation:FLAG_EVALUATIONS_AGGREGATION},startTime,endTime,granularity:resolvedGranularity.duration,groupBy:groupByFields,filter:flag?`flagKey:${JSON.stringify(flag.slug)}`:void 0,limit:MAX_GROUPS+1,orderBy:"value",orderDirection:"desc"}),canonicalResponse=await client.fetch(OBSERVABILITY_METRICS_PATH,{method:"POST",body:JSON.stringify(body),headers:{"Content-Type":"application/json"},accountId:org.id,bailOn429:!0});response=canonicalResponseToMetricsResponse(canonicalResponse,FLAG_EVALUATIONS_ROLLUP,"value","desc")}catch(error){return handleMetricsQueryError(client,error,jsonOutput)}finally{jsonOutput||output_manager_default.stopSpinner()}let limited=limitEvaluationGroups(response,groupByFields);if(jsonOutput)return client.stdout.write(formatEvaluationsJson(flag,dimensions,sdkKeys2,limited.response,startTime,endTime,resolvedGranularity.duration,limited.truncated)),0;let headings=dimensions.map(dimension=>FLAG_EVALUATIONS_DIMENSIONS[dimension].heading);if(limited.truncated){let subject=headings.length===1?headings[0].toLowerCase():"groups";output_manager_default.warn(`Results are limited to the ${MAX_GROUPS} most evaluated ${subject}.`)}let headingToDimension=new Map(dimensions.map((dimension,index)=>[headings[index],dimension]));return client.stdout.write(formatText({...limited.response,data:limited.response.data?.map(row=>({...row,...Object.fromEntries(dimensions.map((dimension,index)=>[headings[index],getCellValue(row[FLAG_EVALUATIONS_DIMENSIONS[dimension].field])]))}))},{metric:FLAG_EVALUATIONS_METRIC,metricUnit:"count",aggregation:FLAG_EVALUATIONS_AGGREGATION,groupBy:headings,scope,projectName:project.name,teamName:org.slug,periodStart:startTime.toISOString(),periodEnd:endTime.toISOString(),granularity:resolvedGranularity.duration,presentation:{compact:!0,formatGroupValue:(field,value)=>{switch(headingToDimension.get(field)){case"variant":return sanitizeGroupValue(flag?getVariantDisplayName(flag,value):value);case"sdk-key":return sanitizeGroupValue(getSdkKeyDisplayName(sdkKeys2,value));default:return sanitizeGroupValue(value)||"(not set)"}}}})),0}var import_chalk50=__toESM(require_source(),1);async function createFlag(client,projectId,request){let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags`;output_manager_default.debug(`Creating feature flag ${request.slug} for project ${projectId}`),output_manager_default.debug(`API endpoint: PUT ${url}`),output_manager_default.debug(`Request body: ${JSON.stringify(request,null,2)}`);try{let response=await client.fetch(url,{method:"PUT",body:request});return output_manager_default.debug(`Response: ${JSON.stringify(response,null,2)}`),response}catch(err){if(output_manager_default.debug("API error occurred"),err instanceof Error){output_manager_default.debug(`Error message: ${err.message}`),output_manager_default.debug(`Error name: ${err.name}`),output_manager_default.debug(`Error stack: ${err.stack}`);let errWithBody=err;errWithBody.status&&output_manager_default.debug(`Error status: ${errWithBody.status}`),errWithBody.body&&output_manager_default.debug(`Error body: ${JSON.stringify(errWithBody.body,null,2)}`)}throw err}}var FlagsCreateTelemetryClient=class extends TelemetryClient{trackCliArgumentSlug(slug){slug&&this.trackCliArgument({arg:"slug",value:this.redactedValue})}trackCliOptionKind(kind){kind&&this.trackCliOption({option:"kind",value:kind})}trackCliOptionDescription(description){description&&this.trackCliOption({option:"description",value:this.redactedValue})}trackCliOptionVariant(variants){variants?.length&&this.trackCliOption({option:"variant",value:this.redactedValue})}trackCliOptionDefaultVariant(defaultVariant){defaultVariant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionEnvironmentVariant(environmentVariants){if(environmentVariants?.length){let environments=environmentVariants.map(input=>input.split("=")[0].trim()),allStandard=environments.every(environment=>STANDARD_ENVIRONMENTS.includes(environment));this.trackCliOption({option:"environment-variant",value:allStandard?STANDARD_ENVIRONMENTS.filter(environment=>environments.includes(environment)).join(","):this.redactedValue})}}};import{randomBytes}from"node:crypto";var VARIANT_ID_ALPHABET="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function generateVariantId(size=21){let bytes=randomBytes(size),id="";for(let index=0;index<size;index++)id+=VARIANT_ID_ALPHABET[bytes[index]%VARIANT_ID_ALPHABET.length];return id}function parseVariantInput(input,kind,index){let{rawValue,rawLabel}=splitVariantInput(input,kind),validationError=validateVariantValue(rawValue,kind);if(validationError)throw new Error(`Invalid variant "${input}": ${validationError}`);return{id:generateVariantId(),value:parseVariantValue2(rawValue,kind),label:getVariantLabel(rawLabel,kind,index),description:""}}function validateVariantValue(value,kind){if(!value.trim())return"Variant value cannot be empty";if(kind==="boolean"){let loweredValue=value.toLowerCase();if(loweredValue!=="true"&&loweredValue!=="false")return"Boolean variant values must be true or false"}if(kind==="number"){let parsed=Number(value);if(!Number.isFinite(parsed))return"Number variants must be valid numeric values"}return kind==="json"&&!isValidJsonVariantValue(value)?"JSON variant values must be valid JSON":null}function splitVariantInput(input,kind){if(kind!=="json"){let separatorIndex=input.indexOf("=");return{rawValue:separatorIndex===-1?input.trim():input.slice(0,separatorIndex).trim(),rawLabel:separatorIndex===-1?void 0:input.slice(separatorIndex+1).trim()||void 0}}let trimmed=input.trim();if(isValidJsonVariantValue(trimmed))return{rawValue:trimmed};for(let index=trimmed.length-1;index>=0;index--){if(trimmed[index]!=="=")continue;let rawValue=trimmed.slice(0,index).trim(),rawLabel=trimmed.slice(index+1).trim();if(!(!rawValue||!isValidJsonVariantValue(rawValue)))return{rawValue,rawLabel:rawLabel||void 0}}return{rawValue:trimmed}}function getVariantLabel(rawLabel,kind,index){if(rawLabel)return rawLabel;if(kind==="json")return`Variant ${index+1}`}function parseVariantValue2(value,kind){return kind==="number"?Number(value):kind==="json"?JSON.parse(value):value}function isValidJsonVariantValue(value){try{return JSON.parse(value),!0}catch{return!1}}function normalizeOptionalInput(input){let value=input?.trim();return value||void 0}async function resolveOptionalInput(client,input,defaultValue,promptMessage){let value=normalizeOptionalInput(input);if(value!==void 0)return value;if(!client.stdin.isTTY)return defaultValue;let response=await client.input.text({message:promptMessage,default:defaultValue});return normalizeOptionalInput(response)||defaultValue}async function create(client,argv){let telemetryClient=new FlagsCreateTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(createSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[slug]=args;if(!slug)return output_manager_default.error("Please provide a slug for the feature flag"),output_manager_default.log(`Example: ${getCommandName("flags create my-feature")}`),2;let kind=flags["--kind"]||"boolean",description=flags["--description"],variantInputs=flags["--variant"]||[],defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),environmentVariantInputs=flags["--environment-variant"]||[],projectName=getProjectNameFromFlags(flags);if(telemetryClient.trackCliArgumentSlug(slug),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionKind(kind),telemetryClient.trackCliOptionDescription(description),telemetryClient.trackCliOptionVariant(variantInputs),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionEnvironmentVariant(environmentVariantInputs),kind!=="boolean"&&kind!=="string"&&kind!=="number"&&kind!=="json")return output_manager_default.error(`Invalid kind: ${kind}. Must be one of: boolean, string, number, json`),2;let environmentVariantSelectors;try{environmentVariantSelectors=parseEnvironmentVariantInputs(environmentVariantInputs)}catch(err){return output_manager_default.error(err.message),2}let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link,projectSlugLink=formatProject(link.org.slug,project.name),variants;try{variants=await getVariants(client,kind,variantInputs)}catch(err){return output_manager_default.error(err.message),1}let environments;try{environments=resolveEnvironments(kind,variants,defaultVariantSelector,environmentVariantSelectors)}catch(err){return output_manager_default.error(err.message),2}let request={slug,kind,description:description||"",variants,environments};try{output_manager_default.spinner("Creating feature flag...");let flag=await createFlag(client,project.id,request);output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk50.default.bold(flag.slug)} created successfully`),printFlagDetails({flag,projectSlugLink,orgSlug:link.org.slug,projectName:project.name,showTimestamps:!1})}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function getVariants(client,kind,variantInputs){if(kind==="boolean"){if(variantInputs.length>0)throw new Error("Boolean flags always use true/false variants. Omit --variant when creating a boolean flag.");return getDefaultVariants(kind)}if(variantInputs.length>0)return variantInputs.map((input,index)=>parseVariantInput(input,kind,index));if(!client.stdin.isTTY)throw new Error("Missing required flag --variant. Use --variant <value>[=label] (repeat as needed), or run interactively in a terminal.");return collectVariantsInteractively(client,kind)}async function collectVariantsInteractively(client,kind){let variants=[],addAnother=!0;for(;addAnother||variants.length===0;){let variantNumber=variants.length+1,valueInput=await client.input.text({message:kind==="json"?`Enter JSON value for variant ${variantNumber}:`:`Enter value for variant ${variantNumber}:`,validate:value=>{let result=validateVariantValue(value,kind);return result===null?!0:result}}),label=await client.input.text({message:`Enter an optional label for variant ${variantNumber}:`});variants.push(parseVariantInput(formatVariantInput(valueInput,label),kind,variants.length)),addAnother=await client.input.confirm("Add another variant?",!1)}return variants}function parseEnvironmentVariantInputs(inputs){let selectors={};for(let input of inputs){let separatorIndex=input.indexOf("="),environment=separatorIndex===-1?input.trim():input.slice(0,separatorIndex).trim(),variant=separatorIndex===-1?"":input.slice(separatorIndex+1).trim();if(!environment||!variant)throw new Error(`Invalid --environment-variant ${import_chalk50.default.bold(input)}. Use ENVIRONMENT=VARIANT, for example development=true.`);if(!STANDARD_ENVIRONMENTS.includes(environment))throw new Error(`Invalid environment in --environment-variant ${import_chalk50.default.bold(input)}. Must be one of: ${STANDARD_ENVIRONMENTS.join(", ")}`);let standardEnvironment=environment;if(selectors[standardEnvironment]!==void 0)throw new Error(`--environment-variant was passed more than once for ${import_chalk50.default.bold(environment)}. Pass each environment once.`);selectors[standardEnvironment]=variant}return selectors}function resolveEnvironments(kind,variants,defaultVariantSelector,environmentVariantSelectors){let defaultVariant=defaultVariantSelector?resolveVariantOrThrow(defaultVariantSelector,variants,"--default-variant"):void 0,environments={};for(let environment of STANDARD_ENVIRONMENTS){let selector=environmentVariantSelectors[environment],variant=selector?resolveVariantOrThrow(selector,variants,"--environment-variant",`${environment}=${selector}`):defaultVariant??getDefaultEnvironmentVariant(kind,variants,environment);environments[environment]=createEnvironmentConfig(variant.id,variant.id,!1)}return environments}function getDefaultEnvironmentVariant(kind,variants,environment){return kind==="boolean"&&environment==="development"?variants[1]:variants[0]}function createEnvironmentConfig(pausedVariantId,fallthroughVariantId,active){return{revision:0,active,pausedOutcome:{type:"variant",variantId:pausedVariantId},fallthrough:{type:"variant",variantId:fallthroughVariantId},rules:[],reuse:{active:!1,environment:""}}}function formatVariantInput(valueInput,label){let trimmedLabel=label.trim();return trimmedLabel?`${valueInput}=${trimmedLabel}`:valueInput}function getDefaultVariants(kind){switch(kind){case"boolean":return[{id:generateVariantId(),value:!1,label:"Off",description:"not enabled"},{id:generateVariantId(),value:!0,label:"On",description:"enabled"}];case"string":case"number":case"json":throw new Error(`Default variants are not supported for kind: ${kind}`)}}var import_open=__toESM(require_open(),1);var FlagsOpenTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}};async function openFlag(client,argv){let telemetryClient=new FlagsOpenTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(openSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,extraArg]=args,projectName=getProjectNameFromFlags(flags);if(extraArg)return output_manager_default.error(`Too many arguments. Usage: ${getCommandName("flags open [flag]")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link;try{let url=getFlagsDashboardUrl(org.slug,project.name),label="feature flags dashboard";if(flagArg){output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);output_manager_default.stopSpinner(),url=getFlagDashboardUrl(org.slug,project.name,flag.slug),label=`feature flag ${flag.slug}`}client.stdout.isTTY?(output_manager_default.log(`Opening ${label} in your browser...`),output_manager_default.log(`Visit this URL if the browser does not open: ${url}`),(0,import_open.default)(url).catch(()=>{})):client.stdout.write(`${url}
|
|
269
|
+
`}async function evaluations(client,argv){let telemetry=new FlagsEvaluationsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(evaluationsSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(error){return printError(error),2}let{args,flags}=parsedArgs,[flagArgument]=args,projectName=getProjectNameFromFlags(flags),since=flags["--since"],until=flags["--until"],granularity=flags["--granularity"],groupByArguments=flags["--group-by"]??[];telemetry.trackCliArgumentFlag(flagArgument),telemetry.trackCliOptionProject(projectName),telemetry.trackCliOptionSince(since),telemetry.trackCliOptionUntil(until),telemetry.trackCliOptionGranularity(granularity),telemetry.trackCliOptionGroupBy(groupByArguments.length>0?groupByArguments:void 0),telemetry.trackCliFlagJson(flags["--json"]);let jsonOutput=flags["--json"]??!1;if(granularity&&!isFlagEvaluationsGranularity(granularity))return outputError(client,jsonOutput,"INVALID_GRANULARITY",`Invalid granularity "${granularity}". Use one of: ${FLAG_EVALUATIONS_GRANULARITIES.join(", ")}.`);let invalidDimension=groupByArguments.find(dimension=>!isFlagEvaluationsDimension(dimension));if(invalidDimension!==void 0)return outputError(client,jsonOutput,"INVALID_GROUP_BY",`Invalid group-by dimension "${invalidDimension}". Use one of: ${FLAG_EVALUATIONS_DIMENSION_NAMES.join(", ")}.`);let dimensions=Array.from(new Set(groupByArguments.filter(isFlagEvaluationsDimension)));if(dimensions.length===0&&dimensions.push(flagArgument?"variant":"flag"),!flagArgument&&dimensions.includes("variant"))return outputError(client,jsonOutput,"MISSING_FLAG",`Grouping by variant needs a flag, because variants belong to one flag. Pass a flag: ${getCommandName("flags evaluations <flag> --group-by variant")}, or group the whole project by another dimension.`);let startTime,endTime,resolvedGranularity;try{if({startTime,endTime}=resolveTimeRange(since,until),startTime.getTime()>=endTime.getTime())throw new Error("The start time must be before the end time.");resolvedGranularity=computeGranularity(endTime.getTime()-startTime.getTime(),granularity),{startTime,endTime}=alignTimeRangeToGranularity(startTime,endTime,resolvedGranularity.duration)}catch(error){let message=error instanceof Error?error.message:String(error);return outputError(client,jsonOutput,"INVALID_TIME",message)}!jsonOutput&&resolvedGranularity.adjusted&&resolvedGranularity.notice&&output_manager_default.log(`Notice: ${resolvedGranularity.notice}`);let link;try{link=await getLinkedFlagsProject(client,projectName,{projectNotFoundHandling:jsonOutput?"return":"report"})}catch(error){return handleCommandError(client,error,jsonOutput)}if(link.status==="error")return jsonOutput?outputError(client,!0,"PROJECT_RESOLUTION_FAILED","Unable to resolve the requested Vercel project."):link.exitCode;if(link.status==="not_linked"){let code=projectName?"PROJECT_NOT_FOUND":"NOT_LINKED",message=projectName?`Project "${projectName}" was not found in the current scope.`:`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`;return outputError(client,jsonOutput,code,message)}if(link.org.type!=="team")return outputError(client,jsonOutput,"MISSING_SCOPE",PERSONAL_ACCOUNT_MESSAGE);client.config.currentTeam=link.org.id;let{project,org}=link,flag,sdkKeys2=new Map;try{let[resolvedFlag,resolvedSdkKeys]=await Promise.all([flagArgument?getFlag(client,project.id,flagArgument):void 0,dimensions.includes("sdk-key")?getSdkKeys(client,project.id).catch(error=>(output_manager_default.debug(`Could not load SDK keys: ${String(error)}`),jsonOutput||output_manager_default.warn("Could not load SDK key labels; SDK keys are shown as hashes."),[])):[]]);flag=resolvedFlag;for(let sdkKey of resolvedSdkKeys)sdkKeys2.set(sdkKey.hashKey,sdkKey)}catch(error){return handleCommandError(client,error,jsonOutput)}jsonOutput||output_manager_default.spinner("Querying flag evaluations...");let scope={type:"project",ownerId:org.id,projectIds:[project.id]},groupByFields=dimensions.map(dimension=>FLAG_EVALUATIONS_DIMENSIONS[dimension].field),response;try{let body=createCanonicalMetricsRequest({scope,metric:FLAG_EVALUATIONS_METRIC,selection:{metric:FLAG_EVALUATIONS_METRIC,aggregation:FLAG_EVALUATIONS_AGGREGATION},startTime,endTime,granularity:resolvedGranularity.duration,groupBy:groupByFields,filter:flag?`flagKey:${JSON.stringify(flag.slug)}`:void 0,limit:MAX_GROUPS+1,orderBy:"value",orderDirection:"desc"}),canonicalResponse=await client.fetch(OBSERVABILITY_METRICS_PATH,{method:"POST",body:JSON.stringify(body),headers:{"Content-Type":"application/json"},accountId:org.id,bailOn429:!0});response=canonicalResponseToMetricsResponse(canonicalResponse,FLAG_EVALUATIONS_ROLLUP,"value","desc")}catch(error){return handleMetricsQueryError(client,error,jsonOutput)}finally{jsonOutput||output_manager_default.stopSpinner()}let limited=limitEvaluationGroups(response,groupByFields);if(jsonOutput)return client.stdout.write(formatEvaluationsJson(flag,dimensions,sdkKeys2,limited.response,startTime,endTime,resolvedGranularity.duration,limited.truncated)),0;let headings=dimensions.map(dimension=>FLAG_EVALUATIONS_DIMENSIONS[dimension].heading);if(limited.truncated){let subject=headings.length===1?headings[0].toLowerCase():"groups";output_manager_default.warn(`Results are limited to the ${MAX_GROUPS} most evaluated ${subject}.`)}let headingToDimension=new Map(dimensions.map((dimension,index)=>[headings[index],dimension]));return client.stdout.write(formatText({...limited.response,data:limited.response.data?.map(row=>({...row,...Object.fromEntries(dimensions.map((dimension,index)=>[headings[index],getCellValue(row[FLAG_EVALUATIONS_DIMENSIONS[dimension].field])]))}))},{metric:FLAG_EVALUATIONS_METRIC,metricUnit:"count",aggregation:FLAG_EVALUATIONS_AGGREGATION,groupBy:headings,scope,projectName:project.name,teamName:org.slug,periodStart:startTime.toISOString(),periodEnd:endTime.toISOString(),granularity:resolvedGranularity.duration,presentation:{compact:!0,formatGroupValue:(field,value)=>{switch(headingToDimension.get(field)){case"variant":return sanitizeGroupValue(flag?getVariantDisplayName(flag,value):value);case"sdk-key":return sanitizeGroupValue(getSdkKeyDisplayName(sdkKeys2,value));default:return sanitizeGroupValue(value)||"(not set)"}}}})),0}var import_chalk50=__toESM(require_source(),1);async function createFlag(client,projectId,request){let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags`;output_manager_default.debug(`Creating feature flag ${request.slug} for project ${projectId}`),output_manager_default.debug(`API endpoint: PUT ${url}`),output_manager_default.debug(`Request body: ${JSON.stringify(request,null,2)}`);try{let response=await client.fetch(url,{method:"PUT",body:request});return output_manager_default.debug(`Response: ${JSON.stringify(response,null,2)}`),response}catch(err){if(output_manager_default.debug("API error occurred"),err instanceof Error){output_manager_default.debug(`Error message: ${err.message}`),output_manager_default.debug(`Error name: ${err.name}`),output_manager_default.debug(`Error stack: ${err.stack}`);let errWithBody=err;errWithBody.status&&output_manager_default.debug(`Error status: ${errWithBody.status}`),errWithBody.body&&output_manager_default.debug(`Error body: ${JSON.stringify(errWithBody.body,null,2)}`)}throw err}}var FlagsCreateTelemetryClient=class extends TelemetryClient{trackCliArgumentSlug(slug){slug&&this.trackCliArgument({arg:"slug",value:this.redactedValue})}trackCliOptionKind(kind){kind&&this.trackCliOption({option:"kind",value:kind})}trackCliOptionDescription(description){description&&this.trackCliOption({option:"description",value:this.redactedValue})}trackCliOptionVariant(variants){variants?.length&&this.trackCliOption({option:"variant",value:this.redactedValue})}trackCliOptionDefaultVariant(defaultVariant){defaultVariant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionEnvironmentVariant(environmentVariants){if(environmentVariants?.length){let environments=environmentVariants.map(input=>input.split("=")[0].trim()),allStandard=environments.every(environment=>STANDARD_ENVIRONMENTS.includes(environment));this.trackCliOption({option:"environment-variant",value:allStandard?STANDARD_ENVIRONMENTS.filter(environment=>environments.includes(environment)).join(","):this.redactedValue})}}};import{randomBytes}from"node:crypto";var VARIANT_ID_ALPHABET="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";function generateVariantId(size=21){let bytes=randomBytes(size),id="";for(let index=0;index<size;index++)id+=VARIANT_ID_ALPHABET[bytes[index]%VARIANT_ID_ALPHABET.length];return id}function parseVariantInput(input,kind,index){let{rawValue,rawLabel}=splitVariantInput(input,kind),validationError=validateVariantValue(rawValue,kind);if(validationError)throw new Error(`Invalid variant "${input}": ${validationError}`);return{id:generateVariantId(),value:parseVariantValue2(rawValue,kind),label:getVariantLabel(rawLabel,kind,index),description:""}}function validateVariantValue(value,kind){if(!value.trim())return"Variant value cannot be empty";if(kind==="boolean"){let loweredValue=value.toLowerCase();if(loweredValue!=="true"&&loweredValue!=="false")return"Boolean variant values must be true or false"}if(kind==="number"){let parsed=Number(value);if(!Number.isFinite(parsed))return"Number variants must be valid numeric values"}return kind==="json"&&!isValidJsonVariantValue(value)?"JSON variant values must be valid JSON":null}function splitVariantInput(input,kind){if(kind!=="json"){let separatorIndex=input.indexOf("=");return{rawValue:separatorIndex===-1?input.trim():input.slice(0,separatorIndex).trim(),rawLabel:separatorIndex===-1?void 0:input.slice(separatorIndex+1).trim()||void 0}}let trimmed=input.trim();if(isValidJsonVariantValue(trimmed))return{rawValue:trimmed};for(let index=trimmed.length-1;index>=0;index--){if(trimmed[index]!=="=")continue;let rawValue=trimmed.slice(0,index).trim(),rawLabel=trimmed.slice(index+1).trim();if(!(!rawValue||!isValidJsonVariantValue(rawValue)))return{rawValue,rawLabel:rawLabel||void 0}}return{rawValue:trimmed}}function getVariantLabel(rawLabel,kind,index){if(rawLabel)return rawLabel;if(kind==="json")return`Variant ${index+1}`}function parseVariantValue2(value,kind){return kind==="number"?Number(value):kind==="json"?JSON.parse(value):value}function isValidJsonVariantValue(value){try{return JSON.parse(value),!0}catch{return!1}}function normalizeOptionalInput(input){let value=input?.trim();return value||void 0}async function resolveOptionalInput(client,input,defaultValue,promptMessage){let value=normalizeOptionalInput(input);if(value!==void 0)return value;if(!client.stdin.isTTY)return defaultValue;let response=await client.input.text({message:promptMessage,default:defaultValue});return normalizeOptionalInput(response)||defaultValue}async function create(client,argv){let telemetryClient=new FlagsCreateTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(createSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[slug]=args;if(!slug)return output_manager_default.error("Please provide a slug for the feature flag"),output_manager_default.log(`Example: ${getCommandName("flags create my-feature")}`),2;let kind=flags["--kind"]||"boolean",description=flags["--description"],variantInputs=flags["--variant"]||[],defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),environmentVariantInputs=flags["--environment-variant"]||[],projectName=getProjectNameFromFlags(flags);if(telemetryClient.trackCliArgumentSlug(slug),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionKind(kind),telemetryClient.trackCliOptionDescription(description),telemetryClient.trackCliOptionVariant(variantInputs),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionEnvironmentVariant(environmentVariantInputs),kind!=="boolean"&&kind!=="string"&&kind!=="number"&&kind!=="json")return output_manager_default.error(`Invalid kind: ${kind}. Must be one of: boolean, string, number, json`),2;let environmentVariantSelectors;try{environmentVariantSelectors=parseEnvironmentVariantInputs(environmentVariantInputs)}catch(err){return output_manager_default.error(err.message),2}let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link,projectSlugLink=formatProject(link.org.slug,project.name),variants;try{variants=await getVariants(client,kind,variantInputs)}catch(err){return output_manager_default.error(err.message),1}let environments;try{environments=resolveEnvironments(kind,variants,defaultVariantSelector,environmentVariantSelectors)}catch(err){return output_manager_default.error(err.message),2}let request={slug,kind,description:description||"",variants,environments};try{output_manager_default.spinner("Creating feature flag...");let flag=await createFlag(client,project.id,request);output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk50.default.bold(flag.slug)} created successfully`),printFlagDetails({flag,projectSlugLink,orgSlug:link.org.slug,projectName:project.name,showTimestamps:!1})}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function getVariants(client,kind,variantInputs){if(kind==="boolean"){if(variantInputs.length>0)throw new Error("Boolean flags always use true/false variants. Omit --variant when creating a boolean flag.");return getDefaultVariants(kind)}if(variantInputs.length>0)return variantInputs.map((input,index)=>parseVariantInput(input,kind,index));if(!client.stdin.isTTY)throw new Error("Missing required option --variant. Use --variant <value>[=label] (repeat as needed), or run interactively in a terminal.");return collectVariantsInteractively(client,kind)}async function collectVariantsInteractively(client,kind){let variants=[],addAnother=!0;for(;addAnother||variants.length===0;){let variantNumber=variants.length+1,valueInput=await client.input.text({message:kind==="json"?`Enter JSON value for variant ${variantNumber}:`:`Enter value for variant ${variantNumber}:`,validate:value=>{let result=validateVariantValue(value,kind);return result===null?!0:result}}),label=await client.input.text({message:`Enter an optional label for variant ${variantNumber}:`});variants.push(parseVariantInput(formatVariantInput(valueInput,label),kind,variants.length)),addAnother=await client.input.confirm("Add another variant?",!1)}return variants}function parseEnvironmentVariantInputs(inputs){let selectors={};for(let input of inputs){let separatorIndex=input.indexOf("="),environment=separatorIndex===-1?input.trim():input.slice(0,separatorIndex).trim(),variant=separatorIndex===-1?"":input.slice(separatorIndex+1).trim();if(!environment||!variant)throw new Error(`Invalid --environment-variant ${import_chalk50.default.bold(input)}. Use ENVIRONMENT=VARIANT, for example development=true.`);if(!STANDARD_ENVIRONMENTS.includes(environment))throw new Error(`Invalid environment in --environment-variant ${import_chalk50.default.bold(input)}. Must be one of: ${STANDARD_ENVIRONMENTS.join(", ")}`);let standardEnvironment=environment;if(selectors[standardEnvironment]!==void 0)throw new Error(`--environment-variant was passed more than once for ${import_chalk50.default.bold(environment)}. Pass each environment once.`);selectors[standardEnvironment]=variant}return selectors}function resolveEnvironments(kind,variants,defaultVariantSelector,environmentVariantSelectors){let defaultVariant=defaultVariantSelector?resolveVariantOrThrow(defaultVariantSelector,variants,"--default-variant"):void 0,environments={};for(let environment of STANDARD_ENVIRONMENTS){let selector=environmentVariantSelectors[environment],variant=selector?resolveVariantOrThrow(selector,variants,"--environment-variant",`${environment}=${selector}`):defaultVariant??getDefaultEnvironmentVariant(kind,variants,environment);environments[environment]=createEnvironmentConfig(variant.id,variant.id,!1)}return environments}function getDefaultEnvironmentVariant(kind,variants,environment){return kind==="boolean"&&environment==="development"?variants[1]:variants[0]}function createEnvironmentConfig(pausedVariantId,fallthroughVariantId,active){return{revision:0,active,pausedOutcome:{type:"variant",variantId:pausedVariantId},fallthrough:{type:"variant",variantId:fallthroughVariantId},rules:[],reuse:{active:!1,environment:""}}}function formatVariantInput(valueInput,label){let trimmedLabel=label.trim();return trimmedLabel?`${valueInput}=${trimmedLabel}`:valueInput}function getDefaultVariants(kind){switch(kind){case"boolean":return[{id:generateVariantId(),value:!1,label:"Off",description:"not enabled"},{id:generateVariantId(),value:!0,label:"On",description:"enabled"}];case"string":case"number":case"json":throw new Error(`Default variants are not supported for kind: ${kind}`)}}var import_open=__toESM(require_open(),1);var FlagsOpenTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}};async function openFlag(client,argv){let telemetryClient=new FlagsOpenTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(openSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,extraArg]=args,projectName=getProjectNameFromFlags(flags);if(extraArg)return output_manager_default.error(`Too many arguments. Usage: ${getCommandName("flags open [flag]")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link;try{let url=getFlagsDashboardUrl(org.slug,project.name),label="feature flags dashboard";if(flagArg){output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);output_manager_default.stopSpinner(),url=getFlagDashboardUrl(org.slug,project.name,flag.slug),label=`feature flag ${flag.slug}`}client.stdout.isTTY?(output_manager_default.log(`Opening ${label} in your browser...`),output_manager_default.log(`Visit this URL if the browser does not open: ${url}`),(0,import_open.default)(url).catch(()=>{})):client.stdout.write(`${url}
|
|
270
270
|
`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function logArchivedFlagNotice(flag){flag.state==="archived"&&output_manager_default.log("This flag remains archived. Changes will not affect flag evaluation until it is unarchived.")}var import_chalk51=__toESM(require_source(),1),import_fast_deep_equal3=__toESM(require_fast_deep_equal(),1);function findVariantReferencePaths(flag,variantIds){let trackedVariantIds=new Set(variantIds),references=new Map;for(let[environmentName,environmentConfig]of Object.entries(flag.environments))collectEnvironmentReferencePaths(environmentName,environmentConfig,trackedVariantIds,references);return new Map(Array.from(references.entries(),([variantId,paths])=>[variantId,Array.from(paths).sort()]))}function collectEnvironmentReferencePaths(environmentName,environmentConfig,trackedVariantIds,references){collectOutcomeReferencePaths(environmentConfig.pausedOutcome,`${environmentName}.pausedOutcome`,trackedVariantIds,references),collectOutcomeReferencePaths(environmentConfig.fallthrough,`${environmentName}.fallthrough`,trackedVariantIds,references);for(let[ruleIndex,rule]of environmentConfig.rules.entries())collectOutcomeReferencePaths(rule.outcome,`${environmentName}.rules[${ruleIndex}].outcome`,trackedVariantIds,references);if(environmentConfig.targets){for(let[variantId,entityKinds]of Object.entries(environmentConfig.targets))if(trackedVariantIds.has(variantId))for(let[entityKind,attributes]of Object.entries(entityKinds))for(let[attribute,values]of Object.entries(attributes))values.length!==0&&addReferencePath(references,variantId,`${environmentName}.targets.${entityKind}.${attribute}`)}}function collectOutcomeReferencePaths(outcome,basePath,trackedVariantIds,references){if(outcome)switch(outcome.type){case"variant":trackedVariantIds.has(outcome.variantId)&&addReferencePath(references,outcome.variantId,basePath);return;case"split":collectSplitOutcomeReferencePaths(outcome,basePath,trackedVariantIds,references);return;case"rollout":collectRolloutOutcomeReferencePaths(outcome,basePath,trackedVariantIds,references);return;default:return}}function collectSplitOutcomeReferencePaths(outcome,basePath,trackedVariantIds,references){trackedVariantIds.has(outcome.defaultVariantId)&&addReferencePath(references,outcome.defaultVariantId,`${basePath}.default`);for(let variantId of Object.keys(outcome.weights))trackedVariantIds.has(variantId)&&addReferencePath(references,variantId,`${basePath}.weights.${variantId}`)}function collectRolloutOutcomeReferencePaths(outcome,basePath,trackedVariantIds,references){trackedVariantIds.has(outcome.rollFromVariantId)&&addReferencePath(references,outcome.rollFromVariantId,`${basePath}.from`),trackedVariantIds.has(outcome.rollToVariantId)&&addReferencePath(references,outcome.rollToVariantId,`${basePath}.to`),trackedVariantIds.has(outcome.defaultVariantId)&&addReferencePath(references,outcome.defaultVariantId,`${basePath}.default`)}function addReferencePath(references,variantId,path){let paths=references.get(variantId);paths||(paths=new Set,references.set(variantId,paths)),paths.add(path)}var FlagsUpdateTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionVariant(variant){variant&&this.trackCliOption({option:"variant",value:this.redactedValue})}trackCliOptionValue(value){value&&this.trackCliOption({option:"value",value:this.redactedValue})}trackCliOptionLabel(label){label&&this.trackCliOption({option:"label",value:this.redactedValue})}trackCliOptionAddVariant(addVariant){addVariant?.length&&this.trackCliOption({option:"add-variant",value:this.redactedValue})}trackCliOptionRemoveVariant(removeVariant){removeVariant?.length&&this.trackCliOption({option:"remove-variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};var DEFAULT_UPDATE_MESSAGE="Updated via CLI";async function update(client,argv){let telemetryClient=new FlagsUpdateTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(updateSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,variantSelector=normalizeOptionalInput(flags["--variant"]),valueInput=normalizeOptionalInput(flags["--value"]),label=normalizeOptionalInput(flags["--label"]),addVariantInputs=flags["--add-variant"]||[],removeVariantSelectors=flags["--remove-variant"]||[],skipConfirmation=flags["--yes"],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to update"),output_manager_default.log(`Example: ${getCommandName('flags update my-feature --variant control --value welcome-back --label "Welcome back"')}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionVariant(variantSelector),telemetryClient.trackCliOptionValue(valueInput),telemetryClient.trackCliOptionLabel(label),telemetryClient.trackCliOptionAddVariant(addVariantInputs),telemetryClient.trackCliOptionRemoveVariant(removeVariantSelectors),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliFlagYes(skipConfirmation);let hasVariantMutations=addVariantInputs.length>0||removeVariantSelectors.length>0;if(hasVariantMutations&&hasLegacyVariantEditOptions(variantSelector,valueInput,label))return output_manager_default.error("Cannot mix --variant, --value, or --label with --add-variant or --remove-variant."),1;let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{return hasVariantMutations?await updateFlagVariants(client,project.id,flagArg,{addVariantInputs,removeVariantSelectors,skipConfirmation:skipConfirmation||!1,message}):await updateExistingVariant(client,project.id,flagArg,{selector:variantSelector,valueInput,label,message})}catch(err){return output_manager_default.stopSpinner(),isAPIError(err)&&err.status===412?(output_manager_default.error("Flag changed while updating; re-run the command."),1):(printError(err),1)}}async function updateExistingVariant(client,projectId,flagArg,input){output_manager_default.spinner("Fetching flag...");let{flag,etag}=await fetchFlagForUpdate(client,projectId,flagArg);if(output_manager_default.stopSpinner(),logArchivedFlagNotice(flag),rejectExperimentOwnedVariantUpdate(flag))return 1;let variantUpdate=await collectVariantUpdate(client,flag,input),{variants,changedVariants}=applyVariantUpdates(flag,[variantUpdate]);if(changedVariants.length===0)return output_manager_default.warn(`Flag ${import_chalk51.default.bold(flag.slug)} is already up to date`),0;let updateMessage=await resolveOptionalInput(client,input.message,DEFAULT_UPDATE_MESSAGE,"Enter a message for this update:");output_manager_default.spinner("Updating flag..."),await updateFlag(client,projectId,flagArg,{variants,message:updateMessage},{ifMatch:etag}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk51.default.bold(flag.slug)} has been updated`);for(let variant of changedVariants)output_manager_default.log(` ${import_chalk51.default.dim("Variant:")} ${formatVariantForDisplay(variant)}`);return 0}async function updateFlagVariants(client,projectId,flagArg,input){output_manager_default.spinner("Fetching flag...");let{flag,etag}=await fetchFlagForUpdate(client,projectId,flagArg);if(output_manager_default.stopSpinner(),logArchivedFlagNotice(flag),rejectExperimentOwnedVariantUpdate(flag))return 1;if(flag.kind==="boolean")return output_manager_default.error("Boolean flags do not support --add-variant or --remove-variant."),1;let plan=buildVariantMutationPlan(flag,input.addVariantInputs,input.removeVariantSelectors);if(plan.removedVariants.length>0&&!await confirmVariantRemoval(client,flag,plan.removedVariants,input.skipConfirmation))return output_manager_default.log("Aborted"),0;let updateMessage=await resolveOptionalInput(client,input.message,DEFAULT_UPDATE_MESSAGE,"Enter a message for this update:");output_manager_default.spinner("Updating flag..."),await updateFlag(client,projectId,flagArg,{variants:plan.variants,message:updateMessage},{ifMatch:etag}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk51.default.bold(flag.slug)} has been updated`);for(let variant of plan.addedVariants)output_manager_default.log(` ${import_chalk51.default.dim("Added:")} ${formatVariantForLog(variant)}`);for(let variant of plan.removedVariants)output_manager_default.log(` ${import_chalk51.default.dim("Removed:")} ${formatVariantForLog(variant)}`);return 0}function rejectExperimentOwnedVariantUpdate(flag){if(!flag.experiment)return!1;let experiment=flag.experiment.id?`experiment ${import_chalk51.default.bold(flag.experiment.id)}`:"an experiment";return output_manager_default.error(`Flag ${import_chalk51.default.bold(flag.slug)} is managed by ${experiment}. Update its variants with ${getCommandName("experiments update <experiment> --file <file>")}.`),!0}function hasLegacyVariantEditOptions(variantSelector,valueInput,label){return variantSelector!==void 0||valueInput!==void 0||label!==void 0}function buildVariantMutationPlan(flag,addVariantInputs,removeVariantSelectors){let removedVariants=resolveRemovedVariants(flag.variants,removeVariantSelectors);assertVariantRemovalsAreAllowed(flag,removedVariants);let baseIndex=flag.variants.length-removedVariants.length,addedVariants=parseAddedVariants(flag,addVariantInputs,baseIndex),removedVariantIds=new Set(removedVariants.map(variant=>variant.id)),variants=flag.variants.filter(variant=>!removedVariantIds.has(variant.id)).map(variant=>({...variant}));return variants.push(...addedVariants),assertUniqueVariantValues(variants),{variants,addedVariants,removedVariants}}function parseAddedVariants(flag,addVariantInputs,baseIndex){let kind=flag.kind;if(kind==="boolean")throw new Error("Boolean flags do not support adding variants.");return addVariantInputs.map((input,index)=>parseVariantInput(input,kind,baseIndex+index))}function resolveRemovedVariants(variants,removeVariantSelectors){let removedVariantIds=new Set;return removeVariantSelectors.map(selector=>{let result=resolveVariant(selector,variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${selector}" not found`);if(removedVariantIds.has(result.variant.id))throw new Error(`Duplicate --remove-variant selector ${import_chalk51.default.bold(selector)} resolves to ${formatVariantForLog(result.variant)}.`);return removedVariantIds.add(result.variant.id),result.variant})}function assertVariantRemovalsAreAllowed(flag,removedVariants){let referencePaths=findVariantReferencePaths(flag,removedVariants.map(variant=>variant.id));if(referencePaths.size===0)return;let referencedVariants=removedVariants.filter(variant=>referencePaths.has(variant.id)),detailLines=referencedVariants.map(variant=>{let paths=referencePaths.get(variant.id)??[];return` - ${formatVariantForLog(variant)} referenced by ${paths.join(", ")}`});throw new Error(`Cannot remove variant${referencedVariants.length===1?"":"s"} because ${referencedVariants.length===1?"it is":"they are"} still referenced:
|
|
271
271
|
${detailLines.join(`
|
|
272
|
-
`)}`)}function assertUniqueVariantValues(variants){for(let index=0;index<variants.length;index++){let variant=variants[index],duplicateVariant=variants.slice(0,index).find(candidate=>(0,import_fast_deep_equal3.default)(candidate.value,variant.value));if(duplicateVariant)throw new Error(`Variant value ${formatVariantValue(variant.value)} would be duplicated by ${formatVariantForLog(duplicateVariant)} and ${formatVariantForLog(variant)}.`)}}async function confirmVariantRemoval(client,flag,removedVariants,skipConfirmation){if(skipConfirmation)return!0;if(!client.stdin.isTTY)throw new Error("Missing required
|
|
272
|
+
`)}`)}function assertUniqueVariantValues(variants){for(let index=0;index<variants.length;index++){let variant=variants[index],duplicateVariant=variants.slice(0,index).find(candidate=>(0,import_fast_deep_equal3.default)(candidate.value,variant.value));if(duplicateVariant)throw new Error(`Variant value ${formatVariantValue(variant.value)} would be duplicated by ${formatVariantForLog(duplicateVariant)} and ${formatVariantForLog(variant)}.`)}}async function confirmVariantRemoval(client,flag,removedVariants,skipConfirmation){if(skipConfirmation)return!0;if(!client.stdin.isTTY)throw new Error("Missing required option --yes. Use --yes to skip the removal confirmation prompt in non-interactive mode.");let promptLines=removedVariants.map(variant=>` - ${formatVariantForLog(variant)}`).join(`
|
|
273
273
|
`);return client.input.confirm(`Remove ${removedVariants.length} variant${removedVariants.length===1?"":"s"} from ${import_chalk51.default.bold(flag.slug)}?
|
|
274
|
-
${promptLines}`,!1)}function formatVariantForLog(variant){return`${formatVariantForDisplay(variant)} ${import_chalk51.default.dim(`[id: ${variant.id}]`)}`}async function collectVariantUpdate(client,flag,input){let selectedVariant=await resolveSelectedVariant(client,flag,input.selector),nextValueInput=input.valueInput,nextLabel=input.label;return flag.kind!=="boolean"&&nextValueInput===void 0&&client.stdin.isTTY&&(nextValueInput=await promptForVariantValueUpdate(client,flag,selectedVariant)),nextLabel===void 0&&client.stdin.isTTY&&(nextLabel=await promptForVariantLabelUpdate(client,selectedVariant)),client.stdin.isTTY||ensureVariantUpdateInput(nextValueInput,nextLabel),{selector:selectedVariant.id,valueInput:nextValueInput,label:nextLabel}}function ensureVariantUpdateInput(valueInput,label){if(!valueInput&&!label)throw new Error("At least one of --value or --label must be provided. Use --value <VALUE>, --label <LABEL>, or run interactively in a terminal.")}async function resolveSelectedVariant(client,flag,selector){if(selector){let result=resolveVariant(selector,flag.variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${selector}" not found`);return result.variant}if(!client.stdin.isTTY)throw new Error("Missing required flag --variant. Use --variant <VARIANT>, or run interactively in a terminal.");let selectedVariantId=await client.input.select({message:"Select a variant to update:",choices:flag.variants.map(variant=>({name:formatVariantForLog(variant),value:variant.id}))}),selectedVariant=flag.variants.find(v=>v.id===selectedVariantId);if(!selectedVariant)throw new Error("No variant selected");return selectedVariant}async function promptForVariantValueUpdate(client,flag,selectedVariant){let valueResponse=await client.input.text({message:`Enter a new value for ${formatVariantForDisplay(selectedVariant)} (press Enter to keep ${formatVariantValue(selectedVariant.value)}):`,validate:value=>{if(!value.trim())return!0;let result=validateVariantValue(value,flag.kind);return result===null?!0:result}});return normalizeOptionalInput(valueResponse)}async function promptForVariantLabelUpdate(client,selectedVariant){let currentLabel=selectedVariant.label,labelResponse=await client.input.text({message:currentLabel?`Enter a new label for ${formatVariantForDisplay(selectedVariant)} (press Enter to keep ${JSON.stringify(currentLabel)}):`:`Enter an optional label for ${formatVariantForDisplay(selectedVariant)} (press Enter to skip):`});return normalizeOptionalInput(labelResponse)}function applyVariantUpdates(flag,updates){let variants=flag.variants.map(variant=>({...variant})),changedVariantIds=new Set;for(let update2 of updates){let result=resolveVariant(update2.selector,variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${update2.selector}" not found`);let nextValue=update2.valueInput!==void 0?parseUpdatedVariantValue(update2.valueInput,flag.kind,result.variant):result.variant.value,nextLabel=update2.label??result.variant.label,variantIndex=variants.findIndex(v=>v.id===result.variant.id),existingVariant=variants[variantIndex],hasChanged=!(0,import_fast_deep_equal3.default)(existingVariant.value,nextValue)||existingVariant.label!==nextLabel;variants[variantIndex]={...existingVariant,value:nextValue,label:nextLabel},hasChanged&&changedVariantIds.add(existingVariant.id)}return{variants,changedVariants:variants.filter(variant=>changedVariantIds.has(variant.id))}}function parseUpdatedVariantValue(valueInput,kind,existingVariant){let validationError=validateVariantValue(valueInput,kind);if(validationError)throw new Error(validationError);if(kind==="boolean"){let nextValue=valueInput.toLowerCase()==="true";if(nextValue!==existingVariant.value)throw new Error("Boolean variant values cannot be changed. You can update the label only.");return nextValue}return kind==="number"?Number(valueInput):kind==="json"?JSON.parse(valueInput):valueInput}var import_chalk53=__toESM(require_source(),1);var import_chalk52=__toESM(require_source(),1);async function resolveFlagEnvironment(client,flag,environment,promptMessage,options={}){let nextEnvironment=environment;if(!nextEnvironment){if(!canPrompt(client))throw new Error("Missing required flag --environment. Use --environment <ENV>, or run interactively in a terminal.");let availableEnvironments=STANDARD_ENVIRONMENTS.filter(env=>Object.prototype.hasOwnProperty.call(flag.environments,env));if(availableEnvironments.length===0)throw new Error("No valid environments found for this flag");options.showEnvironmentDetails&&printFlagEnvironmentDetails(flag,void 0,availableEnvironments),nextEnvironment=await client.input.select({message:promptMessage,choices:availableEnvironments.map(env=>({name:options.decorateChoices===!1?env:formatEnvironmentChoiceLabel(env,flag.environments[env]),value:env}))})}if(!STANDARD_ENVIRONMENTS.includes(nextEnvironment))throw new Error(`Invalid environment: ${nextEnvironment}. Must be one of: ${STANDARD_ENVIRONMENTS.join(", ")}`);if(!flag.environments[nextEnvironment])throw new Error(`Environment ${nextEnvironment} not found for this flag`);return nextEnvironment}function formatEnvironmentChoiceLabel(envName,envConfig){let status2=envConfig?.active?import_chalk52.default.green("active"):import_chalk52.default.yellow("paused");return`${envName} (${status2})`}function isPausingEnvironmentToVariant(envConfig,variantId){return!envConfig.active&&envConfig.pausedOutcome?.variantId===variantId}function buildTargetingVariantEnvironmentConfig(envConfig,variantId){return buildOutcomeEnvConfig(envConfig,{outcome:{type:"variant",variantId},defaultVariantId:variantId})}function buildResumeTargetingEnvironmentConfig(flag,environment){let envConfig=flag.environments[environment],fallthrough=resolveEffectiveFallthrough(flag,environment),defaultVariantId=getFallthroughDefaultVariantId(fallthrough);return buildOutcomeEnvConfig(envConfig,{outcome:fallthrough,defaultVariantId})}function resolveEffectiveFallthrough(flag,environment){let envConfig=flag.environments[environment],inheritedFrom=envConfig.reuse?.active?envConfig.reuse.environment:void 0;if(inheritedFrom){let inheritedConfig=flag.environments[inheritedFrom];if(inheritedConfig)return structuredClone(inheritedConfig.fallthrough)}return structuredClone(envConfig.fallthrough)}function isUsableFallthrough(fallthrough,variants){let variantIds=new Set(variants.map(variant=>variant.id));return fallthrough.type==="variant"?variantIds.has(fallthrough.variantId):fallthrough.type==="split"?variantIds.has(fallthrough.defaultVariantId):fallthrough.type==="experiment"?!1:variantIds.has(fallthrough.defaultVariantId)&&variantIds.has(fallthrough.rollFromVariantId)&&variantIds.has(fallthrough.rollToVariantId)}function getFallthroughDefaultVariantId(fallthrough){if(fallthrough.type==="variant")return fallthrough.variantId;if(fallthrough.type==="experiment")throw new Error("Experiment outcomes do not have a default variant");return fallthrough.defaultVariantId}function buildPausedEnvironmentConfig(envConfig,variantId){return{...envConfig,active:!1,pausedOutcome:{type:"variant",variantId}}}function buildOutcomeEnvConfig(envConfig,options){let{reuse,...restConfig}=envConfig,nextConfig={...restConfig,active:!0,pausedOutcome:envConfig.pausedOutcome??{type:"variant",variantId:options.defaultVariantId},fallthrough:options.outcome};return reuse&&(nextConfig.reuse={...reuse,active:!1}),nextConfig}function getBooleanVariant(flag,value){let variant=flag.variants.find(candidate=>candidate.value===value);if(!variant)throw new Error(`Flag ${import_chalk52.default.bold(flag.slug)} is missing the standard boolean variants`);return variant}async function resolveFlagUpdateMessage(client,message,defaultMessage){if(message!==void 0)return message;if(!canPrompt(client))return defaultMessage;let response=await client.input.text({message:"Enter a message for this update:",default:defaultMessage});return normalizeOptionalInput(response)||defaultMessage}var FlagsSetTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionVariant(variant){variant&&this.trackCliOption({option:"variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function set(client,argv){let telemetryClient=new FlagsSetTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(setSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],variantSelector=normalizeOptionalInput(flags["--variant"]),message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to set"),output_manager_default.log(`Example: ${getCommandName("flags set my-feature --environment production --variant true")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionVariant(variantSelector),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to set the variant in:",{showEnvironmentDetails:!0,decorateChoices:!1}),selectedVariant=await resolveVariantToSet(client,flag,variantSelector),envConfig=flag.environments[selectedEnvironment];if(isPausingEnvironmentToVariant(envConfig,selectedVariant.id))return output_manager_default.warning(`Flag ${import_chalk53.default.bold(flag.slug)} is already ${flag.state==="archived"?"configured with":"serving"} ${formatVariantForDisplay(selectedVariant)} in ${selectedEnvironment}`),0;let presentation=getSetPresentation(flag,selectedVariant),updateMessage=await resolveFlagUpdateMessage(client,message,presentation.defaultMessage(selectedEnvironment));output_manager_default.spinner(presentation.spinner(selectedEnvironment)),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:buildPausedEnvironmentConfig(envConfig,selectedVariant.id)},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(flag.state==="archived"?`Archived flag ${import_chalk53.default.bold(flag.slug)} configuration has been updated in ${import_chalk53.default.bold(selectedEnvironment)}`:presentation.success(flag.slug,selectedEnvironment)),output_manager_default.log(` ${import_chalk53.default.dim(flag.state==="archived"?"Configured variant:":"Serving variant:")} ${formatVariantForDisplay(selectedVariant)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveVariantToSet(client,flag,selector){if(selector){let result=resolveVariant(selector,flag.variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${selector}" not found`);return result.variant}if(!client.stdin.isTTY)throw new Error("Missing required flag --variant. Use --variant <VARIANT>, or run interactively in a terminal.");let selectedVariantId=await client.input.select({message:"Select a variant to serve:",choices:flag.variants.map(variant=>({name:formatVariantForDisplay(variant),value:variant.id}))}),selectedVariant=flag.variants.find(variant=>variant.id===selectedVariantId);if(!selectedVariant)throw new Error("No variant selected");return selectedVariant}function getSetPresentation(flag,variant){return flag.kind==="boolean"&&variant.value===!0?{spinner:environment=>`Enabling flag in ${environment}...`,success:(slug,environment)=>`Feature flag ${import_chalk53.default.bold(slug)} has been enabled in ${import_chalk53.default.bold(environment)}`,defaultMessage:environment=>`Enabled for ${environment} via CLI`}:flag.kind==="boolean"&&variant.value===!1?{spinner:environment=>`Disabling flag in ${environment}...`,success:(slug,environment)=>`Feature flag ${import_chalk53.default.bold(slug)} has been disabled in ${import_chalk53.default.bold(environment)}`,defaultMessage:environment=>`Disabled for ${environment} via CLI`}:{spinner:environment=>`Setting variant in ${environment}...`,success:(slug,environment)=>`Feature flag ${import_chalk53.default.bold(slug)} has been set in ${import_chalk53.default.bold(environment)}`,defaultMessage:environment=>`Set variant for ${environment} via CLI`}}var import_chalk54=__toESM(require_source(),1),import_fast_deep_equal4=__toESM(require_fast_deep_equal(),1);var FlagsUseTargetingTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionDefaultVariant(variant){variant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}trackCliOptionProject(project){project&&this.trackCliOption({option:"project",value:this.redactedValue})}};async function useTargeting(client,argv){let telemetryClient=new FlagsUseTargetingTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(useTargetingSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to use targeting for"),output_manager_default.log(`Example: ${getCommandName("flags targeting enable my-feature --environment production")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to use targeting in:",{showEnvironmentDetails:!0,decorateChoices:!1}),envConfig=flag.environments[selectedEnvironment],nextEnvConfig=await resolveNextTargetingEnvironmentConfig(client,flag,selectedEnvironment,defaultVariantSelector);if((0,import_fast_deep_equal4.default)(envConfig,nextEnvConfig))return output_manager_default.warn(flag.state==="archived"?`Archived flag ${import_chalk54.default.bold(flag.slug)} is already configured to use targeting in ${import_chalk54.default.bold(selectedEnvironment)}`:formatAlreadyUsingTargetingWarning(flag,selectedEnvironment,nextEnvConfig)),0;let updateMessage=await resolveFlagUpdateMessage(client,message,`Activated targeting for ${selectedEnvironment} via CLI`);output_manager_default.spinner(`Activating targeting in ${selectedEnvironment}...`),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:nextEnvConfig},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk54.default.bold(flag.slug)} ${flag.state==="archived"?"is configured to use targeting":"now uses targeting"} in ${import_chalk54.default.bold(selectedEnvironment)}`),output_manager_default.log(` ${import_chalk54.default.dim("Fallthrough:")} ${formatFlagOutcome(nextEnvConfig.fallthrough,flag.variants)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveNextTargetingEnvironmentConfig(client,flag,environment,defaultVariantSelector){if(defaultVariantSelector){let variant=resolveDefaultVariantOrThrow(flag,defaultVariantSelector);return buildTargetingVariantEnvironmentConfig(flag.environments[environment],variant.id)}let fallthrough=resolveEffectiveFallthrough(flag,environment);if(isUsableFallthrough(fallthrough,flag.variants))return buildResumeTargetingEnvironmentConfig(flag,environment);let selectedVariant=await resolveReplacementDefaultVariant(client,flag,fallthrough);return buildTargetingVariantEnvironmentConfig(flag.environments[environment],selectedVariant.id)}function resolveDefaultVariantOrThrow(flag,selector){let result=resolveVariant(selector,flag.variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${selector}" not found`);return result.variant}async function resolveReplacementDefaultVariant(client,flag,fallthrough){if(!canPrompt(client))throw new Error(`Couldn't resume targeting because the current fallthrough references a missing variant. Pass --default-variant <VARIANT>${describeUnusableFallthrough(fallthrough)}.`);output_manager_default.warn(`Current fallthrough references a missing variant${describeUnusableFallthrough(fallthrough)}. Choose a new default variant.`);let selectedVariantId=await client.input.select({message:"Select a default variant when no rules match:",choices:flag.variants.map(variant=>({name:formatVariantForDisplay(variant),value:variant.id}))}),selectedVariant=flag.variants.find(variant=>variant.id===selectedVariantId);if(!selectedVariant)throw new Error("No variant selected");return selectedVariant}function describeUnusableFallthrough(fallthrough){return fallthrough.type==="variant"?` (${fallthrough.variantId})`:fallthrough.type==="experiment"?" (experiment assignment)":` (${fallthrough.type} default ${fallthrough.defaultVariantId})`}function formatAlreadyUsingTargetingWarning(flag,environment,envConfig){let{fallthrough}=envConfig;if(fallthrough.type==="variant"){let variant=flag.variants.find(candidate=>candidate.id===fallthrough.variantId),label=variant?formatVariantForDisplay(variant):fallthrough.variantId;return`Flag ${import_chalk54.default.bold(flag.slug)} already uses targeting with default ${label} in ${environment}`}return`Flag ${import_chalk54.default.bold(flag.slug)} already uses targeting in ${environment}`}var import_chalk57=__toESM(require_source(),1),import_fast_deep_equal5=__toESM(require_fast_deep_equal(),1);var import_chalk56=__toESM(require_source(),1);var import_chalk55=__toESM(require_source(),1);function resolveFlagBucketingBase(settings,selector){let separatorIndex=selector.indexOf(".");if(separatorIndex<=0||separatorIndex===selector.length-1)throw new Error("Invalid value for --by. Use the format <entity.attribute>, for example --by user.userId.");let kind=selector.slice(0,separatorIndex),attribute=selector.slice(separatorIndex+1),entity=settings.entities.find(candidate=>candidate.kind===kind);if(!entity){let availableKinds=settings.entities.map(candidate=>candidate.kind);throw new Error(`Unknown entity ${import_chalk55.default.bold(kind)}. Available entities: ${availableKinds.join(", ")}`)}let matchingAttribute=entity.attributes.find(candidate=>candidate.key===attribute);if(!matchingAttribute){let availableAttributes=entity.attributes.map(candidate=>candidate.key);throw new Error(`Unknown attribute ${import_chalk55.default.bold(selector)}. Available attributes for ${kind}: ${availableAttributes.join(", ")}`)}if(!isBucketingAttribute(matchingAttribute))throw new Error(`Attribute ${import_chalk55.default.bold(selector)} is a Timestamp and cannot be used for bucketing. Choose a string or number attribute.`);return{type:"entity",kind,attribute}}function formatFlagBucketingBaseSelector(base){if(base)return`${base.kind}.${base.attribute}`}function resolveFlagSplit(flag,settings,options){let currentSplit=options.currentOutcome?.type==="split"?options.currentOutcome:void 0,baseSelector=options.baseSelector||formatFlagBucketingBaseSelector(currentSplit?.base);if(!baseSelector)throw new Error("Missing required flag --by. Use --by <entity.attribute> to choose how users are bucketed.");let base=resolveFlagBucketingBase(settings,baseSelector),weights=resolveSplitWeights(flag,options.weightInputs,currentSplit),defaultVariant=resolveDefaultVariant(flag,options.defaultVariantSelector,currentSplit);return{outcome:{type:"split",base,weights,defaultVariantId:defaultVariant.id},defaultVariant,baseLabel:`${base.kind}.${base.attribute}`,summary:formatSplitSummary(flag.variants,weights)}}function resolveSplitWeights(flag,weightInputs,currentSplit){if(weightInputs.length===0&¤tSplit)return validateAndNormalizeWeights(flag,currentSplit.weights);if(weightInputs.length===0)throw new Error("At least one --weight is required. Use --weight <VARIANT=WEIGHT> for each variant, or run interactively in a terminal.");let weights={},seen=new Set;for(let input of weightInputs){let{variantSelector,weight}=parseWeightInput(input),variant=resolveVariantOrThrow(variantSelector,flag.variants,"--weight");if(seen.has(variant.id))throw new Error(`Duplicate weight for variant ${import_chalk56.default.bold(formatVariantForDisplay(variant))}.`);seen.add(variant.id),weights[variant.id]=weight}let missingVariants=flag.variants.filter(variant=>!seen.has(variant.id));if(missingVariants.length>0)throw new Error(`Missing weights for variants: ${missingVariants.map(variant=>formatVariantForDisplay(variant)).join(", ")}. Use --weight <VARIANT=WEIGHT> for each variant, including 0 for variants that should receive no traffic.`);return validateAndNormalizeWeights(flag,weights)}function parseWeightInput(input){let separatorIndex=input.lastIndexOf("=");if(separatorIndex<=0||separatorIndex===input.length-1)throw new Error(`Invalid weight ${import_chalk56.default.bold(input)}. Use --weight <VARIANT=WEIGHT>, for example --weight true=5.`);let variantSelector=input.slice(0,separatorIndex).trim(),rawWeight=input.slice(separatorIndex+1).trim();if(!variantSelector)throw new Error(`Invalid weight ${import_chalk56.default.bold(input)}. Variant cannot be empty.`);if(!rawWeight)throw new Error(`Invalid weight ${import_chalk56.default.bold(input)}. Weight cannot be empty.`);let weight=Number(rawWeight);if(!Number.isFinite(weight)||weight<0)throw new Error(`Invalid weight "${rawWeight}". Use a number greater than or equal to 0.`);return{variantSelector,weight}}function validateAndNormalizeWeights(flag,weights){let normalizedWeights=Object.fromEntries(flag.variants.map(variant=>[variant.id,weights[variant.id]??0]));if(Object.values(normalizedWeights).reduce((sum,weight)=>sum+weight,0)<=0)throw new Error("At least one weight must be greater than 0.");return normalizedWeights}function resolveDefaultVariant(flag,selector,currentSplit){if(selector)return resolveVariantOrThrow(selector,flag.variants,"--default-variant");if(currentSplit)return resolveVariantByIdOrThrow(currentSplit.defaultVariantId,flag.variants,"--default-variant");if(flag.kind==="boolean")return getBooleanVariant(flag,!1);throw new Error("Missing required flag --default-variant. Use --default-variant <VARIANT> for non-boolean splits.")}function formatSplitSummary(variants,weights){let total=Object.values(weights).reduce((sum,weight)=>sum+weight,0);return variants.map(variant=>{let weight=weights[variant.id]??0,percentage=total>0?weight/total*100:0;return`${formatPlainVariant(variant)}: ${formatPercentage(percentage)}`}).join(", ")}function formatPlainVariant(variant){let value=formatVariantValue(variant.value);return variant.label?`${variant.label} (${value})`:value}function formatPercentage(percentage){return Number.isInteger(percentage)?`${percentage}%`:`${Number(percentage.toFixed(2))}%`}var FlagsSplitTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionBy(base){base&&this.trackCliOption({option:"by",value:this.redactedValue})}trackCliOptionWeight(weights){weights?.length&&this.trackCliOption({option:"weight",value:this.redactedValue})}trackCliOptionDefaultVariant(variant){variant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function split(client,argv){let telemetryClient=new FlagsSplitTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(splitSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],baseSelector=normalizeOptionalInput(flags["--by"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),weightInputs=flags["--weight"]||[],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to split"),output_manager_default.log(`Example: ${getCommandName("flags split my-feature --environment production --by user.userId --weight false=95 --weight true=5")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionWeight(weightInputs.length>0?[weightInputs[0]]:void 0),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let[flag,settings]=await Promise.all([getFlag(client,project.id,flagArg),getFlagSettings(client,project.id)]);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to split traffic in:",{showEnvironmentDetails:!0,decorateChoices:!1}),envConfig=flag.environments[selectedEnvironment],currentSplit=envConfig.fallthrough.type==="split"?envConfig.fallthrough:void 0,shouldPromptCurrentSplit=canPrompt(client)&¤tSplit!==void 0&&!baseSelector&&weightInputs.length===0&&!defaultVariantSelector&&!message,resolvedBaseSelector=await resolveBaseSelector(client,settings,baseSelector,currentSplit,shouldPromptCurrentSplit),resolvedWeightInputs=await resolveWeightInputs(client,flag,weightInputs,currentSplit,shouldPromptCurrentSplit),resolvedDefaultVariantSelector=await resolveDefaultVariantSelector(client,flag,defaultVariantSelector,currentSplit,shouldPromptCurrentSplit),splitConfig=resolveFlagSplit(flag,settings,{baseSelector:resolvedBaseSelector,weightInputs:resolvedWeightInputs,defaultVariantSelector:resolvedDefaultVariantSelector,currentOutcome:envConfig.fallthrough.type==="experiment"?void 0:envConfig.fallthrough}),nextEnvironmentConfig=buildOutcomeEnvConfig(envConfig,{outcome:splitConfig.outcome,defaultVariantId:splitConfig.defaultVariant.id});if(!message&&envConfig.active&&(0,import_fast_deep_equal5.default)(envConfig.fallthrough,splitConfig.outcome)&&(0,import_fast_deep_equal5.default)(envConfig,nextEnvironmentConfig))return output_manager_default.warn(`Flag ${import_chalk57.default.bold(flag.slug)} is already configured with this split in ${selectedEnvironment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultSplitMessage(selectedEnvironment,splitConfig));output_manager_default.spinner(`Updating split in ${selectedEnvironment}...`),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:nextEnvironmentConfig},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk57.default.bold(flag.slug)} split has been updated in ${import_chalk57.default.bold(selectedEnvironment)}`),output_manager_default.log(` ${import_chalk57.default.dim("Based on:")} ${splitConfig.baseLabel}`),output_manager_default.log(` ${import_chalk57.default.dim("Fallback:")} ${formatVariantForDisplay(splitConfig.defaultVariant)}`),output_manager_default.log(` ${import_chalk57.default.dim("Weights:")} ${splitConfig.summary}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function getDefaultSplitMessage(environment,splitConfig){return`Configure split for ${environment}: ${splitConfig.summary}`}async function resolveBaseSelector(client,settings,baseSelector,currentSplit,shouldPromptCurrentSplit){if(baseSelector||currentSplit&&!shouldPromptCurrentSplit)return baseSelector;if(!canPrompt(client))return;let choices=settings.entities.flatMap(entity=>entity.attributes.filter(isBucketingAttribute).map(attribute=>({name:`${entity.label} \u203A ${attribute.key}`,value:`${entity.kind}.${attribute.key}`}))),currentBaseSelector=formatFlagBucketingBaseSelector(currentSplit?.base),defaultChoice=choices.find(choice=>choice.value===currentBaseSelector)?.value;if(choices.length===0)throw new Error("No entities are configured for weighted splits.");return client.input.select({message:"Select an attribute to split by:",choices,default:defaultChoice})}async function resolveWeightInputs(client,flag,weightInputs,currentSplit,shouldPromptCurrentSplit){if(weightInputs.length>0||currentSplit&&!shouldPromptCurrentSplit||!canPrompt(client))return weightInputs;output_manager_default.log("Enter weights for each variant. Weights are ratios; use 0 for variants that should receive no traffic.");let promptedWeights=[];for(let variant of flag.variants){let defaultWeight=currentSplit?.weights[variant.id]!==void 0?String(currentSplit.weights[variant.id]):currentSplit?"0":"1",weight=await client.input.text({message:`Weight for ${formatVariantForDisplay(variant)}:`,default:defaultWeight,validate:value=>{let trimmed=value.trim();if(!trimmed)return"Enter a weight";let parsed=Number(trimmed);return!Number.isFinite(parsed)||parsed<0?"Enter a number greater than or equal to 0":!0}});promptedWeights.push(`${variant.id}=${weight.trim()}`)}return promptedWeights}async function resolveDefaultVariantSelector(client,flag,defaultVariantSelector,currentSplit,shouldPromptCurrentSplit){if(defaultVariantSelector||currentSplit&&!shouldPromptCurrentSplit||flag.kind==="boolean"&&!canPrompt(client))return defaultVariantSelector;if(canPrompt(client))return client.input.select({message:"Select a fallback variant:",choices:flag.variants.map(variant=>({name:formatVariantForDisplay(variant),value:variant.id})),default:flag.variants.find(variant=>variant.id===currentSplit?.defaultVariantId)?.id||getBooleanFallbackVariantId(flag)})}function getBooleanFallbackVariantId(flag){if(flag.kind==="boolean")return flag.variants.find(variant=>variant.value===!1)?.id}var import_chalk59=__toESM(require_source(),1),import_fast_deep_equal6=__toESM(require_fast_deep_equal(),1);var import_chalk58=__toESM(require_source(),1),import_ms3=__toESM(require_ms(),1);function resolveFlagRollout(flag,settings,options){let currentRollout=options.currentOutcome?.type==="rollout"?options.currentOutcome:void 0,baseSelector=options.baseSelector||formatFlagBucketingBaseSelector(currentRollout?.base);if(!baseSelector)throw new Error("Missing required flag --by. Use --by <entity.attribute> to choose how users are bucketed.");let base=resolveFlagBucketingBase(settings,baseSelector),rollFromVariant=resolveRollFromVariant(flag,options.rollFromVariantSelector,currentRollout),rollToVariant=resolveRollToVariant(flag,options.rollToVariantSelector,currentRollout);if(rollFromVariant.id===rollToVariant.id)throw new Error("`--from-variant` and `--to-variant` must resolve to different variants.");let defaultVariant=resolveDefaultVariant2(flag,options.defaultVariantSelector,currentRollout,rollFromVariant),slots=options.stageInputs.length>0?parseStageInputs(options.stageInputs):currentRollout?.slots;if(!slots||slots.length===0)throw new Error("At least one --stage is required. Use --stage <PERCENTAGE,DURATION>, for example --stage 5,6h.");let finalPromille=options.finalPercentage===void 0?currentRollout?.finalPromille:parseFinalPercentage(options.finalPercentage),startTimestamp=resolveRolloutStartTimestamp(options.start,currentRollout?.startTimestamp);return{outcome:{type:"rollout",base,startTimestamp,rollFromVariantId:rollFromVariant.id,rollToVariantId:rollToVariant.id,defaultVariantId:defaultVariant.id,slots,...finalPromille!==void 0&&{finalPromille}},defaultVariant,rollFromVariant,rollToVariant,baseLabel:`${base.kind}.${base.attribute}`,summary:formatRolloutStages(slots,finalPromille),startLabel:formatStartLabel(options.start,currentRollout?.startTimestamp)}}function resolveRollFromVariant(flag,selector,currentRollout){return selector?resolveVariantOrThrow(selector,flag.variants,"--from-variant"):currentRollout?resolveVariantByIdOrThrow(currentRollout.rollFromVariantId,flag.variants,"--from-variant"):inferBooleanVariant(flag,!1,"--from-variant")}function resolveRollToVariant(flag,selector,currentRollout){return selector?resolveVariantOrThrow(selector,flag.variants,"--to-variant"):currentRollout?resolveVariantByIdOrThrow(currentRollout.rollToVariantId,flag.variants,"--to-variant"):inferBooleanVariant(flag,!0,"--to-variant")}function resolveDefaultVariant2(flag,selector,currentRollout,rollFromVariant){return selector?resolveVariantOrThrow(selector,flag.variants,"--default-variant"):currentRollout?resolveVariantByIdOrThrow(currentRollout.defaultVariantId,flag.variants,"--default-variant"):rollFromVariant}function inferBooleanVariant(flag,value,optionName){if(flag.kind!=="boolean")throw new Error(`Missing required flag ${optionName}. Use ${optionName} <VARIANT> for non-boolean rollouts.`);let variant=flag.variants.find(candidate=>candidate.value===value);if(!variant)throw new Error(`Flag ${import_chalk58.default.bold(flag.slug)} is missing the standard boolean variants`);return variant}function parseStageInputs(stageInputs){let slots=stageInputs.map(parseStageInput);for(let index=1;index<slots.length;index++)if(slots[index].promille<=slots[index-1].promille)throw new Error("Stage percentages must be in ascending order.");return slots}function parseStageInput(input){let parts=input.split(",").map(part=>part.trim());if(parts.length!==2)throw new Error(`Invalid stage ${import_chalk58.default.bold(input)}. Use --stage <PERCENTAGE,DURATION>, for example --stage 5,6h.`);let percentage=Number(parts[0]);if(!Number.isFinite(percentage)||percentage<=0||percentage>=100||!Number.isInteger(percentage*1e3))throw new Error(`Invalid stage percentage "${parts[0]}". Use a number greater than 0 and less than 100 with up to 3 decimal places.`);let durationMs=parseStageDuration(parts[1]);if(durationMs===void 0)throw new Error(`Invalid duration "${parts[1]}". Use minutes (e.g. "30m"), hours (e.g. "6h"), or days (e.g. "1d"). Seconds are not supported.`);return{durationMs,promille:Math.round(percentage*1e3)}}function parseStageDuration(value){if(!value||/^\d+(s|ms)$/i.test(value))return;let durationMs=(0,import_ms3.default)(/^\d+$/.test(value)?`${value}m`:value);if(durationMs===void 0||durationMs<=0)return;let roundedMinutes=Math.round(durationMs/6e4);if(!(roundedMinutes<=0))return roundedMinutes*6e4}function resolveRolloutStartTimestamp(start,currentStartTimestamp){if(start===void 0)return currentStartTimestamp??Date.now();if(start==="now")return Date.now();let relativeDurationMs=(0,import_ms3.default)(start);if(relativeDurationMs!==void 0){if(relativeDurationMs<=0)throw new Error(`Invalid start time "${start}". Use "now", a future relative duration such as "1h", or an ISO 8601 datetime.`);return Date.now()+relativeDurationMs}let absoluteTime=new Date(start).getTime();if(Number.isNaN(absoluteTime))throw new Error(`Invalid start time "${start}". Use "now", a future relative duration such as "1h", or an ISO 8601 datetime.`);return absoluteTime}function parseFinalPercentage(input){let percentage=Number(input);if(input.trim()===""||!Number.isFinite(percentage)||percentage<0||percentage>100||Math.round(percentage*1e3)/1e3!==percentage)throw new Error(`Invalid final percentage "${input}". Use --final-percentage with a number between 0 and 100 with up to 3 decimal places.`);return Math.round(percentage*1e3)}function formatRolloutStages(slots,finalPromille=1e5){return`${slots.map(slot=>`${formatPromille(slot.promille)} for ${(0,import_ms3.default)(slot.durationMs,{long:!0})}`).join(", ")}, then ${formatPromille(finalPromille)} indefinitely`}function formatPromille(promille){let percentage=promille/1e3;return Number.isInteger(percentage)?`${percentage}%`:`${Number(percentage.toFixed(3))}%`}function formatStartLabel(start,currentStartTimestamp){return start===void 0?currentStartTimestamp?"preserve current start time":"immediately":start==="now"?"immediately":`start at ${start}`}var FlagsRolloutTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionFromVariant(variant){variant&&this.trackCliOption({option:"from-variant",value:this.redactedValue})}trackCliOptionToVariant(variant){variant&&this.trackCliOption({option:"to-variant",value:this.redactedValue})}trackCliOptionDefaultVariant(variant){variant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionBy(base){base&&this.trackCliOption({option:"by",value:this.redactedValue})}trackCliOptionStage(stages){stages?.length&&this.trackCliOption({option:"stage",value:this.redactedValue})}trackCliOptionFinalPercentage(percentage){percentage!==void 0&&this.trackCliOption({option:"final-percentage",value:this.redactedValue})}trackCliOptionStart(start){start&&this.trackCliOption({option:"start",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function rollout(client,argv){let telemetryClient=new FlagsRolloutTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rolloutSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],rollFromVariantSelector=normalizeOptionalInput(flags["--from-variant"]),rollToVariantSelector=normalizeOptionalInput(flags["--to-variant"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),baseSelector=normalizeOptionalInput(flags["--by"]),stageInputs=(flags["--stage"]||[]).map(input=>input.trim()),finalPercentage=flags["--final-percentage"],start=normalizeOptionalInput(flags["--start"]),message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to roll out"),output_manager_default.log(`Example: ${getCommandName("flags rollout my-feature --environment production --by user.userId --stage 5,6h --stage 25,1d")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionFromVariant(rollFromVariantSelector),telemetryClient.trackCliOptionToVariant(rollToVariantSelector),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionStage(stageInputs.length>0?[stageInputs[0]]:void 0),telemetryClient.trackCliOptionFinalPercentage(finalPercentage),telemetryClient.trackCliOptionStart(start),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let[flag,settings]=await Promise.all([getFlag(client,project.id,flagArg),getFlagSettings(client,project.id)]);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to roll out in:",{showEnvironmentDetails:!0,decorateChoices:!1}),currentOutcome=flag.environments[selectedEnvironment].fallthrough,rolloutConfig=resolveFlagRollout(flag,settings,{stageInputs,finalPercentage,baseSelector,rollFromVariantSelector,rollToVariantSelector,defaultVariantSelector,start,currentOutcome:currentOutcome.type==="experiment"?void 0:currentOutcome}),nextEnvironmentConfig=buildOutcomeEnvConfig(flag.environments[selectedEnvironment],{outcome:rolloutConfig.outcome,defaultVariantId:rolloutConfig.defaultVariant.id});if(flag.environments[selectedEnvironment].active&&(0,import_fast_deep_equal6.default)(flag.environments[selectedEnvironment].fallthrough,rolloutConfig.outcome)&&(0,import_fast_deep_equal6.default)(flag.environments[selectedEnvironment],nextEnvironmentConfig))return output_manager_default.warn(`Flag ${import_chalk59.default.bold(flag.slug)} is already configured with this rollout in ${selectedEnvironment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultRolloutMessage(selectedEnvironment,rolloutConfig));output_manager_default.spinner(`Updating rollout in ${selectedEnvironment}...`),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:nextEnvironmentConfig},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk59.default.bold(flag.slug)} rollout has been updated in ${import_chalk59.default.bold(selectedEnvironment)}`),output_manager_default.log(` ${import_chalk59.default.dim("Based on:")} ${rolloutConfig.baseLabel}`),output_manager_default.log(` ${import_chalk59.default.dim("Roll from:")} ${formatVariantLabel(rolloutConfig.rollFromVariant)}`),output_manager_default.log(` ${import_chalk59.default.dim("Roll to:")} ${formatVariantLabel(rolloutConfig.rollToVariant)}`),output_manager_default.log(` ${import_chalk59.default.dim("Fallback:")} ${formatVariantLabel(rolloutConfig.defaultVariant)}`),output_manager_default.log(` ${import_chalk59.default.dim("Start:")} ${rolloutConfig.startLabel}`),output_manager_default.log(` ${import_chalk59.default.dim("Stages:")} ${rolloutConfig.summary}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function getDefaultRolloutMessage(environment,rolloutConfig){return`Configure rollout for ${environment}: ${rolloutConfig.summary}`}function formatVariantLabel(variant){return variant.label||variant.id}var import_chalk60=__toESM(require_source(),1);async function deleteFlag(client,projectId,flagIdOrSlug){output_manager_default.debug(`Deleting feature flag ${flagIdOrSlug} for project ${projectId}`);let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags/${encodeURIComponent(flagIdOrSlug)}`;await client.fetch(url,{method:"DELETE"})}var FlagsRmTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};async function rm(client,argv){let telemetryClient=new FlagsRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(removeSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to delete"),output_manager_default.log(`Example: ${getCommandName("flags delete my-feature")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),flag.state!=="archived")return output_manager_default.error(`Flag ${import_chalk60.default.bold(flag.slug)} must be archived before it can be deleted. Run ${getCommandName(`flags archive ${flag.slug}`)} first.`),1;if(!skipConfirmation){if(!client.stdin.isTTY)return output_manager_default.error("Missing required flag --yes. Use --yes to skip the confirmation prompt in non-interactive mode."),2;if(!await client.input.confirm(`Are you sure you want to delete ${import_chalk60.default.bold(flag.slug)}? This action cannot be undone.`,!1))return output_manager_default.log("Aborted"),0}output_manager_default.spinner("Deleting flag..."),await deleteFlag(client,project.id,flagArg),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk60.default.bold(flag.slug)} has been deleted`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk61=__toESM(require_source(),1);var FlagsArchiveTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};var EVALUATION_WINDOW_DAYS=3;async function archive(client,argv){let telemetryClient=new FlagsArchiveTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(archiveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,skipConfirmation=flags["--yes"],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to archive"),output_manager_default.log(`Example: ${getCommandName("flags archive my-feature")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),flag.state==="archived")return output_manager_default.warn(`Flag ${import_chalk61.default.bold(flag.slug)} is already archived`),0;if(!skipConfirmation&&!client.stdin.isTTY)return output_manager_default.error("Missing required flag --yes. Use --yes to skip the confirmation prompt in non-interactive mode."),2;output_manager_default.spinner("Checking recent evaluations...");let endTime=new Date,startTime=new Date(endTime.getTime()-EVALUATION_WINDOW_DAYS*24*60*60*1e3),evaluations2=await countFlagEvaluations(client,{ownerId:org.id,projectId:project.id,flagSlug:flag.slug,startTime,endTime});output_manager_default.stopSpinner();let window=`the last ${EVALUATION_WINDOW_DAYS} days`;if(evaluations2===null){let evaluationsCommand=["flags","evaluations",flag.slug,"--since",`${EVALUATION_WINDOW_DAYS}d`,...getGlobalFlagsFromArgs(client.argv.slice(2),{preserveProject:!0})].map(quoteArg).join(" ");output_manager_default.log(`Could not check recent evaluations for ${import_chalk61.default.bold(flag.slug)}. Run ${getCommandName(evaluationsCommand)} to verify the flag is no longer evaluated.`)}else evaluations2>0?output_manager_default.warn(`${import_chalk61.default.bold(flag.slug)} reported ${evaluations2.toLocaleString()} ${evaluations2===1?"evaluation":"evaluations"} in ${window}. Archived flags evaluate to the default value in code. Remove the flag from your code and deploy before archiving.`):output_manager_default.log(`No evaluations reported for ${import_chalk61.default.bold(flag.slug)} in ${window}.`);if(!skipConfirmation&&!await client.input.confirm(evaluations2!==null&&evaluations2>0?`Archive ${import_chalk61.default.bold(flag.slug)} anyway?`:`Are you sure you want to archive ${import_chalk61.default.bold(flag.slug)}?`,!1))return output_manager_default.log("Aborted"),0;output_manager_default.spinner("Archiving flag..."),await updateFlag(client,project.id,flagArg,{state:"archived",message:message??"Archived via CLI"}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk61.default.bold(flag.slug)} has been archived`),output_manager_default.log(`
|
|
275
|
-
To unarchive this flag, run ${getCommandName(`flags unarchive ${flag.slug}`)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk62=__toESM(require_source(),1);var FlagsUnarchiveTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};async function unarchive(client,argv){let telemetryClient=new FlagsUnarchiveTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(unarchiveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to unarchive"),output_manager_default.log(`Example: ${getCommandName("flags unarchive my-feature")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),flag.state==="active")return output_manager_default.warn(`Flag ${import_chalk62.default.bold(flag.slug)} is already active`),0;if(!skipConfirmation){if(!client.stdin.isTTY)return output_manager_default.error("Missing required flag --yes. Use --yes to skip the confirmation prompt in non-interactive mode."),2;if(!await client.input.confirm(`Are you sure you want to unarchive ${import_chalk62.default.bold(flag.slug)}?`,!1))return output_manager_default.log("Aborted"),0}output_manager_default.spinner("Unarchiving flag..."),await updateFlag(client,project.id,flagArg,{state:"active",message:"Unarchive"}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk62.default.bold(flag.slug)} has been unarchived`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk64=__toESM(require_source(),1);var import_chalk63=__toESM(require_source(),1);function logNonBooleanFlagGuidance(flag,{attemptedSubcommand,environment,isInteractive,teamSlug,projectName}){let dashboardUrl=getFlagDashboardUrl(teamSlug,projectName,flag.slug),suggestedEnvironment=environment&&environment in flag.environments?environment:void 0;if(output_manager_default.warn(`The ${getCommandName(`flags ${attemptedSubcommand}`)} command only works with boolean flags.`),output_manager_default.log(`Flag ${import_chalk63.default.bold(flag.slug)} is a ${import_chalk63.default.cyan(flag.kind)} flag. Set a specific variant instead:`),output_manager_default.log(` ${getCommandName(getSuggestedSetCommand(flag.slug,suggestedEnvironment,isInteractive))}`),flag.variants.length>0){output_manager_default.log("Available variants:");for(let variant of flag.variants)output_manager_default.log(` - ${formatVariantForDisplay(variant)}`)}output_manager_default.log(`See full flag details with ${getCommandName(`flags inspect ${flag.slug}`)}`),output_manager_default.log(`Open in the dashboard: ${import_chalk63.default.cyan(dashboardUrl)}`)}function getSuggestedSetCommand(slug,environment,isInteractive){let parts=[`flags set ${slug}`];return environment?parts.push(`--environment ${environment}`):isInteractive||parts.push("--environment <ENV>"),isInteractive||parts.push("--variant <VARIANT>"),parts.join(" ")}var FlagsDisableTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionVariant(variant){variant&&this.trackCliOption({option:"variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function disable3(client,argv){let telemetryClient=new FlagsDisableTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(disableSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],variantId=flags["--variant"],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg){if(client.nonInteractive){let envPart=environment?`--environment ${environment}`:"--environment <production|preview|development>";return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide a flag slug or ID to disable.",next:[{command:buildCommandWithGlobalFlags(client.argv,`flags disable <flag> ${envPart}`),when:"disable a feature flag by slug or ID"}]},2),2}return output_manager_default.error("Please provide a flag slug or ID to disable"),output_manager_default.log(`Example: ${getCommandName("flags disable my-feature --environment production")}`),2}telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionVariant(variantId),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. Run link first.",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"link the project"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),logArchivedFlagNotice(flag),flag.kind!=="boolean")return logNonBooleanFlagGuidance(flag,{attemptedSubcommand:"disable",environment,isInteractive:!!client.stdin.isTTY,teamSlug:link.org.slug,projectName:project.name}),0;if(!environment&&client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide --environment (production, preview, or development) to disable the flag in.",next:[{command:buildCommandWithGlobalFlags(client.argv,`flags disable ${flagArg} --environment <production|preview|development>`),when:"disable the flag in a specific environment"}]},2),2;environment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to disable the flag in:");let envConfig=flag.environments[environment],selectedVariant=getBooleanVariant(flag,!1);if(variantId){let result=resolveVariant(variantId,flag.variants);if(result.error)return output_manager_default.error(result.error),1;selectedVariant=result.variant}if(isPausingEnvironmentToVariant(envConfig,selectedVariant.id))return output_manager_default.warn(`Flag ${import_chalk64.default.bold(flag.slug)} is already disabled in ${environment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultDisableMessage(environment));output_manager_default.spinner(`Disabling flag in ${environment}...`),await updateFlag(client,project.id,flagArg,{environments:{[environment]:buildPausedEnvironmentConfig(envConfig,selectedVariant.id)},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk64.default.bold(flag.slug)} ${flag.state==="archived"?"configuration has been updated":"has been disabled"} in ${import_chalk64.default.bold(environment)}`),output_manager_default.log(` ${import_chalk64.default.dim(flag.state==="archived"?"Configured variant:":"Serving variant:")} ${formatVariantForDisplay(selectedVariant)}`)}catch(err){output_manager_default.stopSpinner();let message2=err instanceof Error?err.message:String(err);return client.nonInteractive&&message2.startsWith("Invalid environment:")?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message:message2,next:[{command:buildCommandWithGlobalFlags(client.argv,`flags disable ${flagArg} --environment <production|preview|development>`),when:"use a valid environment (production, preview, or development)"}]},2),2):(printError(err),2)}return 0}function getDefaultDisableMessage(environment){return`Disabled for ${environment} via CLI`}var import_chalk65=__toESM(require_source(),1);var FlagsEnableTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function enable3(client,argv){let telemetryClient=new FlagsEnableTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(enableSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to enable"),output_manager_default.log(`Example: ${getCommandName("flags enable my-feature --environment production")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),logArchivedFlagNotice(flag),flag.kind!=="boolean")return logNonBooleanFlagGuidance(flag,{attemptedSubcommand:"enable",environment,isInteractive:!!client.stdin.isTTY,teamSlug:link.org.slug,projectName:project.name}),0;if(!environment&&client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide --environment (production, preview, or development) to enable the flag in.",next:[{command:buildCommandWithGlobalFlags(client.argv,`flags enable ${flagArg} --environment <production|preview|development>`),when:"enable the flag in a specific environment"}]},2),2;environment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to enable the flag in:");let envConfig=flag.environments[environment],onVariant=getBooleanVariant(flag,!0);if(isPausingEnvironmentToVariant(envConfig,onVariant.id))return output_manager_default.warn(`Flag ${import_chalk65.default.bold(flag.slug)} is already enabled in ${environment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultEnableMessage(environment));output_manager_default.spinner(`Enabling flag in ${environment}...`),await updateFlag(client,project.id,flagArg,{environments:{[environment]:buildPausedEnvironmentConfig(envConfig,onVariant.id)},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk65.default.bold(flag.slug)} ${flag.state==="archived"?"configuration has been updated":"has been enabled"} in ${import_chalk65.default.bold(environment)}`),output_manager_default.log(` ${import_chalk65.default.dim(flag.state==="archived"?"Configured variant:":"Serving variant:")} ${formatVariantForDisplay(onVariant)}`)}catch(err){output_manager_default.stopSpinner();let message2=err instanceof Error?err.message:String(err);return client.nonInteractive&&message2.startsWith("Invalid environment:")?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message:message2,next:[{command:buildCommandWithGlobalFlags(client.argv,`flags enable ${flagArg} --environment <production|preview|development>`),when:"use a valid environment (production, preview, or development)"}]},2),2):(printError(err),2)}return 0}function getDefaultEnableMessage(environment){return`Enabled for ${environment} via CLI`}var FlagsSdkKeysTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandCreate(actual){this.trackCliSubcommand({subcommand:"create",value:actual})}trackCliSubcommandRevoke(actual){this.trackCliSubcommand({subcommand:"revoke",value:actual})}},FlagsSdkKeysLsTelemetryClient=class extends TelemetryClient{trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSdkKeysAddTelemetryClient=class extends TelemetryClient{trackCliOptionType(type){type&&this.trackCliOption({option:"type",value:type})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:environment})}trackCliOptionLabel(label){label&&this.trackCliOption({option:"label",value:this.redactedValue})}},FlagsSdkKeysRmTelemetryClient=class extends TelemetryClient{trackCliArgumentKey(key){key&&this.trackCliArgument({arg:"key",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};var import_chalk66=__toESM(require_source(),1),import_ms4=__toESM(require_ms(),1);async function sdkKeysLs(client,argv){let telemetryClient=new FlagsSdkKeysLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(sdkKeysListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,json=flags["--json"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagJson(json);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name);try{output_manager_default.spinner("Fetching SDK keys...");let keys=await getSdkKeys(client,project.id);output_manager_default.stopSpinner();let sortedKeys=keys.sort((a,b)=>b.createdAt-a.createdAt);json?outputSdkKeysJson(client,sortedKeys):keys.length===0?(output_manager_default.log(`No SDK keys found for ${projectSlugLink}`),output_manager_default.log(`
|
|
274
|
+
${promptLines}`,!1)}function formatVariantForLog(variant){return`${formatVariantForDisplay(variant)} ${import_chalk51.default.dim(`[id: ${variant.id}]`)}`}async function collectVariantUpdate(client,flag,input){let selectedVariant=await resolveSelectedVariant(client,flag,input.selector),nextValueInput=input.valueInput,nextLabel=input.label;return flag.kind!=="boolean"&&nextValueInput===void 0&&client.stdin.isTTY&&(nextValueInput=await promptForVariantValueUpdate(client,flag,selectedVariant)),nextLabel===void 0&&client.stdin.isTTY&&(nextLabel=await promptForVariantLabelUpdate(client,selectedVariant)),client.stdin.isTTY||ensureVariantUpdateInput(nextValueInput,nextLabel),{selector:selectedVariant.id,valueInput:nextValueInput,label:nextLabel}}function ensureVariantUpdateInput(valueInput,label){if(!valueInput&&!label)throw new Error("At least one of --value or --label must be provided. Use --value <VALUE>, --label <LABEL>, or run interactively in a terminal.")}async function resolveSelectedVariant(client,flag,selector){if(selector){let result=resolveVariant(selector,flag.variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${selector}" not found`);return result.variant}if(!client.stdin.isTTY)throw new Error("Missing required option --variant. Use --variant <VARIANT>, or run interactively in a terminal.");let selectedVariantId=await client.input.select({message:"Select a variant to update:",choices:flag.variants.map(variant=>({name:formatVariantForLog(variant),value:variant.id}))}),selectedVariant=flag.variants.find(v=>v.id===selectedVariantId);if(!selectedVariant)throw new Error("No variant selected");return selectedVariant}async function promptForVariantValueUpdate(client,flag,selectedVariant){let valueResponse=await client.input.text({message:`Enter a new value for ${formatVariantForDisplay(selectedVariant)} (press Enter to keep ${formatVariantValue(selectedVariant.value)}):`,validate:value=>{if(!value.trim())return!0;let result=validateVariantValue(value,flag.kind);return result===null?!0:result}});return normalizeOptionalInput(valueResponse)}async function promptForVariantLabelUpdate(client,selectedVariant){let currentLabel=selectedVariant.label,labelResponse=await client.input.text({message:currentLabel?`Enter a new label for ${formatVariantForDisplay(selectedVariant)} (press Enter to keep ${JSON.stringify(currentLabel)}):`:`Enter an optional label for ${formatVariantForDisplay(selectedVariant)} (press Enter to skip):`});return normalizeOptionalInput(labelResponse)}function applyVariantUpdates(flag,updates){let variants=flag.variants.map(variant=>({...variant})),changedVariantIds=new Set;for(let update2 of updates){let result=resolveVariant(update2.selector,variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${update2.selector}" not found`);let nextValue=update2.valueInput!==void 0?parseUpdatedVariantValue(update2.valueInput,flag.kind,result.variant):result.variant.value,nextLabel=update2.label??result.variant.label,variantIndex=variants.findIndex(v=>v.id===result.variant.id),existingVariant=variants[variantIndex],hasChanged=!(0,import_fast_deep_equal3.default)(existingVariant.value,nextValue)||existingVariant.label!==nextLabel;variants[variantIndex]={...existingVariant,value:nextValue,label:nextLabel},hasChanged&&changedVariantIds.add(existingVariant.id)}return{variants,changedVariants:variants.filter(variant=>changedVariantIds.has(variant.id))}}function parseUpdatedVariantValue(valueInput,kind,existingVariant){let validationError=validateVariantValue(valueInput,kind);if(validationError)throw new Error(validationError);if(kind==="boolean"){let nextValue=valueInput.toLowerCase()==="true";if(nextValue!==existingVariant.value)throw new Error("Boolean variant values cannot be changed. You can update the label only.");return nextValue}return kind==="number"?Number(valueInput):kind==="json"?JSON.parse(valueInput):valueInput}var import_chalk53=__toESM(require_source(),1);var import_chalk52=__toESM(require_source(),1);async function resolveFlagEnvironment(client,flag,environment,promptMessage,options={}){let nextEnvironment=environment;if(!nextEnvironment){if(!canPrompt(client))throw new Error("Missing required option --environment. Use --environment <ENV>, or run interactively in a terminal.");let availableEnvironments=STANDARD_ENVIRONMENTS.filter(env=>Object.prototype.hasOwnProperty.call(flag.environments,env));if(availableEnvironments.length===0)throw new Error("No valid environments found for this flag");options.showEnvironmentDetails&&printFlagEnvironmentDetails(flag,void 0,availableEnvironments),nextEnvironment=await client.input.select({message:promptMessage,choices:availableEnvironments.map(env=>({name:options.decorateChoices===!1?env:formatEnvironmentChoiceLabel(env,flag.environments[env]),value:env}))})}if(!STANDARD_ENVIRONMENTS.includes(nextEnvironment))throw new Error(`Invalid environment: ${nextEnvironment}. Must be one of: ${STANDARD_ENVIRONMENTS.join(", ")}`);if(!flag.environments[nextEnvironment])throw new Error(`Environment ${nextEnvironment} not found for this flag`);return nextEnvironment}function formatEnvironmentChoiceLabel(envName,envConfig){let status2=envConfig?.active?import_chalk52.default.green("active"):import_chalk52.default.yellow("paused");return`${envName} (${status2})`}function isPausingEnvironmentToVariant(envConfig,variantId){return!envConfig.active&&envConfig.pausedOutcome?.variantId===variantId}function buildTargetingVariantEnvironmentConfig(envConfig,variantId){return buildOutcomeEnvConfig(envConfig,{outcome:{type:"variant",variantId},defaultVariantId:variantId})}function buildResumeTargetingEnvironmentConfig(flag,environment){let envConfig=flag.environments[environment],fallthrough=resolveEffectiveFallthrough(flag,environment),defaultVariantId=getFallthroughDefaultVariantId(fallthrough);return buildOutcomeEnvConfig(envConfig,{outcome:fallthrough,defaultVariantId})}function resolveEffectiveFallthrough(flag,environment){let envConfig=flag.environments[environment],inheritedFrom=envConfig.reuse?.active?envConfig.reuse.environment:void 0;if(inheritedFrom){let inheritedConfig=flag.environments[inheritedFrom];if(inheritedConfig)return structuredClone(inheritedConfig.fallthrough)}return structuredClone(envConfig.fallthrough)}function isUsableFallthrough(fallthrough,variants){let variantIds=new Set(variants.map(variant=>variant.id));return fallthrough.type==="variant"?variantIds.has(fallthrough.variantId):fallthrough.type==="split"?variantIds.has(fallthrough.defaultVariantId):fallthrough.type==="experiment"?!1:variantIds.has(fallthrough.defaultVariantId)&&variantIds.has(fallthrough.rollFromVariantId)&&variantIds.has(fallthrough.rollToVariantId)}function getFallthroughDefaultVariantId(fallthrough){if(fallthrough.type==="variant")return fallthrough.variantId;if(fallthrough.type==="experiment")throw new Error("Experiment outcomes do not have a default variant");return fallthrough.defaultVariantId}function buildPausedEnvironmentConfig(envConfig,variantId){return{...envConfig,active:!1,pausedOutcome:{type:"variant",variantId}}}function buildOutcomeEnvConfig(envConfig,options){let{reuse,...restConfig}=envConfig,nextConfig={...restConfig,active:!0,pausedOutcome:envConfig.pausedOutcome??{type:"variant",variantId:options.defaultVariantId},fallthrough:options.outcome};return reuse&&(nextConfig.reuse={...reuse,active:!1}),nextConfig}function getBooleanVariant(flag,value){let variant=flag.variants.find(candidate=>candidate.value===value);if(!variant)throw new Error(`Flag ${import_chalk52.default.bold(flag.slug)} is missing the standard boolean variants`);return variant}async function resolveFlagUpdateMessage(client,message,defaultMessage){if(message!==void 0)return message;if(!canPrompt(client))return defaultMessage;let response=await client.input.text({message:"Enter a message for this update:",default:defaultMessage});return normalizeOptionalInput(response)||defaultMessage}var FlagsSetTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionVariant(variant){variant&&this.trackCliOption({option:"variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function set(client,argv){let telemetryClient=new FlagsSetTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(setSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],variantSelector=normalizeOptionalInput(flags["--variant"]),message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to set"),output_manager_default.log(`Example: ${getCommandName("flags set my-feature --environment production --variant true")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionVariant(variantSelector),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to set the variant in:",{showEnvironmentDetails:!0,decorateChoices:!1}),selectedVariant=await resolveVariantToSet(client,flag,variantSelector),envConfig=flag.environments[selectedEnvironment];if(isPausingEnvironmentToVariant(envConfig,selectedVariant.id))return output_manager_default.warning(`Flag ${import_chalk53.default.bold(flag.slug)} is already ${flag.state==="archived"?"configured with":"serving"} ${formatVariantForDisplay(selectedVariant)} in ${selectedEnvironment}`),0;let presentation=getSetPresentation(flag,selectedVariant),updateMessage=await resolveFlagUpdateMessage(client,message,presentation.defaultMessage(selectedEnvironment));output_manager_default.spinner(presentation.spinner(selectedEnvironment)),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:buildPausedEnvironmentConfig(envConfig,selectedVariant.id)},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(flag.state==="archived"?`Archived flag ${import_chalk53.default.bold(flag.slug)} configuration has been updated in ${import_chalk53.default.bold(selectedEnvironment)}`:presentation.success(flag.slug,selectedEnvironment)),output_manager_default.log(` ${import_chalk53.default.dim(flag.state==="archived"?"Configured variant:":"Serving variant:")} ${formatVariantForDisplay(selectedVariant)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveVariantToSet(client,flag,selector){if(selector){let result=resolveVariant(selector,flag.variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${selector}" not found`);return result.variant}if(!client.stdin.isTTY)throw new Error("Missing required option --variant. Use --variant <VARIANT>, or run interactively in a terminal.");let selectedVariantId=await client.input.select({message:"Select a variant to serve:",choices:flag.variants.map(variant=>({name:formatVariantForDisplay(variant),value:variant.id}))}),selectedVariant=flag.variants.find(variant=>variant.id===selectedVariantId);if(!selectedVariant)throw new Error("No variant selected");return selectedVariant}function getSetPresentation(flag,variant){return flag.kind==="boolean"&&variant.value===!0?{spinner:environment=>`Enabling flag in ${environment}...`,success:(slug,environment)=>`Feature flag ${import_chalk53.default.bold(slug)} has been enabled in ${import_chalk53.default.bold(environment)}`,defaultMessage:environment=>`Enabled for ${environment} via CLI`}:flag.kind==="boolean"&&variant.value===!1?{spinner:environment=>`Disabling flag in ${environment}...`,success:(slug,environment)=>`Feature flag ${import_chalk53.default.bold(slug)} has been disabled in ${import_chalk53.default.bold(environment)}`,defaultMessage:environment=>`Disabled for ${environment} via CLI`}:{spinner:environment=>`Setting variant in ${environment}...`,success:(slug,environment)=>`Feature flag ${import_chalk53.default.bold(slug)} has been set in ${import_chalk53.default.bold(environment)}`,defaultMessage:environment=>`Set variant for ${environment} via CLI`}}var import_chalk54=__toESM(require_source(),1),import_fast_deep_equal4=__toESM(require_fast_deep_equal(),1);var FlagsUseTargetingTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionDefaultVariant(variant){variant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}trackCliOptionProject(project){project&&this.trackCliOption({option:"project",value:this.redactedValue})}};async function useTargeting(client,argv){let telemetryClient=new FlagsUseTargetingTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(useTargetingSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to use targeting for"),output_manager_default.log(`Example: ${getCommandName("flags targeting enable my-feature --environment production")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to use targeting in:",{showEnvironmentDetails:!0,decorateChoices:!1}),envConfig=flag.environments[selectedEnvironment],nextEnvConfig=await resolveNextTargetingEnvironmentConfig(client,flag,selectedEnvironment,defaultVariantSelector);if((0,import_fast_deep_equal4.default)(envConfig,nextEnvConfig))return output_manager_default.warn(flag.state==="archived"?`Archived flag ${import_chalk54.default.bold(flag.slug)} is already configured to use targeting in ${import_chalk54.default.bold(selectedEnvironment)}`:formatAlreadyUsingTargetingWarning(flag,selectedEnvironment,nextEnvConfig)),0;let updateMessage=await resolveFlagUpdateMessage(client,message,`Activated targeting for ${selectedEnvironment} via CLI`);output_manager_default.spinner(`Activating targeting in ${selectedEnvironment}...`),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:nextEnvConfig},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk54.default.bold(flag.slug)} ${flag.state==="archived"?"is configured to use targeting":"now uses targeting"} in ${import_chalk54.default.bold(selectedEnvironment)}`),output_manager_default.log(` ${import_chalk54.default.dim("Fallthrough:")} ${formatFlagOutcome(nextEnvConfig.fallthrough,flag.variants)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveNextTargetingEnvironmentConfig(client,flag,environment,defaultVariantSelector){if(defaultVariantSelector){let variant=resolveDefaultVariantOrThrow(flag,defaultVariantSelector);return buildTargetingVariantEnvironmentConfig(flag.environments[environment],variant.id)}let fallthrough=resolveEffectiveFallthrough(flag,environment);if(isUsableFallthrough(fallthrough,flag.variants))return buildResumeTargetingEnvironmentConfig(flag,environment);let selectedVariant=await resolveReplacementDefaultVariant(client,flag,fallthrough);return buildTargetingVariantEnvironmentConfig(flag.environments[environment],selectedVariant.id)}function resolveDefaultVariantOrThrow(flag,selector){let result=resolveVariant(selector,flag.variants);if(result.error||!result.variant)throw new Error(result.error||`Variant "${selector}" not found`);return result.variant}async function resolveReplacementDefaultVariant(client,flag,fallthrough){if(!canPrompt(client))throw new Error(`Couldn't resume targeting because the current fallthrough references a missing variant. Pass --default-variant <VARIANT>${describeUnusableFallthrough(fallthrough)}.`);output_manager_default.warn(`Current fallthrough references a missing variant${describeUnusableFallthrough(fallthrough)}. Choose a new default variant.`);let selectedVariantId=await client.input.select({message:"Select a default variant when no rules match:",choices:flag.variants.map(variant=>({name:formatVariantForDisplay(variant),value:variant.id}))}),selectedVariant=flag.variants.find(variant=>variant.id===selectedVariantId);if(!selectedVariant)throw new Error("No variant selected");return selectedVariant}function describeUnusableFallthrough(fallthrough){return fallthrough.type==="variant"?` (${fallthrough.variantId})`:fallthrough.type==="experiment"?" (experiment assignment)":` (${fallthrough.type} default ${fallthrough.defaultVariantId})`}function formatAlreadyUsingTargetingWarning(flag,environment,envConfig){let{fallthrough}=envConfig;if(fallthrough.type==="variant"){let variant=flag.variants.find(candidate=>candidate.id===fallthrough.variantId),label=variant?formatVariantForDisplay(variant):fallthrough.variantId;return`Flag ${import_chalk54.default.bold(flag.slug)} already uses targeting with default ${label} in ${environment}`}return`Flag ${import_chalk54.default.bold(flag.slug)} already uses targeting in ${environment}`}var import_chalk57=__toESM(require_source(),1),import_fast_deep_equal5=__toESM(require_fast_deep_equal(),1);var import_chalk56=__toESM(require_source(),1);var import_chalk55=__toESM(require_source(),1);function resolveFlagBucketingBase(settings,selector){let separatorIndex=selector.indexOf(".");if(separatorIndex<=0||separatorIndex===selector.length-1)throw new Error("Invalid value for --by. Use the format <entity.attribute>, for example --by user.userId.");let kind=selector.slice(0,separatorIndex),attribute=selector.slice(separatorIndex+1),entity=settings.entities.find(candidate=>candidate.kind===kind);if(!entity){let availableKinds=settings.entities.map(candidate=>candidate.kind);throw new Error(`Unknown entity ${import_chalk55.default.bold(kind)}. Available entities: ${availableKinds.join(", ")}`)}let matchingAttribute=entity.attributes.find(candidate=>candidate.key===attribute);if(!matchingAttribute){let availableAttributes=entity.attributes.map(candidate=>candidate.key);throw new Error(`Unknown attribute ${import_chalk55.default.bold(selector)}. Available attributes for ${kind}: ${availableAttributes.join(", ")}`)}if(!isBucketingAttribute(matchingAttribute))throw new Error(`Attribute ${import_chalk55.default.bold(selector)} is a Timestamp and cannot be used for bucketing. Choose a string or number attribute.`);return{type:"entity",kind,attribute}}function formatFlagBucketingBaseSelector(base){if(base)return`${base.kind}.${base.attribute}`}function resolveFlagSplit(flag,settings,options){let currentSplit=options.currentOutcome?.type==="split"?options.currentOutcome:void 0,baseSelector=options.baseSelector||formatFlagBucketingBaseSelector(currentSplit?.base);if(!baseSelector)throw new Error("Missing required option --by. Use --by <entity.attribute> to choose how users are bucketed.");let base=resolveFlagBucketingBase(settings,baseSelector),weights=resolveSplitWeights(flag,options.weightInputs,currentSplit),defaultVariant=resolveDefaultVariant(flag,options.defaultVariantSelector,currentSplit);return{outcome:{type:"split",base,weights,defaultVariantId:defaultVariant.id},defaultVariant,baseLabel:`${base.kind}.${base.attribute}`,summary:formatSplitSummary(flag.variants,weights)}}function resolveSplitWeights(flag,weightInputs,currentSplit){if(weightInputs.length===0&¤tSplit)return validateAndNormalizeWeights(flag,currentSplit.weights);if(weightInputs.length===0)throw new Error("At least one --weight is required. Use --weight <VARIANT=WEIGHT> for each variant, or run interactively in a terminal.");let weights={},seen=new Set;for(let input of weightInputs){let{variantSelector,weight}=parseWeightInput(input),variant=resolveVariantOrThrow(variantSelector,flag.variants,"--weight");if(seen.has(variant.id))throw new Error(`Duplicate weight for variant ${import_chalk56.default.bold(formatVariantForDisplay(variant))}.`);seen.add(variant.id),weights[variant.id]=weight}let missingVariants=flag.variants.filter(variant=>!seen.has(variant.id));if(missingVariants.length>0)throw new Error(`Missing weights for variants: ${missingVariants.map(variant=>formatVariantForDisplay(variant)).join(", ")}. Use --weight <VARIANT=WEIGHT> for each variant, including 0 for variants that should receive no traffic.`);return validateAndNormalizeWeights(flag,weights)}function parseWeightInput(input){let separatorIndex=input.lastIndexOf("=");if(separatorIndex<=0||separatorIndex===input.length-1)throw new Error(`Invalid weight ${import_chalk56.default.bold(input)}. Use --weight <VARIANT=WEIGHT>, for example --weight true=5.`);let variantSelector=input.slice(0,separatorIndex).trim(),rawWeight=input.slice(separatorIndex+1).trim();if(!variantSelector)throw new Error(`Invalid weight ${import_chalk56.default.bold(input)}. Variant cannot be empty.`);if(!rawWeight)throw new Error(`Invalid weight ${import_chalk56.default.bold(input)}. Weight cannot be empty.`);let weight=Number(rawWeight);if(!Number.isFinite(weight)||weight<0)throw new Error(`Invalid weight "${rawWeight}". Use a number greater than or equal to 0.`);return{variantSelector,weight}}function validateAndNormalizeWeights(flag,weights){let normalizedWeights=Object.fromEntries(flag.variants.map(variant=>[variant.id,weights[variant.id]??0]));if(Object.values(normalizedWeights).reduce((sum,weight)=>sum+weight,0)<=0)throw new Error("At least one weight must be greater than 0.");return normalizedWeights}function resolveDefaultVariant(flag,selector,currentSplit){if(selector)return resolveVariantOrThrow(selector,flag.variants,"--default-variant");if(currentSplit)return resolveVariantByIdOrThrow(currentSplit.defaultVariantId,flag.variants,"--default-variant");if(flag.kind==="boolean")return getBooleanVariant(flag,!1);throw new Error("Missing required option --default-variant. Use --default-variant <VARIANT> for non-boolean splits.")}function formatSplitSummary(variants,weights){let total=Object.values(weights).reduce((sum,weight)=>sum+weight,0);return variants.map(variant=>{let weight=weights[variant.id]??0,percentage=total>0?weight/total*100:0;return`${formatPlainVariant(variant)}: ${formatPercentage(percentage)}`}).join(", ")}function formatPlainVariant(variant){let value=formatVariantValue(variant.value);return variant.label?`${variant.label} (${value})`:value}function formatPercentage(percentage){return Number.isInteger(percentage)?`${percentage}%`:`${Number(percentage.toFixed(2))}%`}var FlagsSplitTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionBy(base){base&&this.trackCliOption({option:"by",value:this.redactedValue})}trackCliOptionWeight(weights){weights?.length&&this.trackCliOption({option:"weight",value:this.redactedValue})}trackCliOptionDefaultVariant(variant){variant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function split(client,argv){let telemetryClient=new FlagsSplitTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(splitSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],baseSelector=normalizeOptionalInput(flags["--by"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),weightInputs=flags["--weight"]||[],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to split"),output_manager_default.log(`Example: ${getCommandName("flags split my-feature --environment production --by user.userId --weight false=95 --weight true=5")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionWeight(weightInputs.length>0?[weightInputs[0]]:void 0),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let[flag,settings]=await Promise.all([getFlag(client,project.id,flagArg),getFlagSettings(client,project.id)]);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to split traffic in:",{showEnvironmentDetails:!0,decorateChoices:!1}),envConfig=flag.environments[selectedEnvironment],currentSplit=envConfig.fallthrough.type==="split"?envConfig.fallthrough:void 0,shouldPromptCurrentSplit=canPrompt(client)&¤tSplit!==void 0&&!baseSelector&&weightInputs.length===0&&!defaultVariantSelector&&!message,resolvedBaseSelector=await resolveBaseSelector(client,settings,baseSelector,currentSplit,shouldPromptCurrentSplit),resolvedWeightInputs=await resolveWeightInputs(client,flag,weightInputs,currentSplit,shouldPromptCurrentSplit),resolvedDefaultVariantSelector=await resolveDefaultVariantSelector(client,flag,defaultVariantSelector,currentSplit,shouldPromptCurrentSplit),splitConfig=resolveFlagSplit(flag,settings,{baseSelector:resolvedBaseSelector,weightInputs:resolvedWeightInputs,defaultVariantSelector:resolvedDefaultVariantSelector,currentOutcome:envConfig.fallthrough.type==="experiment"?void 0:envConfig.fallthrough}),nextEnvironmentConfig=buildOutcomeEnvConfig(envConfig,{outcome:splitConfig.outcome,defaultVariantId:splitConfig.defaultVariant.id});if(!message&&envConfig.active&&(0,import_fast_deep_equal5.default)(envConfig.fallthrough,splitConfig.outcome)&&(0,import_fast_deep_equal5.default)(envConfig,nextEnvironmentConfig))return output_manager_default.warn(`Flag ${import_chalk57.default.bold(flag.slug)} is already configured with this split in ${selectedEnvironment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultSplitMessage(selectedEnvironment,splitConfig));output_manager_default.spinner(`Updating split in ${selectedEnvironment}...`),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:nextEnvironmentConfig},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk57.default.bold(flag.slug)} split has been updated in ${import_chalk57.default.bold(selectedEnvironment)}`),output_manager_default.log(` ${import_chalk57.default.dim("Based on:")} ${splitConfig.baseLabel}`),output_manager_default.log(` ${import_chalk57.default.dim("Fallback:")} ${formatVariantForDisplay(splitConfig.defaultVariant)}`),output_manager_default.log(` ${import_chalk57.default.dim("Weights:")} ${splitConfig.summary}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function getDefaultSplitMessage(environment,splitConfig){return`Configure split for ${environment}: ${splitConfig.summary}`}async function resolveBaseSelector(client,settings,baseSelector,currentSplit,shouldPromptCurrentSplit){if(baseSelector||currentSplit&&!shouldPromptCurrentSplit)return baseSelector;if(!canPrompt(client))return;let choices=settings.entities.flatMap(entity=>entity.attributes.filter(isBucketingAttribute).map(attribute=>({name:`${entity.label} \u203A ${attribute.key}`,value:`${entity.kind}.${attribute.key}`}))),currentBaseSelector=formatFlagBucketingBaseSelector(currentSplit?.base),defaultChoice=choices.find(choice=>choice.value===currentBaseSelector)?.value;if(choices.length===0)throw new Error("No entities are configured for weighted splits.");return client.input.select({message:"Select an attribute to split by:",choices,default:defaultChoice})}async function resolveWeightInputs(client,flag,weightInputs,currentSplit,shouldPromptCurrentSplit){if(weightInputs.length>0||currentSplit&&!shouldPromptCurrentSplit||!canPrompt(client))return weightInputs;output_manager_default.log("Enter weights for each variant. Weights are ratios; use 0 for variants that should receive no traffic.");let promptedWeights=[];for(let variant of flag.variants){let defaultWeight=currentSplit?.weights[variant.id]!==void 0?String(currentSplit.weights[variant.id]):currentSplit?"0":"1",weight=await client.input.text({message:`Weight for ${formatVariantForDisplay(variant)}:`,default:defaultWeight,validate:value=>{let trimmed=value.trim();if(!trimmed)return"Enter a weight";let parsed=Number(trimmed);return!Number.isFinite(parsed)||parsed<0?"Enter a number greater than or equal to 0":!0}});promptedWeights.push(`${variant.id}=${weight.trim()}`)}return promptedWeights}async function resolveDefaultVariantSelector(client,flag,defaultVariantSelector,currentSplit,shouldPromptCurrentSplit){if(defaultVariantSelector||currentSplit&&!shouldPromptCurrentSplit||flag.kind==="boolean"&&!canPrompt(client))return defaultVariantSelector;if(canPrompt(client))return client.input.select({message:"Select a fallback variant:",choices:flag.variants.map(variant=>({name:formatVariantForDisplay(variant),value:variant.id})),default:flag.variants.find(variant=>variant.id===currentSplit?.defaultVariantId)?.id||getBooleanFallbackVariantId(flag)})}function getBooleanFallbackVariantId(flag){if(flag.kind==="boolean")return flag.variants.find(variant=>variant.value===!1)?.id}var import_chalk59=__toESM(require_source(),1),import_fast_deep_equal6=__toESM(require_fast_deep_equal(),1);var import_chalk58=__toESM(require_source(),1),import_ms3=__toESM(require_ms(),1);function resolveFlagRollout(flag,settings,options){let currentRollout=options.currentOutcome?.type==="rollout"?options.currentOutcome:void 0,baseSelector=options.baseSelector||formatFlagBucketingBaseSelector(currentRollout?.base);if(!baseSelector)throw new Error("Missing required option --by. Use --by <entity.attribute> to choose how users are bucketed.");let base=resolveFlagBucketingBase(settings,baseSelector),rollFromVariant=resolveRollFromVariant(flag,options.rollFromVariantSelector,currentRollout),rollToVariant=resolveRollToVariant(flag,options.rollToVariantSelector,currentRollout);if(rollFromVariant.id===rollToVariant.id)throw new Error("`--from-variant` and `--to-variant` must resolve to different variants.");let defaultVariant=resolveDefaultVariant2(flag,options.defaultVariantSelector,currentRollout,rollFromVariant),slots=options.stageInputs.length>0?parseStageInputs(options.stageInputs):currentRollout?.slots;if(!slots||slots.length===0)throw new Error("At least one --stage is required. Use --stage <PERCENTAGE,DURATION>, for example --stage 5,6h.");let finalPromille=options.finalPercentage===void 0?currentRollout?.finalPromille:parseFinalPercentage(options.finalPercentage),startTimestamp=resolveRolloutStartTimestamp(options.start,currentRollout?.startTimestamp);return{outcome:{type:"rollout",base,startTimestamp,rollFromVariantId:rollFromVariant.id,rollToVariantId:rollToVariant.id,defaultVariantId:defaultVariant.id,slots,...finalPromille!==void 0&&{finalPromille}},defaultVariant,rollFromVariant,rollToVariant,baseLabel:`${base.kind}.${base.attribute}`,summary:formatRolloutStages(slots,finalPromille),startLabel:formatStartLabel(options.start,currentRollout?.startTimestamp)}}function resolveRollFromVariant(flag,selector,currentRollout){return selector?resolveVariantOrThrow(selector,flag.variants,"--from-variant"):currentRollout?resolveVariantByIdOrThrow(currentRollout.rollFromVariantId,flag.variants,"--from-variant"):inferBooleanVariant(flag,!1,"--from-variant")}function resolveRollToVariant(flag,selector,currentRollout){return selector?resolveVariantOrThrow(selector,flag.variants,"--to-variant"):currentRollout?resolveVariantByIdOrThrow(currentRollout.rollToVariantId,flag.variants,"--to-variant"):inferBooleanVariant(flag,!0,"--to-variant")}function resolveDefaultVariant2(flag,selector,currentRollout,rollFromVariant){return selector?resolveVariantOrThrow(selector,flag.variants,"--default-variant"):currentRollout?resolveVariantByIdOrThrow(currentRollout.defaultVariantId,flag.variants,"--default-variant"):rollFromVariant}function inferBooleanVariant(flag,value,optionName){if(flag.kind!=="boolean")throw new Error(`Missing required option ${optionName}. Use ${optionName} <VARIANT> for non-boolean rollouts.`);let variant=flag.variants.find(candidate=>candidate.value===value);if(!variant)throw new Error(`Flag ${import_chalk58.default.bold(flag.slug)} is missing the standard boolean variants`);return variant}function parseStageInputs(stageInputs){let slots=stageInputs.map(parseStageInput);for(let index=1;index<slots.length;index++)if(slots[index].promille<=slots[index-1].promille)throw new Error("Stage percentages must be in ascending order.");return slots}function parseStageInput(input){let parts=input.split(",").map(part=>part.trim());if(parts.length!==2)throw new Error(`Invalid stage ${import_chalk58.default.bold(input)}. Use --stage <PERCENTAGE,DURATION>, for example --stage 5,6h.`);let percentage=Number(parts[0]);if(!Number.isFinite(percentage)||percentage<=0||percentage>=100||!Number.isInteger(percentage*1e3))throw new Error(`Invalid stage percentage "${parts[0]}". Use a number greater than 0 and less than 100 with up to 3 decimal places.`);let durationMs=parseStageDuration(parts[1]);if(durationMs===void 0)throw new Error(`Invalid duration "${parts[1]}". Use minutes (e.g. "30m"), hours (e.g. "6h"), or days (e.g. "1d"). Seconds are not supported.`);return{durationMs,promille:Math.round(percentage*1e3)}}function parseStageDuration(value){if(!value||/^\d+(s|ms)$/i.test(value))return;let durationMs=(0,import_ms3.default)(/^\d+$/.test(value)?`${value}m`:value);if(durationMs===void 0||durationMs<=0)return;let roundedMinutes=Math.round(durationMs/6e4);if(!(roundedMinutes<=0))return roundedMinutes*6e4}function resolveRolloutStartTimestamp(start,currentStartTimestamp){if(start===void 0)return currentStartTimestamp??Date.now();if(start==="now")return Date.now();let relativeDurationMs=(0,import_ms3.default)(start);if(relativeDurationMs!==void 0){if(relativeDurationMs<=0)throw new Error(`Invalid start time "${start}". Use "now", a future relative duration such as "1h", or an ISO 8601 datetime.`);return Date.now()+relativeDurationMs}let absoluteTime=new Date(start).getTime();if(Number.isNaN(absoluteTime))throw new Error(`Invalid start time "${start}". Use "now", a future relative duration such as "1h", or an ISO 8601 datetime.`);return absoluteTime}function parseFinalPercentage(input){let percentage=Number(input);if(input.trim()===""||!Number.isFinite(percentage)||percentage<0||percentage>100||Math.round(percentage*1e3)/1e3!==percentage)throw new Error(`Invalid final percentage "${input}". Use --final-percentage with a number between 0 and 100 with up to 3 decimal places.`);return Math.round(percentage*1e3)}function formatRolloutStages(slots,finalPromille=1e5){return`${slots.map(slot=>`${formatPromille(slot.promille)} for ${(0,import_ms3.default)(slot.durationMs,{long:!0})}`).join(", ")}, then ${formatPromille(finalPromille)} indefinitely`}function formatPromille(promille){let percentage=promille/1e3;return Number.isInteger(percentage)?`${percentage}%`:`${Number(percentage.toFixed(3))}%`}function formatStartLabel(start,currentStartTimestamp){return start===void 0?currentStartTimestamp?"preserve current start time":"immediately":start==="now"?"immediately":`start at ${start}`}var FlagsRolloutTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionFromVariant(variant){variant&&this.trackCliOption({option:"from-variant",value:this.redactedValue})}trackCliOptionToVariant(variant){variant&&this.trackCliOption({option:"to-variant",value:this.redactedValue})}trackCliOptionDefaultVariant(variant){variant&&this.trackCliOption({option:"default-variant",value:this.redactedValue})}trackCliOptionBy(base){base&&this.trackCliOption({option:"by",value:this.redactedValue})}trackCliOptionStage(stages){stages?.length&&this.trackCliOption({option:"stage",value:this.redactedValue})}trackCliOptionFinalPercentage(percentage){percentage!==void 0&&this.trackCliOption({option:"final-percentage",value:this.redactedValue})}trackCliOptionStart(start){start&&this.trackCliOption({option:"start",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function rollout(client,argv){let telemetryClient=new FlagsRolloutTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rolloutSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],rollFromVariantSelector=normalizeOptionalInput(flags["--from-variant"]),rollToVariantSelector=normalizeOptionalInput(flags["--to-variant"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),baseSelector=normalizeOptionalInput(flags["--by"]),stageInputs=(flags["--stage"]||[]).map(input=>input.trim()),finalPercentage=flags["--final-percentage"],start=normalizeOptionalInput(flags["--start"]),message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to roll out"),output_manager_default.log(`Example: ${getCommandName("flags rollout my-feature --environment production --by user.userId --stage 5,6h --stage 25,1d")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionFromVariant(rollFromVariantSelector),telemetryClient.trackCliOptionToVariant(rollToVariantSelector),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionStage(stageInputs.length>0?[stageInputs[0]]:void 0),telemetryClient.trackCliOptionFinalPercentage(finalPercentage),telemetryClient.trackCliOptionStart(start),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let[flag,settings]=await Promise.all([getFlag(client,project.id,flagArg),getFlagSettings(client,project.id)]);output_manager_default.stopSpinner(),logArchivedFlagNotice(flag);let selectedEnvironment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to roll out in:",{showEnvironmentDetails:!0,decorateChoices:!1}),currentOutcome=flag.environments[selectedEnvironment].fallthrough,rolloutConfig=resolveFlagRollout(flag,settings,{stageInputs,finalPercentage,baseSelector,rollFromVariantSelector,rollToVariantSelector,defaultVariantSelector,start,currentOutcome:currentOutcome.type==="experiment"?void 0:currentOutcome}),nextEnvironmentConfig=buildOutcomeEnvConfig(flag.environments[selectedEnvironment],{outcome:rolloutConfig.outcome,defaultVariantId:rolloutConfig.defaultVariant.id});if(flag.environments[selectedEnvironment].active&&(0,import_fast_deep_equal6.default)(flag.environments[selectedEnvironment].fallthrough,rolloutConfig.outcome)&&(0,import_fast_deep_equal6.default)(flag.environments[selectedEnvironment],nextEnvironmentConfig))return output_manager_default.warn(`Flag ${import_chalk59.default.bold(flag.slug)} is already configured with this rollout in ${selectedEnvironment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultRolloutMessage(selectedEnvironment,rolloutConfig));output_manager_default.spinner(`Updating rollout in ${selectedEnvironment}...`),await updateFlag(client,project.id,flagArg,{environments:{[selectedEnvironment]:nextEnvironmentConfig},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk59.default.bold(flag.slug)} rollout has been updated in ${import_chalk59.default.bold(selectedEnvironment)}`),output_manager_default.log(` ${import_chalk59.default.dim("Based on:")} ${rolloutConfig.baseLabel}`),output_manager_default.log(` ${import_chalk59.default.dim("Roll from:")} ${formatVariantLabel(rolloutConfig.rollFromVariant)}`),output_manager_default.log(` ${import_chalk59.default.dim("Roll to:")} ${formatVariantLabel(rolloutConfig.rollToVariant)}`),output_manager_default.log(` ${import_chalk59.default.dim("Fallback:")} ${formatVariantLabel(rolloutConfig.defaultVariant)}`),output_manager_default.log(` ${import_chalk59.default.dim("Start:")} ${rolloutConfig.startLabel}`),output_manager_default.log(` ${import_chalk59.default.dim("Stages:")} ${rolloutConfig.summary}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function getDefaultRolloutMessage(environment,rolloutConfig){return`Configure rollout for ${environment}: ${rolloutConfig.summary}`}function formatVariantLabel(variant){return variant.label||variant.id}var import_chalk60=__toESM(require_source(),1);async function deleteFlag(client,projectId,flagIdOrSlug){output_manager_default.debug(`Deleting feature flag ${flagIdOrSlug} for project ${projectId}`);let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags/${encodeURIComponent(flagIdOrSlug)}`;await client.fetch(url,{method:"DELETE"})}var FlagsRmTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};async function rm(client,argv){let telemetryClient=new FlagsRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(removeSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to delete"),output_manager_default.log(`Example: ${getCommandName("flags delete my-feature")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),flag.state!=="archived")return output_manager_default.error(`Flag ${import_chalk60.default.bold(flag.slug)} must be archived before it can be deleted. Run ${getCommandName(`flags archive ${flag.slug}`)} first.`),1;if(!skipConfirmation){if(!client.stdin.isTTY)return output_manager_default.error("Missing required option --yes. Use --yes to skip the confirmation prompt in non-interactive mode."),2;if(!await client.input.confirm(`Are you sure you want to delete ${import_chalk60.default.bold(flag.slug)}? This action cannot be undone.`,!1))return output_manager_default.log("Aborted"),0}output_manager_default.spinner("Deleting flag..."),await deleteFlag(client,project.id,flagArg),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk60.default.bold(flag.slug)} has been deleted`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk61=__toESM(require_source(),1);var FlagsArchiveTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};var EVALUATION_WINDOW_DAYS=3;async function archive(client,argv){let telemetryClient=new FlagsArchiveTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(archiveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,skipConfirmation=flags["--yes"],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to archive"),output_manager_default.log(`Example: ${getCommandName("flags archive my-feature")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),flag.state==="archived")return output_manager_default.warn(`Flag ${import_chalk61.default.bold(flag.slug)} is already archived`),0;if(!skipConfirmation&&!client.stdin.isTTY)return output_manager_default.error("Missing required option --yes. Use --yes to skip the confirmation prompt in non-interactive mode."),2;output_manager_default.spinner("Checking recent evaluations...");let endTime=new Date,startTime=new Date(endTime.getTime()-EVALUATION_WINDOW_DAYS*24*60*60*1e3),evaluations2=await countFlagEvaluations(client,{ownerId:org.id,projectId:project.id,flagSlug:flag.slug,startTime,endTime});output_manager_default.stopSpinner();let window=`the last ${EVALUATION_WINDOW_DAYS} days`;if(evaluations2===null){let evaluationsCommand=["flags","evaluations",flag.slug,"--since",`${EVALUATION_WINDOW_DAYS}d`,...getGlobalFlagsFromArgs(client.argv.slice(2),{preserveProject:!0})].map(quoteArg).join(" ");output_manager_default.log(`Could not check recent evaluations for ${import_chalk61.default.bold(flag.slug)}. Run ${getCommandName(evaluationsCommand)} to verify the flag is no longer evaluated.`)}else evaluations2>0?output_manager_default.warn(`${import_chalk61.default.bold(flag.slug)} reported ${evaluations2.toLocaleString()} ${evaluations2===1?"evaluation":"evaluations"} in ${window}. Archived flags evaluate to the default value in code. Remove the flag from your code and deploy before archiving.`):output_manager_default.log(`No evaluations reported for ${import_chalk61.default.bold(flag.slug)} in ${window}.`);if(!skipConfirmation&&!await client.input.confirm(evaluations2!==null&&evaluations2>0?`Archive ${import_chalk61.default.bold(flag.slug)} anyway?`:`Are you sure you want to archive ${import_chalk61.default.bold(flag.slug)}?`,!1))return output_manager_default.log("Aborted"),0;output_manager_default.spinner("Archiving flag..."),await updateFlag(client,project.id,flagArg,{state:"archived",message:message??"Archived via CLI"}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk61.default.bold(flag.slug)} has been archived`),output_manager_default.log(`
|
|
275
|
+
To unarchive this flag, run ${getCommandName(`flags unarchive ${flag.slug}`)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk62=__toESM(require_source(),1);var FlagsUnarchiveTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};async function unarchive(client,argv){let telemetryClient=new FlagsUnarchiveTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(unarchiveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to unarchive"),output_manager_default.log(`Example: ${getCommandName("flags unarchive my-feature")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),flag.state==="active")return output_manager_default.warn(`Flag ${import_chalk62.default.bold(flag.slug)} is already active`),0;if(!skipConfirmation){if(!client.stdin.isTTY)return output_manager_default.error("Missing required option --yes. Use --yes to skip the confirmation prompt in non-interactive mode."),2;if(!await client.input.confirm(`Are you sure you want to unarchive ${import_chalk62.default.bold(flag.slug)}?`,!1))return output_manager_default.log("Aborted"),0}output_manager_default.spinner("Unarchiving flag..."),await updateFlag(client,project.id,flagArg,{state:"active",message:"Unarchive"}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk62.default.bold(flag.slug)} has been unarchived`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk64=__toESM(require_source(),1);var import_chalk63=__toESM(require_source(),1);function logNonBooleanFlagGuidance(flag,{attemptedSubcommand,environment,isInteractive,teamSlug,projectName}){let dashboardUrl=getFlagDashboardUrl(teamSlug,projectName,flag.slug),suggestedEnvironment=environment&&environment in flag.environments?environment:void 0;if(output_manager_default.warn(`The ${getCommandName(`flags ${attemptedSubcommand}`)} command only works with boolean flags.`),output_manager_default.log(`Flag ${import_chalk63.default.bold(flag.slug)} is a ${import_chalk63.default.cyan(flag.kind)} flag. Set a specific variant instead:`),output_manager_default.log(` ${getCommandName(getSuggestedSetCommand(flag.slug,suggestedEnvironment,isInteractive))}`),flag.variants.length>0){output_manager_default.log("Available variants:");for(let variant of flag.variants)output_manager_default.log(` - ${formatVariantForDisplay(variant)}`)}output_manager_default.log(`See full flag details with ${getCommandName(`flags inspect ${flag.slug}`)}`),output_manager_default.log(`Open in the dashboard: ${import_chalk63.default.cyan(dashboardUrl)}`)}function getSuggestedSetCommand(slug,environment,isInteractive){let parts=[`flags set ${slug}`];return environment?parts.push(`--environment ${environment}`):isInteractive||parts.push("--environment <ENV>"),isInteractive||parts.push("--variant <VARIANT>"),parts.join(" ")}var FlagsDisableTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionVariant(variant){variant&&this.trackCliOption({option:"variant",value:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function disable3(client,argv){let telemetryClient=new FlagsDisableTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(disableSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],variantId=flags["--variant"],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg){if(client.nonInteractive){let envPart=environment?`--environment ${environment}`:"--environment <production|preview|development>";return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide a flag slug or ID to disable.",next:[{command:buildCommandWithGlobalFlags(client.argv,`flags disable <flag> ${envPart}`),when:"disable a feature flag by slug or ID"}]},2),2}return output_manager_default.error("Please provide a flag slug or ID to disable"),output_manager_default.log(`Example: ${getCommandName("flags disable my-feature --environment production")}`),2}telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionVariant(variantId),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. Run link first.",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"link the project"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),logArchivedFlagNotice(flag),flag.kind!=="boolean")return logNonBooleanFlagGuidance(flag,{attemptedSubcommand:"disable",environment,isInteractive:!!client.stdin.isTTY,teamSlug:link.org.slug,projectName:project.name}),0;if(!environment&&client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide --environment (production, preview, or development) to disable the flag in.",next:[{command:buildCommandWithGlobalFlags(client.argv,`flags disable ${flagArg} --environment <production|preview|development>`),when:"disable the flag in a specific environment"}]},2),2;environment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to disable the flag in:");let envConfig=flag.environments[environment],selectedVariant=getBooleanVariant(flag,!1);if(variantId){let result=resolveVariant(variantId,flag.variants);if(result.error)return output_manager_default.error(result.error),1;selectedVariant=result.variant}if(isPausingEnvironmentToVariant(envConfig,selectedVariant.id))return output_manager_default.warn(`Flag ${import_chalk64.default.bold(flag.slug)} is already disabled in ${environment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultDisableMessage(environment));output_manager_default.spinner(`Disabling flag in ${environment}...`),await updateFlag(client,project.id,flagArg,{environments:{[environment]:buildPausedEnvironmentConfig(envConfig,selectedVariant.id)},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk64.default.bold(flag.slug)} ${flag.state==="archived"?"configuration has been updated":"has been disabled"} in ${import_chalk64.default.bold(environment)}`),output_manager_default.log(` ${import_chalk64.default.dim(flag.state==="archived"?"Configured variant:":"Serving variant:")} ${formatVariantForDisplay(selectedVariant)}`)}catch(err){output_manager_default.stopSpinner();let message2=err instanceof Error?err.message:String(err);return client.nonInteractive&&message2.startsWith("Invalid environment:")?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message:message2,next:[{command:buildCommandWithGlobalFlags(client.argv,`flags disable ${flagArg} --environment <production|preview|development>`),when:"use a valid environment (production, preview, or development)"}]},2),2):(printError(err),2)}return 0}function getDefaultDisableMessage(environment){return`Disabled for ${environment} via CLI`}var import_chalk65=__toESM(require_source(),1);var FlagsEnableTelemetryClient=class extends TelemetryClient{trackCliArgumentFlag(flag){flag&&this.trackCliArgument({arg:"flag",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:STANDARD_ENVIRONMENTS.includes(environment)?environment:this.redactedValue})}trackCliOptionMessage(message){message&&this.trackCliOption({option:"message",value:this.redactedValue})}};async function enable3(client,argv){let telemetryClient=new FlagsEnableTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(enableSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],message=normalizeOptionalInput(flags["--message"]),projectName=getProjectNameFromFlags(flags);if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to enable"),output_manager_default.log(`Example: ${getCommandName("flags enable my-feature --environment production")}`),2;telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionMessage(message);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{output_manager_default.spinner("Fetching flag...");let flag=await getFlag(client,project.id,flagArg);if(output_manager_default.stopSpinner(),logArchivedFlagNotice(flag),flag.kind!=="boolean")return logNonBooleanFlagGuidance(flag,{attemptedSubcommand:"enable",environment,isInteractive:!!client.stdin.isTTY,teamSlug:link.org.slug,projectName:project.name}),0;if(!environment&&client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide --environment (production, preview, or development) to enable the flag in.",next:[{command:buildCommandWithGlobalFlags(client.argv,`flags enable ${flagArg} --environment <production|preview|development>`),when:"enable the flag in a specific environment"}]},2),2;environment=await resolveFlagEnvironment(client,flag,environment,"Select an environment to enable the flag in:");let envConfig=flag.environments[environment],onVariant=getBooleanVariant(flag,!0);if(isPausingEnvironmentToVariant(envConfig,onVariant.id))return output_manager_default.warn(`Flag ${import_chalk65.default.bold(flag.slug)} is already enabled in ${environment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,getDefaultEnableMessage(environment));output_manager_default.spinner(`Enabling flag in ${environment}...`),await updateFlag(client,project.id,flagArg,{environments:{[environment]:buildPausedEnvironmentConfig(envConfig,onVariant.id)},message:updateMessage}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag ${import_chalk65.default.bold(flag.slug)} ${flag.state==="archived"?"configuration has been updated":"has been enabled"} in ${import_chalk65.default.bold(environment)}`),output_manager_default.log(` ${import_chalk65.default.dim(flag.state==="archived"?"Configured variant:":"Serving variant:")} ${formatVariantForDisplay(onVariant)}`)}catch(err){output_manager_default.stopSpinner();let message2=err instanceof Error?err.message:String(err);return client.nonInteractive&&message2.startsWith("Invalid environment:")?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.INVALID_ARGUMENTS,message:message2,next:[{command:buildCommandWithGlobalFlags(client.argv,`flags enable ${flagArg} --environment <production|preview|development>`),when:"use a valid environment (production, preview, or development)"}]},2),2):(printError(err),2)}return 0}function getDefaultEnableMessage(environment){return`Enabled for ${environment} via CLI`}var FlagsSdkKeysTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandCreate(actual){this.trackCliSubcommand({subcommand:"create",value:actual})}trackCliSubcommandRevoke(actual){this.trackCliSubcommand({subcommand:"revoke",value:actual})}},FlagsSdkKeysLsTelemetryClient=class extends TelemetryClient{trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSdkKeysAddTelemetryClient=class extends TelemetryClient{trackCliOptionType(type){type&&this.trackCliOption({option:"type",value:type})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:environment})}trackCliOptionLabel(label){label&&this.trackCliOption({option:"label",value:this.redactedValue})}},FlagsSdkKeysRmTelemetryClient=class extends TelemetryClient{trackCliArgumentKey(key){key&&this.trackCliArgument({arg:"key",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};var import_chalk66=__toESM(require_source(),1),import_ms4=__toESM(require_ms(),1);async function sdkKeysLs(client,argv){let telemetryClient=new FlagsSdkKeysLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(sdkKeysListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,json=flags["--json"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagJson(json);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name);try{output_manager_default.spinner("Fetching SDK keys...");let keys=await getSdkKeys(client,project.id);output_manager_default.stopSpinner();let sortedKeys=keys.sort((a,b)=>b.createdAt-a.createdAt);json?outputSdkKeysJson(client,sortedKeys):keys.length===0?(output_manager_default.log(`No SDK keys found for ${projectSlugLink}`),output_manager_default.log(`
|
|
276
276
|
Create one with: ${getCommandName("flags sdk-keys create --type server --environment production")}`)):(output_manager_default.log(`${import_chalk66.default.bold(keys.length)} SDK key${keys.length===1?"":"s"} found for ${projectSlugLink}`),printSdkKeysTable(sortedKeys))}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function outputSdkKeysJson(client,keys){let jsonOutput={sdkKeys:keys.map(key=>({hashKey:key.hashKey,type:key.type,environment:key.environment,label:key.label??null,partialKeyValue:key.partialKeyValue??null,createdAt:key.createdAt,updatedAt:key.updatedAt}))};client.stdout.write(`${JSON.stringify(jsonOutput,null,2)}
|
|
277
277
|
`)}function printSdkKeysTable(keys){let headers=["Hash Key","Type","Environment","Label","Partial Key Value","Created"],now=Date.now(),rows=keys.map(key=>[import_chalk66.default.dim(key.hashKey.slice(0,12)+"..."),getTypeLabel(key.type),key.environment,key.label||import_chalk66.default.dim("-"),key.partialKeyValue||import_chalk66.default.dim("-"),(0,import_ms4.default)(now-key.createdAt)+" ago"]),table2=formatTable(headers,["l","l","l","l","l","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
278
278
|
${table2}
|
|
@@ -286,14 +286,14 @@ ${table2}
|
|
|
286
286
|
${import_chalk67.default.cyan(key.keyValue)}
|
|
287
287
|
`)),key.connectionString&&(output_manager_default.print(`
|
|
288
288
|
`),output_manager_default.log(`${import_chalk67.default.dim("Connection string:")}`),output_manager_default.print(` ${import_chalk67.default.cyan(key.connectionString)}
|
|
289
|
-
`))}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk68=__toESM(require_source(),1);async function sdkKeysRm(client,argv){let telemetryClient=new FlagsSdkKeysRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(sdkKeysRemoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[hashKey]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentKey(hashKey),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. A user must run `vercel link` in a terminal to continue (this will prompt for login if needed).",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"run in a terminal to log in if needed and link this codebase to a Vercel project, then retry this command"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{if(!hashKey){if(client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide the SDK key hash to delete. Run `vercel flags sdk-keys ls` to list keys.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags sdk-keys revoke <hashKey>"),when:"delete an SDK key by hash"},{command:buildCommandWithGlobalFlags(client.argv,"flags sdk-keys ls"),when:"list SDK keys to find the hash"}]},2),2;output_manager_default.spinner("Fetching SDK keys...");let keys=await getSdkKeys(client,project.id);if(output_manager_default.stopSpinner(),keys.length===0)return output_manager_default.log("No SDK keys found"),0;hashKey=await client.input.select({message:"Select an SDK key to delete:",choices:keys.map(key=>({name:`${key.hashKey.slice(0,12)}... (${key.type}, ${key.environment}${key.label?`, ${key.label}`:""})`,value:key.hashKey}))})}if(!skipConfirmation){if(client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`Confirm revoking SDK key ${hashKey.slice(0,12)}... by adding --yes.`,next:[{command:buildCommandWithGlobalFlags(client.argv,`flags sdk-keys revoke ${hashKey} --yes`),when:"confirm and revoke the SDK key"}]},1),1;if(!await client.input.confirm(`Are you sure you want to revoke SDK key ${import_chalk68.default.bold(hashKey.slice(0,12)+"...")}?`,!1))return output_manager_default.log("Aborted"),0}output_manager_default.spinner("Revoking SDK key..."),await deleteSdkKey(client,project.id,hashKey),output_manager_default.stopSpinner(),output_manager_default.success(`SDK key ${import_chalk68.default.bold(hashKey.slice(0,12)+"...")} has been revoked`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG11={ls:getCommandAliases(sdkKeysListSubcommand),add:getCommandAliases(sdkKeysAddSubcommand),revoke:getCommandAliases(sdkKeysRemoveSubcommand)};async function sdkKeys(client){let telemetry=new FlagsSdkKeysTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(sdkKeysSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let subArgs=parsedArgs.args.slice(0),{subcommand,args,subcommandOriginal}=getSubcommand(subArgs,COMMAND_CONFIG11),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags sdk-keys",subcommand),output_manager_default.print(help(sdkKeysSubcommand,{parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:sdkKeysSubcommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags sdk-keys",subcommandOriginal),printHelp(sdkKeysListSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),sdkKeysLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags sdk-keys",subcommandOriginal),printHelp(sdkKeysAddSubcommand),0):(telemetry.trackCliSubcommandCreate(subcommandOriginal),subcommandOriginal==="add"&&warnDeprecatedSubcommand(client,"flags sdk-keys add","flags sdk-keys create"),sdkKeysAdd(client,args));case"revoke":return needHelp?(telemetry.trackCliFlagHelp("flags sdk-keys",subcommandOriginal),printHelp(sdkKeysRemoveSubcommand),0):(telemetry.trackCliSubcommandRevoke(subcommandOriginal),subcommandOriginal!=="revoke"&&warnDeprecatedSubcommand(client,`flags sdk-keys ${subcommandOriginal}`,"flags sdk-keys revoke"),sdkKeysRm(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG11)),output_manager_default.print(help(sdkKeysSubcommand,{parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsConnectionsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandAdd(actual){this.trackCliSubcommand({subcommand:"add",value:actual})}trackCliSubcommandRemove(actual){this.trackCliSubcommand({subcommand:"rm",value:actual})}},FlagsConnectionsLsTelemetryClient=class extends TelemetryClient{trackCliOptionRole(role){role&&this.trackCliOption({option:"role",value:role})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsConnectionsAddTelemetryClient=class extends TelemetryClient{trackCliArgumentConsumerProject(project){project&&this.trackCliArgument({arg:"consumer-project",value:this.redactedValue})}},FlagsConnectionsRmTelemetryClient=class extends TelemetryClient{trackCliArgumentConsumerProject(project){project&&this.trackCliArgument({arg:"consumer-project",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};var import_chalk69=__toESM(require_source(),1),import_ms5=__toESM(require_ms(),1);function connectionsUrl(projectId){return`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/connections`}async function getConnections(client,projectId,role){return output_manager_default.debug(`Fetching flags connections for project ${projectId} as ${role}`),(await client.fetch(`${connectionsUrl(projectId)}?role=${role}`)).data}async function createConnection(client,sourceProjectId,consumerProjectId){return output_manager_default.debug(`Connecting project ${consumerProjectId} to the flags of project ${sourceProjectId}`),client.fetch(connectionsUrl(sourceProjectId),{method:"PUT",body:{consumerProjectId}})}async function deleteConnection(client,sourceProjectId,consumerProjectId){output_manager_default.debug(`Disconnecting project ${consumerProjectId} from the flags of project ${sourceProjectId}`),await client.fetch(`${connectionsUrl(sourceProjectId)}/${encodeURIComponent(consumerProjectId)}`,{method:"DELETE",json:!1})}function connectionsCommand(client,template){return buildCommandWithGlobalFlags(client.argv,template,void 0,{preserveProject:!0,excludeFlags:["--yes"]})}function connectionsError(client,payload,exitCode=1){return outputAgentError(client,{...payload,status:AGENT_STATUS.ERROR,next:payload.next?.map(next=>({...next,command:connectionsCommand(client,next.command)}))},exitCode),client.nonInteractive||output_manager_default.fatal(payload.message),exitCode}async function resolveSourceProject(client,projectName){let link=await getLinkedFlagsProject(client,projectName);return link.status==="error"?link.exitCode:link.status==="not_linked"?connectionsError(client,{reason:AGENT_REASON.NOT_LINKED,message:`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`,next:[{command:"link",when:"link the project"}]}):(client.config.currentTeam=link.org.type==="team"?link.org.id:void 0,link)}async function resolveConsumerProject(client,link,consumerNameOrId,usage){if(!consumerNameOrId)return connectionsError(client,{reason:AGENT_REASON.MISSING_ARGUMENTS,message:`Please provide the name or ID of the consumer project: ${getCommandName(usage)}`,next:[{command:usage,when:"name the consumer project"}]},2);let consumer;try{consumer=await getProjectByNameOrId(client,consumerNameOrId,link.org.type==="team"?link.org.id:void 0)}catch(err){return printError(err),1}return consumer instanceof ProjectNotFound?connectionsError(client,{reason:AGENT_REASON.NOT_FOUND,message:`Project "${consumerNameOrId}" was not found in team ${link.org.slug}.`}):consumer.id===link.project.id?connectionsError(client,{reason:AGENT_REASON.INVALID_ARGUMENTS,message:"A project cannot be connected to its own flags."},2):consumer}var VALID_ROLES=["source","consumer"];async function connectionsLs(client,argv){let telemetryClient=new FlagsConnectionsLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(connectionsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,json=flags["--json"],role=flags["--role"]??"source",projectName=getProjectNameFromFlags(flags);if(telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionRole(flags["--role"]),telemetryClient.trackCliFlagJson(json),!isRole(role))return connectionsError(client,{reason:AGENT_REASON.INVALID_ARGUMENTS,message:`Invalid role: ${role}. Must be one of: ${VALID_ROLES.join(", ")}`,next:[{command:"flags connections ls --role <source|consumer>",when:"list connections for a valid role"}]},2);let link=await resolveSourceProject(client,projectName);if(typeof link=="number")return link;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),accountId=org.type==="team"?org.id:void 0;try{output_manager_default.spinner("Fetching flags connections...");let sorted=(await getConnections(client,project.id,role)).sort((a,b)=>b.createdAt-a.createdAt),names=json?new Map:await resolveProjectNames(client,sorted,role,accountId);if(output_manager_default.stopSpinner(),json)client.stdout.write(`${JSON.stringify({role,connections:sorted},null,2)}
|
|
289
|
+
`))}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk68=__toESM(require_source(),1);async function sdkKeysRm(client,argv){let telemetryClient=new FlagsSdkKeysRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(sdkKeysRemoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[hashKey]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentKey(hashKey),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. A user must run `vercel link` in a terminal to continue (this will prompt for login if needed).",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"run in a terminal to log in if needed and link this codebase to a Vercel project, then retry this command"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{if(!hashKey){if(client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide the SDK key hash to delete. Run `vercel flags sdk-keys ls` to list keys.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags sdk-keys revoke <hashKey>"),when:"delete an SDK key by hash"},{command:buildCommandWithGlobalFlags(client.argv,"flags sdk-keys ls"),when:"list SDK keys to find the hash"}]},2),2;output_manager_default.spinner("Fetching SDK keys...");let keys=await getSdkKeys(client,project.id);if(output_manager_default.stopSpinner(),keys.length===0)return output_manager_default.log("No SDK keys found"),0;hashKey=await client.input.select({message:"Select an SDK key to delete:",choices:keys.map(key=>({name:`${key.hashKey.slice(0,12)}... (${key.type}, ${key.environment}${key.label?`, ${key.label}`:""})`,value:key.hashKey}))})}if(!skipConfirmation){if(client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`Confirm revoking SDK key ${hashKey.slice(0,12)}... by adding --yes.`,next:[{command:buildCommandWithGlobalFlags(client.argv,`flags sdk-keys revoke ${hashKey} --yes`),when:"confirm and revoke the SDK key"}]},1),1;if(!await client.input.confirm(`Are you sure you want to revoke SDK key ${import_chalk68.default.bold(hashKey.slice(0,12)+"...")}?`,!1))return output_manager_default.log("Aborted"),0}output_manager_default.spinner("Revoking SDK key..."),await deleteSdkKey(client,project.id,hashKey),output_manager_default.stopSpinner(),output_manager_default.success(`SDK key ${import_chalk68.default.bold(hashKey.slice(0,12)+"...")} has been revoked`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG11={ls:getCommandAliases(sdkKeysListSubcommand),add:getCommandAliases(sdkKeysAddSubcommand),revoke:getCommandAliases(sdkKeysRemoveSubcommand)};async function sdkKeys(client){let telemetry=new FlagsSdkKeysTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(sdkKeysSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let subArgs=parsedArgs.args.slice(0),{subcommand,args,subcommandOriginal}=getSubcommand(subArgs,COMMAND_CONFIG11),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags sdk-keys",subcommand),output_manager_default.print(help(sdkKeysSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:sdkKeysSubcommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags sdk-keys",subcommandOriginal),printHelp(sdkKeysListSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),sdkKeysLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags sdk-keys",subcommandOriginal),printHelp(sdkKeysAddSubcommand),0):(telemetry.trackCliSubcommandCreate(subcommandOriginal),subcommandOriginal==="add"&&warnDeprecatedSubcommand(client,"flags sdk-keys add","flags sdk-keys create"),sdkKeysAdd(client,args));case"revoke":return needHelp?(telemetry.trackCliFlagHelp("flags sdk-keys",subcommandOriginal),printHelp(sdkKeysRemoveSubcommand),0):(telemetry.trackCliSubcommandRevoke(subcommandOriginal),subcommandOriginal!=="revoke"&&warnDeprecatedSubcommand(client,`flags sdk-keys ${subcommandOriginal}`,"flags sdk-keys revoke"),sdkKeysRm(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG11)),output_manager_default.print(help(sdkKeysSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsConnectionsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandAdd(actual){this.trackCliSubcommand({subcommand:"add",value:actual})}trackCliSubcommandRemove(actual){this.trackCliSubcommand({subcommand:"rm",value:actual})}},FlagsConnectionsLsTelemetryClient=class extends TelemetryClient{trackCliOptionRole(role){role&&this.trackCliOption({option:"role",value:role})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsConnectionsAddTelemetryClient=class extends TelemetryClient{trackCliArgumentConsumerProject(project){project&&this.trackCliArgument({arg:"consumer-project",value:this.redactedValue})}},FlagsConnectionsRmTelemetryClient=class extends TelemetryClient{trackCliArgumentConsumerProject(project){project&&this.trackCliArgument({arg:"consumer-project",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};var import_chalk69=__toESM(require_source(),1),import_ms5=__toESM(require_ms(),1);function connectionsUrl(projectId){return`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/connections`}async function getConnections(client,projectId,role){return output_manager_default.debug(`Fetching flags connections for project ${projectId} as ${role}`),(await client.fetch(`${connectionsUrl(projectId)}?role=${role}`)).data}async function createConnection(client,sourceProjectId,consumerProjectId){return output_manager_default.debug(`Connecting project ${consumerProjectId} to the flags of project ${sourceProjectId}`),client.fetch(connectionsUrl(sourceProjectId),{method:"PUT",body:{consumerProjectId}})}async function deleteConnection(client,sourceProjectId,consumerProjectId){output_manager_default.debug(`Disconnecting project ${consumerProjectId} from the flags of project ${sourceProjectId}`),await client.fetch(`${connectionsUrl(sourceProjectId)}/${encodeURIComponent(consumerProjectId)}`,{method:"DELETE",json:!1})}function connectionsCommand(client,template){return buildCommandWithGlobalFlags(client.argv,template,void 0,{preserveProject:!0,excludeFlags:["--yes"]})}function connectionsError(client,payload,exitCode=1){return outputAgentError(client,{...payload,status:AGENT_STATUS.ERROR,next:payload.next?.map(next=>({...next,command:connectionsCommand(client,next.command)}))},exitCode),client.nonInteractive||output_manager_default.fatal(payload.message),exitCode}async function resolveSourceProject(client,projectName){let link=await getLinkedFlagsProject(client,projectName);return link.status==="error"?link.exitCode:link.status==="not_linked"?connectionsError(client,{reason:AGENT_REASON.NOT_LINKED,message:`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`,next:[{command:"link",when:"link the project"}]}):(client.config.currentTeam=link.org.type==="team"?link.org.id:void 0,link)}async function resolveConsumerProject(client,link,consumerNameOrId,usage){if(!consumerNameOrId)return connectionsError(client,{reason:AGENT_REASON.MISSING_ARGUMENTS,message:`Please provide the name or ID of the consumer project: ${getCommandName(usage)}`,next:[{command:usage,when:"name the consumer project"}]},2);let consumer;try{consumer=await getProjectByNameOrId(client,consumerNameOrId,link.org.type==="team"?link.org.id:void 0)}catch(err){return printError(err),1}return consumer instanceof ProjectNotFound?connectionsError(client,{reason:AGENT_REASON.NOT_FOUND,message:`Project "${consumerNameOrId}" was not found in team ${link.org.slug}.`}):consumer.id===link.project.id?connectionsError(client,{reason:AGENT_REASON.INVALID_ARGUMENTS,message:"A project cannot be connected to its own flags."},2):consumer}var VALID_ROLES=["source","consumer"];async function connectionsLs(client,argv){let telemetryClient=new FlagsConnectionsLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(connectionsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,json=flags["--json"],role=flags["--role"]??"source",projectName=getProjectNameFromFlags(flags);if(telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionRole(flags["--role"]),telemetryClient.trackCliFlagJson(json),!isRole(role))return connectionsError(client,{reason:AGENT_REASON.INVALID_ARGUMENTS,message:`Invalid role: ${role}. Must be one of: ${VALID_ROLES.join(", ")}`,next:[{command:"flags connections ls --role <source|consumer>",when:"list connections for a valid role"}]},2);let link=await resolveSourceProject(client,projectName);if(typeof link=="number")return link;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),accountId=org.type==="team"?org.id:void 0;try{output_manager_default.spinner("Fetching flags connections...");let sorted=(await getConnections(client,project.id,role)).sort((a,b)=>b.createdAt-a.createdAt),names=json?new Map:await resolveProjectNames(client,sorted,role,accountId);if(output_manager_default.stopSpinner(),json)client.stdout.write(`${JSON.stringify({role,connections:sorted},null,2)}
|
|
290
290
|
`);else if(sorted.length===0)role==="source"?(output_manager_default.log(`No project may read the flags of ${projectSlugLink}`),output_manager_default.log(`
|
|
291
291
|
Connect one with: ${import_chalk69.default.cyan(connectionsCommand(client,"flags connections add <consumer-project>"))}`)):(output_manager_default.log(`${projectSlugLink} may not read the flags of any project`),output_manager_default.log(`
|
|
292
292
|
Ask an owner of the source project to run: ${getCommandName(`flags connections add ${quoteArg(project.name)} --project <source-project>`)}`));else{let count=`${import_chalk69.default.bold(sorted.length)} project${sorted.length===1?"":"s"}`;output_manager_default.log(role==="source"?`${count} may read the flags of ${projectSlugLink}`:`${projectSlugLink} may read the flags of ${count}`),printConnectionsTable(sorted,role,names)}}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function isRole(value){return VALID_ROLES.includes(value)}function otherProjectId(connection,role){return role==="source"?connection.consumerProjectId:connection.sourceProjectId}async function resolveProjectNames(client,connections2,role,accountId){let ids=[...new Set(connections2.map(c=>otherProjectId(c,role)))],entries=await Promise.all(ids.map(async id=>{try{let project=await getProjectByNameOrId(client,id,accountId);return[id,project instanceof Error?id:project.name]}catch{return[id,id]}}));return new Map(entries)}function printConnectionsTable(connections2,role,names){let now=Date.now(),header=role==="source"?"Consumer Project":"Source Project",rows=connections2.map(connection=>{let id=otherProjectId(connection,role),name=names.get(id)??id;return[name===id?id:`${name} ${import_chalk69.default.dim(id)}`,import_chalk69.default.dim(connection.createdBy),(0,import_ms5.default)(now-connection.createdAt)+" ago"]}),table2=formatTable([header,"Created By","Created"],["l","l","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
293
293
|
${table2}
|
|
294
294
|
`)}var import_chalk70=__toESM(require_source(),1);async function connectionsAdd(client,argv){let telemetryClient=new FlagsConnectionsAddTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(connectionsAddSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[consumerNameOrId]=args,projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentConsumerProject(consumerNameOrId),telemetryClient.trackCliOptionProject(projectName);let link=await resolveSourceProject(client,projectName);if(typeof link=="number")return link;let consumer=await resolveConsumerProject(client,link,consumerNameOrId,"flags connections add <consumer-project>");if(typeof consumer=="number")return consumer;let source=link.project;try{output_manager_default.spinner("Connecting project..."),await createConnection(client,source.id,consumer.id),output_manager_default.stopSpinner()}catch(err){return output_manager_default.stopSpinner(),isAPIError(err)&&err.code==="flags_project_connection_exists"?(output_manager_default.log(`${import_chalk70.default.bold(consumer.name)} already may read the flags of ${import_chalk70.default.bold(source.name)}`),0):(printError(err),1)}return output_manager_default.success(`${import_chalk70.default.bold(consumer.name)} may now read the flags of ${import_chalk70.default.bold(source.name)}`),output_manager_default.print(`
|
|
295
295
|
`),output_manager_default.print(` ${import_chalk70.default.dim("Source project ID:")} ${source.id}
|
|
296
|
-
`),0}var import_chalk71=__toESM(require_source(),1);async function connectionsRm(client,argv){let telemetryClient=new FlagsConnectionsRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(connectionsRemoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[consumerNameOrId]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentConsumerProject(consumerNameOrId),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await resolveSourceProject(client,projectName);if(typeof link=="number")return link;let consumer=await resolveConsumerProject(client,link,consumerNameOrId,"flags connections remove <consumer-project>");if(typeof consumer=="number")return consumer;let source=link.project;if(!skipConfirmation){if(client.nonInteractive)return connectionsError(client,{reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`Confirm removing the connection of ${consumer.name} to the flags of ${source.name} by adding --yes.`,next:[{command:`flags connections remove ${quoteArg(consumerNameOrId)} --yes`,when:"confirm and remove the connection"}]});if(!await client.input.confirm(`Stop ${import_chalk71.default.bold(consumer.name)} from reading the flags of ${import_chalk71.default.bold(source.name)}? Its deployments lose access right away.`,!1))return output_manager_default.log("Aborted"),0}try{output_manager_default.spinner("Removing connection..."),await deleteConnection(client,source.id,consumer.id),output_manager_default.stopSpinner(),output_manager_default.success(`${import_chalk71.default.bold(consumer.name)} may no longer read the flags of ${import_chalk71.default.bold(source.name)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG12={ls:getCommandAliases(connectionsListSubcommand),add:getCommandAliases(connectionsAddSubcommand),rm:getCommandAliases(connectionsRemoveSubcommand)};async function connections(client){let telemetry=new FlagsConnectionsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(connectionsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),1}let subArgs=parsedArgs.args.slice(0),{subcommand,args,subcommandOriginal}=getSubcommand(subArgs,COMMAND_CONFIG12),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags connections",subcommand),output_manager_default.print(help(connectionsSubcommand,{parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:connectionsSubcommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags connections",subcommandOriginal),printHelp(connectionsListSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),connectionsLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags connections",subcommandOriginal),printHelp(connectionsAddSubcommand),0):(telemetry.trackCliSubcommandAdd(subcommandOriginal),connectionsAdd(client,args));case"rm":return needHelp?(telemetry.trackCliFlagHelp("flags connections",subcommandOriginal),printHelp(connectionsRemoveSubcommand),0):(telemetry.trackCliSubcommandRemove(subcommandOriginal),connectionsRm(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG12)),output_manager_default.print(help(connectionsSubcommand,{parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsSegmentsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandInspect(actual){this.trackCliSubcommand({subcommand:"inspect",value:actual})}trackCliSubcommandCreate(actual){this.trackCliSubcommand({subcommand:"create",value:actual})}trackCliSubcommandUpdate(actual){this.trackCliSubcommand({subcommand:"update",value:actual})}trackCliSubcommandDelete(actual){this.trackCliSubcommand({subcommand:"delete",value:actual})}},FlagsSegmentsLsTelemetryClient=class extends TelemetryClient{trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsInspectTelemetryClient=class extends TelemetryClient{trackCliArgumentSegment(segment){segment&&this.trackCliArgument({arg:"segment",value:this.redactedValue})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsCreateTelemetryClient=class extends TelemetryClient{trackCliArgumentSlug(slug){slug&&this.trackCliArgument({arg:"slug",value:this.redactedValue})}trackCliOptionLabel(label){label&&this.trackCliOption({option:"label",value:this.redactedValue})}trackCliOptionDescription(description){description&&this.trackCliOption({option:"description",value:this.redactedValue})}trackCliOptionHint(hint){hint&&this.trackCliOption({option:"hint",value:this.redactedValue})}trackCliOptionData(data){data&&this.trackCliOption({option:"data",value:this.redactedValue})}trackCliOptionAdd(add3){add3?.length&&this.trackCliOption({option:"add",value:this.redactedValue})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsUpdateTelemetryClient=class extends TelemetryClient{trackCliArgumentSegment(segment){segment&&this.trackCliArgument({arg:"segment",value:this.redactedValue})}trackCliOptionLabel(label){label&&this.trackCliOption({option:"label",value:this.redactedValue})}trackCliOptionDescription(description){description&&this.trackCliOption({option:"description",value:this.redactedValue})}trackCliOptionHint(hint){hint&&this.trackCliOption({option:"hint",value:this.redactedValue})}trackCliOptionData(data){data&&this.trackCliOption({option:"data",value:this.redactedValue})}trackCliOptionAdd(add3){add3?.length&&this.trackCliOption({option:"add",value:this.redactedValue})}trackCliOptionRemove(remove3){remove3?.length&&this.trackCliOption({option:"remove",value:this.redactedValue})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsRmTelemetryClient=class extends TelemetryClient{trackCliArgumentSegment(segment){segment&&this.trackCliArgument({arg:"segment",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};var import_chalk72=__toESM(require_source(),1),import_ms6=__toESM(require_ms(),1),import_pluralize4=__toESM(require_pluralize(),1);function getSegmentsUrl(projectId,withMetadata=!1){let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/segments`;return withMetadata?`${url}?withMetadata=true`:url}function getSegmentUrl(projectId,segmentIdOrSlug,withMetadata=!1){let url=`${getSegmentsUrl(projectId)}/${encodeURIComponent(segmentIdOrSlug)}`;return withMetadata?`${url}?withMetadata=true`:url}async function getSegments(client,projectId,withMetadata=!1){return output_manager_default.debug(`Fetching feature flag segments for project ${projectId}`),(await client.fetch(getSegmentsUrl(projectId,withMetadata))).data}async function getSegment(client,projectId,segmentIdOrSlug,withMetadata=!0){return output_manager_default.debug(`Fetching feature flag segment ${segmentIdOrSlug} for project ${projectId}`),client.fetch(getSegmentUrl(projectId,segmentIdOrSlug,withMetadata))}async function createSegment(client,projectId,request){let url=getSegmentsUrl(projectId);return output_manager_default.debug(`Creating feature flag segment ${request.slug} for project ${projectId}`),output_manager_default.debug(`API endpoint: PUT ${url}`),client.fetch(url,{method:"PUT",body:request})}async function updateSegment(client,projectId,segmentIdOrSlug,request){let url=getSegmentUrl(projectId,segmentIdOrSlug);return output_manager_default.debug(`Updating feature flag segment ${segmentIdOrSlug} for project ${projectId}`),client.fetch(url,{method:"PATCH",body:request})}async function deleteSegment(client,projectId,segmentIdOrSlug){let url=getSegmentUrl(projectId,segmentIdOrSlug);output_manager_default.debug(`Deleting feature flag segment ${segmentIdOrSlug} for project ${projectId}`),await client.fetch(url,{method:"DELETE"})}async function segmentsLs(client,argv){let telemetryClient=new FlagsSegmentsLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(segmentsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,json=flags["--json"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagJson(json);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),lsStamp=stamp_default();output_manager_default.spinner(`Fetching feature flag segments for ${projectSlugLink}`);try{let segments2=await getSegments(client,project.id,!0);output_manager_default.stopSpinner();let sortedSegments=segments2.sort((a,b)=>b.updatedAt-a.updatedAt);json?outputJson5(client,sortedSegments):segments2.length===0?(output_manager_default.log(`No feature flag segments found for ${projectSlugLink} ${import_chalk72.default.gray(lsStamp())}`),output_manager_default.log(`
|
|
296
|
+
`),0}var import_chalk71=__toESM(require_source(),1);async function connectionsRm(client,argv){let telemetryClient=new FlagsConnectionsRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(connectionsRemoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[consumerNameOrId]=args,skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentConsumerProject(consumerNameOrId),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await resolveSourceProject(client,projectName);if(typeof link=="number")return link;let consumer=await resolveConsumerProject(client,link,consumerNameOrId,"flags connections remove <consumer-project>");if(typeof consumer=="number")return consumer;let source=link.project;if(!skipConfirmation){if(client.nonInteractive)return connectionsError(client,{reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`Confirm removing the connection of ${consumer.name} to the flags of ${source.name} by adding --yes.`,next:[{command:`flags connections remove ${quoteArg(consumerNameOrId)} --yes`,when:"confirm and remove the connection"}]});if(!await client.input.confirm(`Stop ${import_chalk71.default.bold(consumer.name)} from reading the flags of ${import_chalk71.default.bold(source.name)}? Its deployments lose access right away.`,!1))return output_manager_default.log("Aborted"),0}try{output_manager_default.spinner("Removing connection..."),await deleteConnection(client,source.id,consumer.id),output_manager_default.stopSpinner(),output_manager_default.success(`${import_chalk71.default.bold(consumer.name)} may no longer read the flags of ${import_chalk71.default.bold(source.name)}`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG12={ls:getCommandAliases(connectionsListSubcommand),add:getCommandAliases(connectionsAddSubcommand),rm:getCommandAliases(connectionsRemoveSubcommand)};async function connections(client){let telemetry=new FlagsConnectionsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(connectionsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),1}let subArgs=parsedArgs.args.slice(0),{subcommand,args,subcommandOriginal}=getSubcommand(subArgs,COMMAND_CONFIG12),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags connections",subcommand),output_manager_default.print(help(connectionsSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:connectionsSubcommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags connections",subcommandOriginal),printHelp(connectionsListSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),connectionsLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags connections",subcommandOriginal),printHelp(connectionsAddSubcommand),0):(telemetry.trackCliSubcommandAdd(subcommandOriginal),connectionsAdd(client,args));case"rm":return needHelp?(telemetry.trackCliFlagHelp("flags connections",subcommandOriginal),printHelp(connectionsRemoveSubcommand),0):(telemetry.trackCliSubcommandRemove(subcommandOriginal),connectionsRm(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG12)),output_manager_default.print(help(connectionsSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsSegmentsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandInspect(actual){this.trackCliSubcommand({subcommand:"inspect",value:actual})}trackCliSubcommandCreate(actual){this.trackCliSubcommand({subcommand:"create",value:actual})}trackCliSubcommandUpdate(actual){this.trackCliSubcommand({subcommand:"update",value:actual})}trackCliSubcommandDelete(actual){this.trackCliSubcommand({subcommand:"delete",value:actual})}},FlagsSegmentsLsTelemetryClient=class extends TelemetryClient{trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsInspectTelemetryClient=class extends TelemetryClient{trackCliArgumentSegment(segment){segment&&this.trackCliArgument({arg:"segment",value:this.redactedValue})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsCreateTelemetryClient=class extends TelemetryClient{trackCliArgumentSlug(slug){slug&&this.trackCliArgument({arg:"slug",value:this.redactedValue})}trackCliOptionLabel(label){label&&this.trackCliOption({option:"label",value:this.redactedValue})}trackCliOptionDescription(description){description&&this.trackCliOption({option:"description",value:this.redactedValue})}trackCliOptionHint(hint){hint&&this.trackCliOption({option:"hint",value:this.redactedValue})}trackCliOptionData(data){data&&this.trackCliOption({option:"data",value:this.redactedValue})}trackCliOptionAdd(add3){add3?.length&&this.trackCliOption({option:"add",value:this.redactedValue})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsUpdateTelemetryClient=class extends TelemetryClient{trackCliArgumentSegment(segment){segment&&this.trackCliArgument({arg:"segment",value:this.redactedValue})}trackCliOptionLabel(label){label&&this.trackCliOption({option:"label",value:this.redactedValue})}trackCliOptionDescription(description){description&&this.trackCliOption({option:"description",value:this.redactedValue})}trackCliOptionHint(hint){hint&&this.trackCliOption({option:"hint",value:this.redactedValue})}trackCliOptionData(data){data&&this.trackCliOption({option:"data",value:this.redactedValue})}trackCliOptionAdd(add3){add3?.length&&this.trackCliOption({option:"add",value:this.redactedValue})}trackCliOptionRemove(remove3){remove3?.length&&this.trackCliOption({option:"remove",value:this.redactedValue})}trackCliFlagJson(json){json&&this.trackCliFlag("json")}},FlagsSegmentsRmTelemetryClient=class extends TelemetryClient{trackCliArgumentSegment(segment){segment&&this.trackCliArgument({arg:"segment",value:this.redactedValue})}trackCliFlagYes(yes){yes&&this.trackCliFlag("yes")}};var import_chalk72=__toESM(require_source(),1),import_ms6=__toESM(require_ms(),1),import_pluralize4=__toESM(require_pluralize(),1);function getSegmentsUrl(projectId,withMetadata=!1){let url=`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/segments`;return withMetadata?`${url}?withMetadata=true`:url}function getSegmentUrl(projectId,segmentIdOrSlug,withMetadata=!1){let url=`${getSegmentsUrl(projectId)}/${encodeURIComponent(segmentIdOrSlug)}`;return withMetadata?`${url}?withMetadata=true`:url}async function getSegments(client,projectId,withMetadata=!1){return output_manager_default.debug(`Fetching feature flag segments for project ${projectId}`),(await client.fetch(getSegmentsUrl(projectId,withMetadata))).data}async function getSegment(client,projectId,segmentIdOrSlug,withMetadata=!0){return output_manager_default.debug(`Fetching feature flag segment ${segmentIdOrSlug} for project ${projectId}`),client.fetch(getSegmentUrl(projectId,segmentIdOrSlug,withMetadata))}async function createSegment(client,projectId,request){let url=getSegmentsUrl(projectId);return output_manager_default.debug(`Creating feature flag segment ${request.slug} for project ${projectId}`),output_manager_default.debug(`API endpoint: PUT ${url}`),client.fetch(url,{method:"PUT",body:request})}async function updateSegment(client,projectId,segmentIdOrSlug,request){let url=getSegmentUrl(projectId,segmentIdOrSlug);return output_manager_default.debug(`Updating feature flag segment ${segmentIdOrSlug} for project ${projectId}`),client.fetch(url,{method:"PATCH",body:request})}async function deleteSegment(client,projectId,segmentIdOrSlug){let url=getSegmentUrl(projectId,segmentIdOrSlug);output_manager_default.debug(`Deleting feature flag segment ${segmentIdOrSlug} for project ${projectId}`),await client.fetch(url,{method:"DELETE"})}async function segmentsLs(client,argv){let telemetryClient=new FlagsSegmentsLsTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(segmentsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{flags}=parsedArgs,json=flags["--json"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagJson(json);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name),lsStamp=stamp_default();output_manager_default.spinner(`Fetching feature flag segments for ${projectSlugLink}`);try{let segments2=await getSegments(client,project.id,!0);output_manager_default.stopSpinner();let sortedSegments=segments2.sort((a,b)=>b.updatedAt-a.updatedAt);json?outputJson5(client,sortedSegments):segments2.length===0?(output_manager_default.log(`No feature flag segments found for ${projectSlugLink} ${import_chalk72.default.gray(lsStamp())}`),output_manager_default.log(`
|
|
297
297
|
Create one with: ${getCommandName('flags segments create beta-users --label "Beta users" --add include:user.id=user_123')}`)):(output_manager_default.log(`${(0,import_pluralize4.default)("feature flag segment",segments2.length,!0)} found for ${projectSlugLink} ${import_chalk72.default.gray(lsStamp())}`),printSegmentsTable(sortedSegments))}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function outputJson5(client,segments2){let jsonOutput={segments:segments2.map(segment=>({id:segment.id,slug:segment.slug,label:segment.label,description:segment.description??null,data:segment.data,hint:segment.hint,usedByFlags:segment.usedByFlags??[],usedBySegments:segment.usedBySegments??[],createdAt:segment.createdAt,updatedAt:segment.updatedAt}))};client.stdout.write(`${JSON.stringify(jsonOutput,null,2)}
|
|
298
298
|
`)}function printSegmentsTable(segments2){let headers=["Slug","Label","Rules","Values","Used By","Updated"],now=Date.now(),rows=segments2.map(segment=>[import_chalk72.default.bold(segment.slug),segment.label,String(segment.data.rules?.length??0),String(countSegmentValues(segment)),String((segment.usedByFlags?.length??0)+(segment.usedBySegments?.length??0)),(0,import_ms6.default)(now-segment.updatedAt)+" ago"]),table2=formatTable(headers,["l","l","r","r","r","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
299
299
|
${table2}
|
|
@@ -320,9 +320,9 @@ Feature flag segment ${import_chalk73.default.bold(segment.slug)} for ${projectS
|
|
|
320
320
|
`)}}function getMembershipEntries(map){return Object.entries(map).flatMap(([entity,attributes])=>Object.entries(attributes).flatMap(([attribute,values])=>values.map(value=>({entity,attribute,value:value.value,note:value.note}))))}function formatOutcome2(outcome){return outcome.type==="all"?"match all conditions":`match ${outcome.passPromille/10}% by ${outcome.base.kind}.${outcome.base.attribute}`}function formatCondition(condition,settings){let lhs=condition.lhs.type==="entity"?`${condition.lhs.kind}.${condition.lhs.attribute}`:"segment",attributeType=condition.lhs.type==="entity"?getFlagAttributeType(settings,condition.lhs.kind,condition.lhs.attribute):void 0,rhs=condition.rhs===void 0?"":` ${formatValue(condition.rhs,attributeType)}`;return`${lhs} ${formatFlagConditionComparator(condition.cmp,{attributeType})}${rhs}`}function formatValue(value,attributeType){let timestampRhs=formatTimestampRhs(value,attributeType);return timestampRhs||(typeof value!="object"||value===null?JSON.stringify(value):value.type==="list"||value.type==="list/inline"?value.items.map(item=>JSON.stringify(item.value)).join(", "):value.type==="regex"?`/${value.pattern}/${value.flags}`:JSON.stringify(value))}async function segmentsInspect(client,argv){let telemetryClient=new FlagsSegmentsInspectTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(segmentsInspectSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[segmentArg]=args,json=flags["--json"],projectName=getProjectNameFromFlags(flags);if(!segmentArg)return output_manager_default.error("Please provide a segment slug or ID to inspect"),output_manager_default.log(`Example: ${getCommandName("flags segments inspect beta-users")}`),2;telemetryClient.trackCliArgumentSegment(segmentArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagJson(json);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1;client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name);try{output_manager_default.spinner("Fetching segment...");let[segment,settings]=await Promise.all([getSegment(client,project.id,segmentArg,!0),getFlagSettings(client,project.id)]);output_manager_default.stopSpinner(),json?client.stdout.write(`${JSON.stringify({segment},null,2)}
|
|
321
321
|
`):printSegmentDetails({segment,projectSlugLink,settings})}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk74=__toESM(require_source(),1);var import_fast_deep_equal7=__toESM(require_fast_deep_equal(),1);import{randomBytes as randomBytes2}from"node:crypto";function parseEntityAttributeSelector(input){let trimmed=input.trim(),separatorIndex=trimmed.indexOf(".");if(separatorIndex<=0||separatorIndex===trimmed.length-1)throw new Error(`Invalid entity attribute "${input}". Use ENTITY.ATTRIBUTE, for example user.signupAt.`);return{kind:trimmed.slice(0,separatorIndex),attribute:trimmed.slice(separatorIndex+1)}}var OPERATOR_ALIASES={"=":"eq","==":"eq",eq:"eq",equals:"eq",equal:"eq","does-not-equal":"!eq","not-equals":"!eq","not-equal":"!eq","!=":"!eq","!eq":"!eq",in:"oneOf",oneof:"oneOf","one-of":"oneOf",oneOf:"oneOf","not-in":"!oneOf","not-one-of":"!oneOf","!oneof":"!oneOf","!oneOf":"!oneOf",containsallof:"containsAllOf","contains-all-of":"containsAllOf",containsAllOf:"containsAllOf",containsanyof:"containsAnyOf","contains-any-of":"containsAnyOf",containsAnyOf:"containsAnyOf",containsnoneof:"containsNoneOf","contains-none-of":"containsNoneOf",containsNoneOf:"containsNoneOf",startswith:"startsWith","starts-with":"startsWith",startsWith:"startsWith",endswith:"endsWith","ends-with":"endsWith",endsWith:"endsWith",contains:"contains","!contains":"!contains","does-not-contain":"!contains",notcontains:"!contains","not-contains":"!contains",notContains:"!contains",exists:"ex",ex:"ex","!exists":"!ex","not-exists":"!ex","!ex":"!ex",gt:"gt",">":"gt",after:"gt",gte:"gte",">=":"gte","at-or-after":"gte","on-or-after":"gte",lt:"lt","<":"lt",before:"lt",lte:"lte","<=":"lte","at-or-before":"lte","on-or-before":"lte"},LIST_OPERATORS=new Set(FLAG_CONDITION_LIST_COMPARATORS),RHS_OPTIONAL_OPERATORS=new Set(FLAG_CONDITION_RHS_OPTIONAL_COMPARATORS);function shortId(prefix){let alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",bytes=randomBytes2(12),id=prefix;for(let i=0;i<bytes.length;i++)id+=alphabet[bytes[i]%alphabet.length];return id}function parseSegmentDataInput(input){let value=parseJson(input,"segment data");if(!isRecord(value))throw new Error("Segment data must be a JSON object");return value}function parseSegmentRuleInput(input,outcome={type:"all"}){let trimmed=input.trim();if(!trimmed)throw new Error("Segment rule cannot be empty");if(trimmed.startsWith("{")){let value=parseJson(trimmed,"segment rule");if(!isRecord(value))throw new Error("Segment rule JSON must be an object");return value}let conditions=trimmed.split(";").map(part=>part.trim()).filter(Boolean).map(parseSegmentConditionInput);if(conditions.length===0)throw new Error("Segment rule must include at least one condition");return{id:shortId("rule_"),conditions,outcome}}function parseSegmentConditionInput(input){let[field,operator,...valueParts]=input.split(":");if(!field||!operator)throw new Error(`Invalid segment rule "${input}". Use ENTITY.ATTRIBUTE:OPERATOR:VALUE, for example user.email:ends-with:@vercel.com.`);let lhs=parseEntityAttribute(field),cmp=parseComparator(operator),rawValue=valueParts.join(":");if(!rawValue&&!RHS_OPTIONAL_OPERATORS.has(cmp))throw new Error(`Segment rule "${input}" is missing a value`);return{lhs,cmp,...rawValue?{rhs:parseConditionValue(rawValue,cmp)}:{}}}function parseSegmentValueInput(input){let separatorIndex=input.indexOf("=");if(separatorIndex===-1)throw new Error(`Invalid segment value "${input}". Use ENTITY.ATTRIBUTE=VALUE.`);let lhs=input.slice(0,separatorIndex).trim(),rawValue=input.slice(separatorIndex+1).trim();if(!rawValue)throw new Error(`Invalid segment value "${input}". Value cannot be empty.`);let{kind:entity,attribute}=parseEntityAttribute(lhs),{value,note}=splitValueNote(rawValue);return{entity,attribute,value:note?{value,note}:{value}}}function addSegmentValue(data,field,input){let{entity,attribute,value}=parseSegmentValueInput(input),map=data[field]??{},entityValues=map[entity]??{},values=entityValues[attribute]??[];entityValues[attribute]=values.concat(value),map[entity]=entityValues,data[field]=map}function buildSegmentOperations(field,action,inputs){return inputs.map(input=>{let{entity,attribute,value}=parseSegmentValueInput(input);return{action,field,entity,attribute,value}})}function buildSegmentRuleOperations(action,inputs){return inputs.map(input=>buildSegmentRuleOperation(action,input))}function buildSegmentTargetOperations(action,inputs){return inputs.map(input=>parseSegmentTargetOperation(action,input))}function applySegmentOperations(data,operations){let next=normalizeSegmentData({rules:structuredClone(data.rules??[]),include:structuredClone(data.include??{}),exclude:structuredClone(data.exclude??{})});for(let operation of operations){if(operation.field==="rule"){if(operation.action==="add")next.rules=(next.rules??[]).concat(structuredClone(operation.rule));else if(operation.ruleId){let rules2=next.rules??[];if(!rules2.some(rule=>rule.id===operation.ruleId))throw new Error(`Segment rule "${operation.ruleId}" does not exist.`);next.rules=rules2.filter(rule=>rule.id!==operation.ruleId)}else if(operation.rule){let ruleToRemove=operation.rule,rules2=next.rules??[];if(!rules2.some(rule=>segmentRulesEqual(rule,ruleToRemove)))throw new Error("Segment rule does not exist.");next.rules=rules2.filter(rule=>!segmentRulesEqual(rule,ruleToRemove))}continue}if(operation.action==="add"){let map2=next[operation.field]??{},entityValues2=map2[operation.entity]??{},values2=entityValues2[operation.attribute]??[];entityValues2[operation.attribute]=values2.concat(operation.value),map2[operation.entity]=entityValues2,next[operation.field]=map2;continue}let entityValues=next[operation.field]?.[operation.entity],values=entityValues?.[operation.attribute],valueExists=values?.some(value=>value.value===operation.value.value);if(!values||!valueExists)throw new Error(`Segment ${operation.field} value "${operation.entity}.${operation.attribute}=${operation.value.value}" does not exist.`);entityValues[operation.attribute]=values.filter(value=>value.value!==operation.value.value)}return next}function parseSegmentTargetOperation(action,input){let separatorIndex=input.indexOf(":");if(separatorIndex===-1)throw new Error(`Invalid segment operation "${input}". Use include:ENTITY.ATTRIBUTE=VALUE, exclude:ENTITY.ATTRIBUTE=VALUE, or rule:ENTITY.ATTRIBUTE:OPERATOR:VALUE.`);let field=input.slice(0,separatorIndex).trim().toLowerCase(),valueInput=input.slice(separatorIndex+1).trim();if(!valueInput)throw new Error(`Invalid segment operation "${input}". Target is empty.`);if(field==="include"||field==="exclude"){let{entity,attribute,value}=parseSegmentValueInput(valueInput);return{action,field,entity,attribute,value}}if(field==="rule"||field==="rules")return buildSegmentRuleOperation(action,valueInput);throw new Error(`Invalid segment operation target "${field}". Use include, exclude, or rule.`)}function buildSegmentRuleOperation(action,input){if(action==="remove"&&isRuleIdInput(input))return{action,field:"rule",ruleId:input.trim()};let rule=parseSegmentRuleInput(input);return action==="add"?{action,field:"rule",rule}:{action,field:"rule",rule}}function normalizeSegmentData(data){return{rules:data.rules??[],include:data.include??{},exclude:data.exclude??{}}}function segmentRulesEqual(a,b){return(0,import_fast_deep_equal7.default)(getComparableRule(a),getComparableRule(b))}function getComparableRule(rule){return{conditions:rule.conditions,outcome:rule.outcome}}function isRuleIdInput(input){let trimmed=input.trim();return!trimmed.startsWith("{")&&!trimmed.includes(":")&&!trimmed.includes(".")}function parseComparator(input,ruleLabel="segment rule"){let normalized=input.trim(),lowercase=normalized.toLowerCase(),comparator=OPERATOR_ALIASES[normalized]??OPERATOR_ALIASES[lowercase];if(!comparator)throw new Error(`Invalid ${ruleLabel} operator "${input}". Valid operators: ${formatFlagConditionComparatorList()}.`);return comparator}function parseEntityAttribute(input){let{kind,attribute}=parseEntityAttributeSelector(input);return{type:"entity",kind,attribute}}function parseConditionValue(input,comparator){let trimmed=input.trim();return LIST_OPERATORS.has(comparator)?{type:"list",items:trimmed.split(",").map(value=>value.trim()).filter(Boolean).map(value=>({value:parseListItemValue(value)}))}:parseScalarValue(trimmed)}function parseScalarValue(value){return value==="true"?!0:value==="false"?!1:value!==""&&Number.isFinite(Number(value))?Number(value):value}function parseListItemValue(value){return value!==""&&Number.isFinite(Number(value))?Number(value):value}function splitValueNote(input){let separatorIndex=input.indexOf("|");if(separatorIndex===-1)return{value:input};let value=input.slice(0,separatorIndex).trim(),note=input.slice(separatorIndex+1).trim();return note?{value,note}:{value}}function parseJson(input,label){try{return JSON.parse(input)}catch{throw new Error(`Invalid JSON for ${label}`)}}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}async function segmentsCreate(client,argv){let telemetryClient=new FlagsSegmentsCreateTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(segmentsCreateSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[slug]=args,label=flags["--label"],description=flags["--description"],hint=flags["--hint"],dataInput=flags["--data"],addInputs=flags["--add"]??[],json=flags["--json"],projectName=getProjectNameFromFlags(flags);if(telemetryClient.trackCliArgumentSlug(slug),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionLabel(label),telemetryClient.trackCliOptionDescription(description),telemetryClient.trackCliOptionHint(hint),telemetryClient.trackCliOptionData(dataInput),telemetryClient.trackCliOptionAdd(addInputs),telemetryClient.trackCliFlagJson(json),!slug)return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide a segment slug to create.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags segments create <slug> --label <label> --add include:user.id=<value>"),when:"create a segment with explicit values"}]},2),2):(output_manager_default.error("Please provide a slug for the segment"),output_manager_default.log(`Example: ${getCommandName('flags segments create beta-users --label "Beta users" --add include:user.id=user_123')}`),2);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. Run link first.",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"link the project"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name);label=await resolveSegmentLabel(client,label,slug),hint=await resolveSegmentHint(client,hint,description,label);let data,settings;try{settings=await getFlagSettings(client,project.id),data=coerceTimestampSegmentData(await collectSegmentData(client,{dataInput,addInputs}),settings,"input")}catch(err){return output_manager_default.error(err.message),1}let request={slug,label,description,data,hint};try{output_manager_default.spinner("Creating segment...");let segment=await createSegment(client,project.id,request);if(output_manager_default.stopSpinner(),json)return client.stdout.write(`${JSON.stringify({segment},null,2)}
|
|
322
322
|
`),0;output_manager_default.success(`Feature flag segment ${import_chalk74.default.bold(segment.slug)} created`),printSegmentDetails({segment,projectSlugLink,showTimestamps:!1,settings})}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveSegmentLabel(client,label,slug){let defaultLabel=humanizeSlug(slug);return label||client.stdin.isTTY&&!client.nonInteractive&&(await client.input.text({message:`Enter a label for this segment (press Enter for "${defaultLabel}"):`})).trim()||defaultLabel}async function resolveSegmentHint(client,hint,description,label){return hint||(client.stdin.isTTY&&!client.nonInteractive?(await client.input.text({message:`Enter a hint for who belongs in this segment (press Enter for "${description||label}"):`})).trim()||description||label:description||label)}async function collectSegmentData(client,input){let hasExplicitData=!!input.dataInput,data=hasExplicitData?parseSegmentDataInput(input.dataInput):normalizeSegmentData({}),operations=buildSegmentTargetOperations("add",input.addInputs),nextData=operations.length>0?applySegmentOperations(data,operations):data;return!hasExplicitData&&input.addInputs.length===0&&client.stdin.isTTY&&!client.nonInteractive&&await collectSegmentDataInteractively(client,nextData),normalizeSegmentData(nextData)}async function collectSegmentDataInteractively(client,data){let addAnother=await client.input.confirm("Add segment criteria now?",!0);for(;addAnother;){let kind=await client.input.select({message:"What do you want to add?",choices:[{name:"Include an exact entity value",value:"include"},{name:"Exclude an exact entity value",value:"exclude"},{name:"Add a rule",value:"rule"}]});if(kind==="rule"){let rule=await client.input.text({message:"Enter rule as ENTITY.ATTRIBUTE:OPERATOR:VALUE (for example user.email:ends-with:@vercel.com):"});data.rules=(data.rules??[]).concat(parseSegmentRuleInput(rule))}else{let value=await client.input.text({message:`Enter ${kind} value as ENTITY.ATTRIBUTE=VALUE:`});addSegmentValue(data,kind,value)}addAnother=await client.input.confirm("Add another criterion?",!1)}}function humanizeSlug(slug){return slug.split(/[-_\s]+/).filter(Boolean).map(word=>word.charAt(0).toUpperCase()+word.slice(1)).join(" ")}var import_chalk75=__toESM(require_source(),1);async function segmentsUpdate(client,argv){let telemetryClient=new FlagsSegmentsUpdateTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(segmentsUpdateSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,segmentArg=args[0],label=flags["--label"],description=flags["--description"],hint=flags["--hint"],dataInput=flags["--data"],addInputs=flags["--add"]??[],removeInputs=flags["--remove"]??[],json=flags["--json"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentSegment(segmentArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionLabel(label),telemetryClient.trackCliOptionDescription(description),telemetryClient.trackCliOptionHint(hint),telemetryClient.trackCliOptionData(dataInput),telemetryClient.trackCliOptionAdd(addInputs),telemetryClient.trackCliOptionRemove(removeInputs),telemetryClient.trackCliFlagJson(json);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. Run link first.",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"link the project"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project,org}=link,projectSlugLink=formatProject(org.slug,project.name);try{if(!segmentArg&&(segmentArg=await resolveSegmentArg(client,project.id),!segmentArg))return 1;let settings=await getFlagSettings(client,project.id),operations=coerceTimestampOperations(buildOperations({addInputs,removeInputs}),settings),hasChanges=label!==void 0||description!==void 0||hint!==void 0||!!dataInput||operations.length>0,request;if(!hasChanges&&client.stdin.isTTY&&!client.nonInteractive){output_manager_default.spinner("Fetching segment...");let segment2=await getSegment(client,project.id,segmentArg,!0);output_manager_default.stopSpinner(),request=await collectUpdateInteractively(client,segment2,settings)}else request=await buildUpdateRequest(client,project.id,segmentArg,{label,description,hint,dataInput,operations,settings});if(request=coerceTimestampUpdateRequest(request,settings),!hasUpdateRequestChanges(request))return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide at least one segment update option, such as --label, --data, --add, or --remove.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags segments update <segment> --add include:user.id=<value>"),when:"add a value to a segment"},{command:buildCommandWithGlobalFlags(client.argv,"flags segments update <segment> --remove include:user.id=<value>"),when:"remove a value from a segment"},{command:buildCommandWithGlobalFlags(client.argv,"flags segments inspect <segment> --json"),when:"inspect the current segment data first"}]},2),2):(output_manager_default.warn("No segment changes were provided"),0);output_manager_default.spinner("Updating segment...");let segment=await updateSegment(client,project.id,segmentArg,request);if(output_manager_default.stopSpinner(),json)return client.stdout.write(`${JSON.stringify({segment},null,2)}
|
|
323
|
-
`),0;output_manager_default.success(`Feature flag segment ${import_chalk75.default.bold(segment.slug)} updated`),printSegmentDetails({segment,projectSlugLink,showTimestamps:!1,settings})}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveSegmentArg(client,projectId){if(client.nonInteractive){outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide a segment slug or ID. Run `vercel flags segments ls` to list segments.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags segments update <segment> --add include:user.id=<value>"),when:"update a segment by slug or ID"},{command:buildCommandWithGlobalFlags(client.argv,"flags segments ls"),when:"list segments to find the slug or ID"}]},2);return}if(!client.stdin.isTTY){output_manager_default.error("Please provide a segment slug or ID to update"),output_manager_default.log(`Example: ${getCommandName("flags segments update beta-users --add include:user.id=user_123")}`);return}output_manager_default.spinner("Fetching segments...");let segments2=await getSegments(client,projectId,!0);if(output_manager_default.stopSpinner(),segments2.length===0){output_manager_default.error("No feature flag segments found"),output_manager_default.log(`Create one with: ${getCommandName('flags segments create beta-users --label "Beta users" --add include:user.id=user_123')}`);return}return client.input.select({message:"Select a segment to update:",choices:segments2.map(segment=>({name:`${segment.label} (${segment.slug})`,value:segment.slug}))})}async function buildUpdateRequest(client,projectId,segmentArg,input){let request={};if(input.label!==void 0&&(request.label=input.label),input.description!==void 0&&(request.description=input.description),input.hint!==void 0&&(request.hint=input.hint),input.dataInput&&(request.data=coerceTimestampSegmentData(parseSegmentDataInput(input.dataInput),input.settings,"input")),request.data)request.data=applySegmentOperations(request.data,input.operations);else if(hasRuleOperations(input.operations)){output_manager_default.spinner("Fetching segment...");let segment=await getSegment(client,projectId,segmentArg,!0);output_manager_default.stopSpinner(),request.data=applySegmentOperations(segment.data,input.operations)}else if(input.operations.length>0){if(hasRemoveOperations(input.operations)){output_manager_default.spinner("Fetching segment...");let segment=await getSegment(client,projectId,segmentArg,!0);output_manager_default.stopSpinner(),applySegmentOperations(segment.data,input.operations)}request.operations=input.operations.filter(isMembershipOperation)}return request}function buildOperations(input){return[...buildSegmentTargetOperations("add",input.addInputs),...buildSegmentTargetOperations("remove",input.removeInputs)]}function hasRuleOperations(operations){return operations.some(operation=>operation.field==="rule")}function hasRemoveOperations(operations){return operations.some(operation=>operation.action==="remove")}function isMembershipOperation(operation){return operation.field==="include"||operation.field==="exclude"}async function collectUpdateInteractively(client,segment,settings){let request={},data,replacingRules=!1,operations=[],keepEditing=!0;for(;keepEditing;){let action=await client.input.select({message:"What do you want to update?",choices:[{name:"Label",value:"label"},{name:"Description",value:"description"},{name:"Hint",value:"hint"},{name:"Add rule",value:"add-rule"},{name:"Remove rule",value:"remove-rule"},{name:"Replace all rules",value:"replace-rules"},{name:"Add include value",value:"include"},{name:"Add exclude value",value:"exclude"},{name:"Remove include value",value:"remove-include"},{name:"Remove exclude value",value:"remove-exclude"},{name:"Replace full data JSON",value:"data"},{name:"Done",value:"done"}]});switch(action){case"label":request.label=await client.input.text({message:`Enter a new label (current: ${segment.label}):`});break;case"description":request.description=await client.input.text({message:"Enter a new description:"});break;case"hint":request.hint=await client.input.text({message:`Enter a new hint (current: ${segment.hint}):`});break;case"add-rule":{let rule=await client.input.text({message:"Enter rule as ENTITY.ATTRIBUTE:OPERATOR:VALUE:"});operations.push(...buildSegmentRuleOperations("add",[rule]));break}case"remove-rule":{let rule=await client.input.text({message:"Enter rule as ENTITY.ATTRIBUTE:OPERATOR:VALUE or rule ID:"});operations.push(...buildSegmentRuleOperations("remove",[rule]));break}case"replace-rules":{let rule=await client.input.text({message:"Enter rule as ENTITY.ATTRIBUTE:OPERATOR:VALUE (repeat by choosing this again):"});replacingRules||(data=normalizeSegmentData({...segment.data,rules:[]}),replacingRules=!0),data=normalizeSegmentData(data??segment.data);let[coercedRule]=coerceTimestampSegmentData({rules:[parseSegmentRuleInput(rule)]},settings,"input").rules;data.rules=(data.rules??[]).concat(coercedRule);break}case"include":case"exclude":case"remove-include":case"remove-exclude":{let value=await client.input.text({message:"Enter value as ENTITY.ATTRIBUTE=VALUE:"});operations.push(...buildSegmentOperations(action.includes("include")?"include":"exclude",action.startsWith("remove")?"remove":"add",[value]));break}case"data":{let value=await client.input.text({message:"Enter full segment data JSON:"});data=coerceTimestampSegmentData(parseSegmentDataInput(value),settings,"input");break}case"done":keepEditing=!1;break}keepEditing&&(keepEditing=await client.input.confirm("Make another change?",!1))}let coercedOperations=coerceTimestampOperations(operations,settings,"input");return data?request.data=applySegmentOperations(data,coercedOperations):hasRuleOperations(coercedOperations)?request.data=applySegmentOperations(segment.data,coercedOperations):coercedOperations.length>0&&(request.operations=coercedOperations.filter(isMembershipOperation)),request}function hasUpdateRequestChanges(request){return request.label!==void 0||request.description!==void 0||request.hint!==void 0||request.data!==void 0||!!request.operations?.length}function coerceTimestampUpdateRequest(request,settings){return request.data?{...request,data:coerceTimestampSegmentData(request.data,settings)}:request}var import_chalk76=__toESM(require_source(),1);async function segmentsRm(client,argv){let telemetryClient=new FlagsSegmentsRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(segmentsRemoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,segmentArg=args[0],skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentSegment(segmentArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. Run link first.",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"link the project"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{if(!segmentArg&&(segmentArg=await resolveSegmentArg2(client,project.id),!segmentArg))return 1;output_manager_default.spinner("Fetching segment...");let segment=await getSegment(client,project.id,segmentArg,!1);if(output_manager_default.stopSpinner(),!skipConfirmation){if(!client.stdin.isTTY)return output_manager_default.error("Missing required
|
|
323
|
+
`),0;output_manager_default.success(`Feature flag segment ${import_chalk75.default.bold(segment.slug)} updated`),printSegmentDetails({segment,projectSlugLink,showTimestamps:!1,settings})}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}async function resolveSegmentArg(client,projectId){if(client.nonInteractive){outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide a segment slug or ID. Run `vercel flags segments ls` to list segments.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags segments update <segment> --add include:user.id=<value>"),when:"update a segment by slug or ID"},{command:buildCommandWithGlobalFlags(client.argv,"flags segments ls"),when:"list segments to find the slug or ID"}]},2);return}if(!client.stdin.isTTY){output_manager_default.error("Please provide a segment slug or ID to update"),output_manager_default.log(`Example: ${getCommandName("flags segments update beta-users --add include:user.id=user_123")}`);return}output_manager_default.spinner("Fetching segments...");let segments2=await getSegments(client,projectId,!0);if(output_manager_default.stopSpinner(),segments2.length===0){output_manager_default.error("No feature flag segments found"),output_manager_default.log(`Create one with: ${getCommandName('flags segments create beta-users --label "Beta users" --add include:user.id=user_123')}`);return}return client.input.select({message:"Select a segment to update:",choices:segments2.map(segment=>({name:`${segment.label} (${segment.slug})`,value:segment.slug}))})}async function buildUpdateRequest(client,projectId,segmentArg,input){let request={};if(input.label!==void 0&&(request.label=input.label),input.description!==void 0&&(request.description=input.description),input.hint!==void 0&&(request.hint=input.hint),input.dataInput&&(request.data=coerceTimestampSegmentData(parseSegmentDataInput(input.dataInput),input.settings,"input")),request.data)request.data=applySegmentOperations(request.data,input.operations);else if(hasRuleOperations(input.operations)){output_manager_default.spinner("Fetching segment...");let segment=await getSegment(client,projectId,segmentArg,!0);output_manager_default.stopSpinner(),request.data=applySegmentOperations(segment.data,input.operations)}else if(input.operations.length>0){if(hasRemoveOperations(input.operations)){output_manager_default.spinner("Fetching segment...");let segment=await getSegment(client,projectId,segmentArg,!0);output_manager_default.stopSpinner(),applySegmentOperations(segment.data,input.operations)}request.operations=input.operations.filter(isMembershipOperation)}return request}function buildOperations(input){return[...buildSegmentTargetOperations("add",input.addInputs),...buildSegmentTargetOperations("remove",input.removeInputs)]}function hasRuleOperations(operations){return operations.some(operation=>operation.field==="rule")}function hasRemoveOperations(operations){return operations.some(operation=>operation.action==="remove")}function isMembershipOperation(operation){return operation.field==="include"||operation.field==="exclude"}async function collectUpdateInteractively(client,segment,settings){let request={},data,replacingRules=!1,operations=[],keepEditing=!0;for(;keepEditing;){let action=await client.input.select({message:"What do you want to update?",choices:[{name:"Label",value:"label"},{name:"Description",value:"description"},{name:"Hint",value:"hint"},{name:"Add rule",value:"add-rule"},{name:"Remove rule",value:"remove-rule"},{name:"Replace all rules",value:"replace-rules"},{name:"Add include value",value:"include"},{name:"Add exclude value",value:"exclude"},{name:"Remove include value",value:"remove-include"},{name:"Remove exclude value",value:"remove-exclude"},{name:"Replace full data JSON",value:"data"},{name:"Done",value:"done"}]});switch(action){case"label":request.label=await client.input.text({message:`Enter a new label (current: ${segment.label}):`});break;case"description":request.description=await client.input.text({message:"Enter a new description:"});break;case"hint":request.hint=await client.input.text({message:`Enter a new hint (current: ${segment.hint}):`});break;case"add-rule":{let rule=await client.input.text({message:"Enter rule as ENTITY.ATTRIBUTE:OPERATOR:VALUE:"});operations.push(...buildSegmentRuleOperations("add",[rule]));break}case"remove-rule":{let rule=await client.input.text({message:"Enter rule as ENTITY.ATTRIBUTE:OPERATOR:VALUE or rule ID:"});operations.push(...buildSegmentRuleOperations("remove",[rule]));break}case"replace-rules":{let rule=await client.input.text({message:"Enter rule as ENTITY.ATTRIBUTE:OPERATOR:VALUE (repeat by choosing this again):"});replacingRules||(data=normalizeSegmentData({...segment.data,rules:[]}),replacingRules=!0),data=normalizeSegmentData(data??segment.data);let[coercedRule]=coerceTimestampSegmentData({rules:[parseSegmentRuleInput(rule)]},settings,"input").rules;data.rules=(data.rules??[]).concat(coercedRule);break}case"include":case"exclude":case"remove-include":case"remove-exclude":{let value=await client.input.text({message:"Enter value as ENTITY.ATTRIBUTE=VALUE:"});operations.push(...buildSegmentOperations(action.includes("include")?"include":"exclude",action.startsWith("remove")?"remove":"add",[value]));break}case"data":{let value=await client.input.text({message:"Enter full segment data JSON:"});data=coerceTimestampSegmentData(parseSegmentDataInput(value),settings,"input");break}case"done":keepEditing=!1;break}keepEditing&&(keepEditing=await client.input.confirm("Make another change?",!1))}let coercedOperations=coerceTimestampOperations(operations,settings,"input");return data?request.data=applySegmentOperations(data,coercedOperations):hasRuleOperations(coercedOperations)?request.data=applySegmentOperations(segment.data,coercedOperations):coercedOperations.length>0&&(request.operations=coercedOperations.filter(isMembershipOperation)),request}function hasUpdateRequestChanges(request){return request.label!==void 0||request.description!==void 0||request.hint!==void 0||request.data!==void 0||!!request.operations?.length}function coerceTimestampUpdateRequest(request,settings){return request.data?{...request,data:coerceTimestampSegmentData(request.data,settings)}:request}var import_chalk76=__toESM(require_source(),1);async function segmentsRm(client,argv){let telemetryClient=new FlagsSegmentsRmTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(segmentsRemoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,segmentArg=args[0],skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);telemetryClient.trackCliArgumentSegment(segmentArg),telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliFlagYes(skipConfirmation);let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return client.nonInteractive?(outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. Run link first.",next:[{command:buildCommandWithGlobalFlags(client.argv,"link"),when:"link the project"}]},1),1):(output_manager_default.error(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),1);client.config.currentTeam=link.org.type==="team"?link.org.id:void 0;let{project}=link;try{if(!segmentArg&&(segmentArg=await resolveSegmentArg2(client,project.id),!segmentArg))return 1;output_manager_default.spinner("Fetching segment...");let segment=await getSegment(client,project.id,segmentArg,!1);if(output_manager_default.stopSpinner(),!skipConfirmation){if(!client.stdin.isTTY)return output_manager_default.error("Missing required option --yes. Use --yes to skip the confirmation prompt in non-interactive mode."),2;if(client.nonInteractive)return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`Confirm deletion of segment ${segment.slug} by adding --yes.`,next:[{command:buildCommandWithGlobalFlags(client.argv,`flags segments delete ${segmentArg} --yes`),when:"confirm and delete the segment"}]},1),1;if(!await client.input.confirm(`Are you sure you want to delete segment ${import_chalk76.default.bold(segment.slug)}?`,!1))return output_manager_default.log("Aborted"),0}output_manager_default.spinner("Deleting segment..."),await deleteSegment(client,project.id,segmentArg),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag segment ${import_chalk76.default.bold(segment.slug)} deleted`)}catch(err){return output_manager_default.stopSpinner(),handleSegmentInUseError(client,err,segmentArg)||printError(err),1}return 0}function handleSegmentInUseError(client,error,segmentArg){if(!isAPIError(error)||error.code!=="SEGMENT_IN_USE")return!1;let usedBy=error.usedBy,flags=usedBy?.flags??[],segments2=usedBy?.segments??[],segment=segmentArg??"<segment>",formatReferences=references=>references.map(reference=>{let primary=reference.name??reference.label??reference.slug??reference.id;return primary&&reference.slug&&reference.slug!==primary?`${primary} (${reference.slug})`:primary??"Unknown reference"}).join(", "),firstFlag=flags.find(reference=>reference.slug||reference.id),firstSegment=segments2.find(reference=>reference.slug||reference.id),inspectSubcommand2=firstFlag!==void 0?`flags inspect ${firstFlag.slug??firstFlag.id}`:firstSegment!==void 0?`flags segments inspect ${firstSegment.slug??firstSegment.id}`:void 0,lines=[`Segment ${segment} is still in use and can't be deleted.`];flags.length>0&&lines.push(`Used by feature flags: ${formatReferences(flags)}`),segments2.length>0&&lines.push(`Used by segments: ${formatReferences(segments2)}`);let message=lines.join(`
|
|
324
324
|
`);return outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.SEGMENT_IN_USE,message,next:[...inspectSubcommand2?[{command:buildCommandWithGlobalFlags(client.argv,inspectSubcommand2),when:"inspect one reference that still uses the segment"}]:[],{command:buildCommandWithGlobalFlags(client.argv,`flags segments delete ${segment} --yes`),when:"retry after removing all references"}]},1),inspectSubcommand2?lines.push("",`Run ${getCommandName(inspectSubcommand2)} to inspect one reference, remove the segment from each rule, then try deleting the segment again.`):lines.push("","Remove every flag or segment rule that references it, then try deleting the segment again."),output_manager_default.error(lines.join(`
|
|
325
|
-
`)),!0}async function resolveSegmentArg2(client,projectId){if(client.nonInteractive){outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide a segment slug or ID. Run `vercel flags segments ls` to list segments.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags segments delete <segment> --yes"),when:"delete a segment by slug or ID"},{command:buildCommandWithGlobalFlags(client.argv,"flags segments ls"),when:"list segments to find the slug or ID"}]},2);return}if(!client.stdin.isTTY){output_manager_default.error("Please provide a segment slug or ID to delete"),output_manager_default.log(`Example: ${getCommandName("flags segments delete beta-users")}`);return}output_manager_default.spinner("Fetching segments...");let segments2=await getSegments(client,projectId);if(output_manager_default.stopSpinner(),segments2.length===0){output_manager_default.log("No feature flag segments found");return}return client.input.select({message:"Select a segment to delete:",choices:segments2.map(segment=>({name:`${segment.label} (${segment.slug})`,value:segment.slug}))})}var COMMAND_CONFIG13={ls:getCommandAliases(segmentsListSubcommand),inspect:getCommandAliases(segmentsInspectSubcommand),create:getCommandAliases(segmentsCreateSubcommand),update:getCommandAliases(segmentsUpdateSubcommand),delete:getCommandAliases(segmentsRemoveSubcommand)};async function segments(client){let telemetry=new FlagsSegmentsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(segmentsSubcommand.options),
|
|
325
|
+
`)),!0}async function resolveSegmentArg2(client,projectId){if(client.nonInteractive){outputAgentError(client,{status:AGENT_STATUS.ERROR,reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Please provide a segment slug or ID. Run `vercel flags segments ls` to list segments.",next:[{command:buildCommandWithGlobalFlags(client.argv,"flags segments delete <segment> --yes"),when:"delete a segment by slug or ID"},{command:buildCommandWithGlobalFlags(client.argv,"flags segments ls"),when:"list segments to find the slug or ID"}]},2);return}if(!client.stdin.isTTY){output_manager_default.error("Please provide a segment slug or ID to delete"),output_manager_default.log(`Example: ${getCommandName("flags segments delete beta-users")}`);return}output_manager_default.spinner("Fetching segments...");let segments2=await getSegments(client,projectId);if(output_manager_default.stopSpinner(),segments2.length===0){output_manager_default.log("No feature flag segments found");return}return client.input.select({message:"Select a segment to delete:",choices:segments2.map(segment=>({name:`${segment.label} (${segment.slug})`,value:segment.slug}))})}var COMMAND_CONFIG13={ls:getCommandAliases(segmentsListSubcommand),inspect:getCommandAliases(segmentsInspectSubcommand),create:getCommandAliases(segmentsCreateSubcommand),update:getCommandAliases(segmentsUpdateSubcommand),delete:getCommandAliases(segmentsRemoveSubcommand)};async function segments(client){let telemetry=new FlagsSegmentsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(segmentsSubcommand.options),argv=client.argv.slice(4),parsedArgs;try{parsedArgs=parseArguments(argv,flagsSpecification,{permissive:!0,commandShorthands:findCommandShorthands(segmentsSubcommand.subcommands,argv)})}catch(err){return printError(err),2}let{subcommand,args,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG13),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags segments",subcommand),output_manager_default.print(help(segmentsSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:segmentsSubcommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags segments",subcommandOriginal),printHelp(segmentsListSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),segmentsLs(client,args));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("flags segments",subcommandOriginal),printHelp(segmentsInspectSubcommand),0):(telemetry.trackCliSubcommandInspect(subcommandOriginal),segmentsInspect(client,args));case"create":return needHelp?(telemetry.trackCliFlagHelp("flags segments",subcommandOriginal),printHelp(segmentsCreateSubcommand),0):(telemetry.trackCliSubcommandCreate(subcommandOriginal),subcommandOriginal==="add"&&warnDeprecatedSubcommand(client,"flags segments add","flags segments create"),segmentsCreate(client,args));case"update":return needHelp?(telemetry.trackCliFlagHelp("flags segments",subcommandOriginal),printHelp(segmentsUpdateSubcommand),0):(telemetry.trackCliSubcommandUpdate(subcommandOriginal),segmentsUpdate(client,args));case"delete":return needHelp?(telemetry.trackCliFlagHelp("flags segments",subcommandOriginal),printHelp(segmentsRemoveSubcommand),0):(telemetry.trackCliSubcommandDelete(subcommandOriginal),subcommandOriginal==="remove"&&warnDeprecatedSubcommand(client,"flags segments remove","flags segments delete"),segmentsRm(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG13)),output_manager_default.print(help(segmentsSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsEntitiesTelemetryClient=class extends TelemetryClient{trackSubcommand(subcommand,actual){this.trackCliSubcommand({subcommand,value:actual})}trackArguments(args,flags){args[0]&&this.trackCliArgument({arg:"kind",value:this.redactedValue}),this.trackCliOptionProject(flags["--project"]);for(let option of["label","attribute","add-attribute","remove-attribute","set-attribute-type"]){let value=flags[`--${option}`];(typeof value=="string"?value.trim():Array.isArray(value)&&value.length)&&this.trackCliOption({option,value:this.redactedValue})}for(let flag of["json","yes"])flags[`--${flag}`]&&this.trackCliFlag(flag)}};var import_chalk78=__toESM(require_source(),1),import_pluralize5=__toESM(require_pluralize(),1);var import_chalk77=__toESM(require_source(),1);async function loadEntityUsageSources(client,projectId){let[active,archived,segments2]=await Promise.all([getFlagsFromDatabase(client,projectId,"active"),getFlagsFromDatabase(client,projectId,"archived"),getSegments(client,projectId)]);return{flags:[...active,...archived],segments:segments2}}async function getFlagsFromDatabase(client,projectId,state){let flags=[],query=new URLSearchParams({state,limit:String(MAX_FLAGS_PAGE_LIMIT)}),cursor;do{let response=await client.fetch(`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/flags?${query}`);flags.push(...response.data),cursor=response.pagination?.next??null,cursor&&query.set("cursor",cursor)}while(cursor);return flags}function collectEntityUsage(sources,kind,attribute){let matches=reference=>reference.kind===kind&&(attribute===void 0||reference.attribute===attribute);return{flags:sources.flags.filter(flag=>flagReferences(flag).some(matches)).map(flag=>flag.slug),segments:sources.segments.filter(segment=>segmentReferences(segment).some(matches)).map(segment=>segment.slug)}}function hasEntityUsage(usage){return usage.flags.length>0||usage.segments.length>0}function flagReferences(flag){let references=Object.values(flag.environments).flatMap(environmentReferences);return flag.experiment&&references.push(flag.experiment.base),references}function environmentReferences(environment){let references=[];(environment.fallthrough.type==="split"||environment.fallthrough.type==="rollout")&&references.push(environment.fallthrough.base);for(let rule of environment.rules){for(let condition of rule.conditions)condition.lhs.type==="entity"&&references.push(condition.lhs);(rule.outcome.type==="split"||rule.outcome.type==="rollout")&&references.push(rule.outcome.base)}for(let targets2 of Object.values(environment.targets??{}))references.push(...membershipReferences(targets2));return references}function segmentReferences(segment){let references=[];for(let rule of segment.data.rules??[]){for(let condition of rule.conditions)condition.lhs.type==="entity"&&references.push(condition.lhs);rule.outcome.type==="split"&&references.push(rule.outcome.base)}return references.push(...membershipReferences(segment.data.include)),references.push(...membershipReferences(segment.data.exclude)),references}function membershipReferences(map){return map?Object.entries(map).flatMap(([kind,attributes])=>Object.entries(attributes).filter(([,values])=>values.length>0).map(([attribute])=>({kind,attribute}))):[]}async function resolveEntitiesProject(client,projectName){let link=await getLinkedFlagsProject(client,projectName);return link.status==="error"?{exitCode:link.exitCode}:link.status==="not_linked"?client.nonInteractive?(entityAgentError(client,{reason:AGENT_REASON.NOT_LINKED,message:"Your codebase is not linked to a project. Run link first.",next:[{command:"link",when:"link the project"}]}),{exitCode:1}):(output_manager_default.fatal(`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${getCommandName("link")} to link it.`),{exitCode:1}):(client.config.currentTeam=link.org.type==="team"?link.org.id:void 0,{project:link.project,org:link.org,projectSlugLink:formatProject(link.org.slug,link.project.name)})}function isExitCodeResult(result){return"exitCode"in result}function formatAttributeList(entity){return entity.attributes.length===0?import_chalk77.default.dim("-"):entity.attributes.map(attribute=>`${attribute.key}:${import_chalk77.default.dim(attribute.type)}`).join(", ")}function printEntityDetails(entity,projectSlugLink){output_manager_default.log(`
|
|
326
326
|
Feature flag entity ${import_chalk77.default.bold(entity.kind)} for ${projectSlugLink}
|
|
327
327
|
`),output_manager_default.print(` ${import_chalk77.default.dim("Kind:")} ${entity.kind}
|
|
328
328
|
`),output_manager_default.print(` ${import_chalk77.default.dim("Label:")} ${entity.label}
|
|
@@ -339,11 +339,11 @@ Create your first flag to set it up: ${cmd(buildCommandWithGlobalFlags(client.ar
|
|
|
339
339
|
${table2}
|
|
340
340
|
`)}var import_chalk79=__toESM(require_source(),1);var IDENTIFIER_PATTERN=/^[a-zA-Z0-9_-]+$/,MAX_ENTITIES=32,MAX_ATTRIBUTES=32,MAX_IDENTIFIER_LENGTH=128;function validateEntityKind(kind){if(!IDENTIFIER_PATTERN.test(kind)||kind.length>MAX_IDENTIFIER_LENGTH)throw new Error(`Invalid entity kind "${kind}". Use up to ${MAX_IDENTIFIER_LENGTH} letters, numbers, dashes, and underscores, for example user.`)}function validateEntityLabel(label){if(label.trim().length===0)throw new Error("Entity label can not be empty.");if(label.length>MAX_IDENTIFIER_LENGTH)throw new Error(`Entity label can not be longer than ${MAX_IDENTIFIER_LENGTH} characters.`)}function validateAttributeKey(key){if(!IDENTIFIER_PATTERN.test(key)||key.length>MAX_IDENTIFIER_LENGTH)throw new Error(`Invalid attribute key "${key}". Use up to ${MAX_IDENTIFIER_LENGTH} letters, numbers, dashes, and underscores, for example plan.`)}function parseAttributeType(type,key){if(!isFlagAttributeType(type))throw new Error(`Invalid type "${type}" for attribute "${key}". Valid types: ${formatFlagAttributeTypeList()}.`);return type}function parseAttributeInput(input){let parts=input.trim().split(":").map(part=>part.trim());if(parts.length!==2||!parts[0]||!parts[1])throw new Error(`Invalid attribute "${input}". Use KEY:TYPE, for example plan:string. Valid types: ${formatFlagAttributeTypeList()}.`);let[key,type]=parts;return validateAttributeKey(key),{key,type:parseAttributeType(type,key)}}function parseAttributeInputs(inputs){let attributes=inputs.map(parseAttributeInput),seen=new Set;for(let attribute of attributes){if(seen.has(attribute.key))throw new Error(`Attribute "${attribute.key}" is specified twice.`);seen.add(attribute.key)}return attributes}function defaultEntityLabel(kind){return kind.split(/[-_\s]+/).filter(Boolean).map(word=>word.charAt(0).toUpperCase()+word.slice(1)).join(" ")}function findEntity(entities2,kind){return entities2.find(entity=>entity.kind===kind)}function findAttribute(entity,key){return entity.attributes.find(attribute=>attribute.key===key)}function validateEntities(entities2){if(entities2.length>MAX_ENTITIES)throw new Error(`A project can have at most ${MAX_ENTITIES} entities. Remove one before adding another.`);let kinds=new Set,labels2=new Set;for(let entity of entities2){if(kinds.has(entity.kind))throw new Error(`Entity kind "${entity.kind}" already exists.`);if(labels2.has(entity.label.trim()))throw new Error(`Entity label "${entity.label}" is already used by another entity.`);if(kinds.add(entity.kind),labels2.add(entity.label.trim()),entity.attributes.length>MAX_ATTRIBUTES)throw new Error(`Entity "${entity.kind}" can have at most ${MAX_ATTRIBUTES} attributes.`);let keys=new Set;for(let attribute of entity.attributes){if(keys.has(attribute.key))throw new Error(`Attribute "${attribute.key}" already exists on entity "${entity.kind}".`);keys.add(attribute.key)}}}async function entitiesCreate(client,argv){let parsedArgs=parseEntityArguments(client,argv,entitiesCreateSubcommand.options),{args,flags}=parsedArgs,[kind]=args,label=flags["--label"]?.trim(),attributeInputs=flags["--attribute"]??[],json=flags["--json"],projectName=getProjectNameFromFlags(flags);if(!kind)return client.nonInteractive?(entityAgentError(client,{reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Provide an entity kind to create.",next:[{command:"flags entities create <kind> --label <label> --attribute <key>:<type>",when:"create an entity with explicit attributes"}]}),2):(output_manager_default.fatal("Provide a kind for the entity"),output_manager_default.log(`Example: ${getCommandName("flags entities create user --label User --attribute id:string")}`),2);let attributes;try{validateEntityKind(kind),label!==void 0&&validateEntityLabel(label),attributes=parseAttributeInputs(attributeInputs)}catch(err){return output_manager_default.fatal(err.message),2}let context=await resolveEntitiesProject(client,projectName);if(isExitCodeResult(context))return context.exitCode;let{project,projectSlugLink}=context;output_manager_default.spinner("Fetching feature flag settings\u2026");let settings=await getFlagSettings(client,project.id);if(output_manager_default.stopSpinner(),findEntity(settings.entities,kind))return output_manager_default.fatal(`Entity ${import_chalk79.default.bold(kind)} already exists. Run ${getCommandName(`flags entities update ${kind}`)} to change it.`),1;let willPrompt=client.stdin.isTTY&&!client.nonInteractive&&(label===void 0||attributes.length===0);willPrompt&&printAlignedLabel("Project",projectSlugLink),label=await resolveEntityLabel(client,label,kind),attributes.length===0&&client.stdin.isTTY&&!client.nonInteractive&&(attributes=await collectAttributesInteractively(client)),willPrompt&&(settings=await getFlagSettings(client,project.id));let entity={kind,label,attributes},entities2=[...settings.entities,entity];try{validateEntityLabel(label),validateEntities(entities2)}catch(err){return output_manager_default.fatal(err.message),1}output_manager_default.spinner("Creating entity\u2026");let updated=await updateFlagSettings(client,project.id,{entities:entities2});output_manager_default.stopSpinner();let created=findEntity(updated.entities,kind)??entity;return json?(client.stdout.write(`${JSON.stringify({entity:created},null,2)}
|
|
341
341
|
`),0):(output_manager_default.success(`Feature flag entity ${import_chalk79.default.bold(created.kind)} created`),printEntityDetails(created,projectSlugLink),0)}async function resolveEntityLabel(client,label,kind){if(label)return label;let defaultLabel=defaultEntityLabel(kind);return client.stdin.isTTY&&!client.nonInteractive&&(await client.input.text({message:`Enter a label for this entity (press Enter for "${defaultLabel}"):`})).trim()||defaultLabel}async function collectAttributesInteractively(client){let attributes=[],addAnother=await client.input.confirm("Add attributes now?",!0);for(;addAnother;){let key=await client.input.text({message:"Attribute key (for example plan):",validate:value=>{try{validateAttributeKey(value.trim())}catch(err){return err.message}return attributes.some(attribute=>attribute.key===value.trim())?`Attribute "${value.trim()}" is already added.`:!0}}),type=await client.input.select({message:"Attribute type:",choices:FLAG_ATTRIBUTE_TYPES.map(value=>({name:value,value}))});attributes.push({key:key.trim(),type}),addAnother=await client.input.confirm("Add another attribute?",!1)}return attributes}var import_chalk80=__toESM(require_source(),1);async function entitiesUpdate(client,argv){let parsedArgs=parseEntityArguments(client,argv,entitiesUpdateSubcommand.options),{args,flags}=parsedArgs,kind=args[0],label=flags["--label"]?.trim(),addInputs=flags["--add-attribute"]??[],removeInputs=flags["--remove-attribute"]??[],setTypeInputs=flags["--set-attribute-type"]??[],json=flags["--json"],projectName=getProjectNameFromFlags(flags),changes;try{changes=parseChanges({label,addInputs,removeInputs,setTypeInputs})}catch(err){return output_manager_default.fatal(err.message),2}if(!(changes.label!==void 0||changes.addAttributes.length>0||changes.removeAttributes.length>0||changes.setAttributeTypes.length>0))return client.nonInteractive?(entityAgentError(client,{reason:AGENT_REASON.MISSING_ARGUMENTS,message:"Provide at least one entity update option, such as --label, --add-attribute, --remove-attribute, or --set-attribute-type.",next:[{command:"flags entities update <kind> --add-attribute <key>:<type>",when:"add an attribute to an entity"},{command:"flags entities update <kind> --remove-attribute <key>",when:"remove an attribute from an entity"},{command:"flags entities ls --json",when:"inspect the current entities first"}]}),2):(output_manager_default.fatal("Provide at least one change: --label, --add-attribute, --remove-attribute, or --set-attribute-type"),output_manager_default.log(`Example: ${getCommandName("flags entities update user --add-attribute email:string")}`),2);let context=await resolveEntitiesProject(client,projectName);if(isExitCodeResult(context))return context.exitCode;let{project,projectSlugLink}=context;output_manager_default.spinner("Fetching feature flag settings\u2026");let settings=await getFlagSettings(client,project.id);if(output_manager_default.stopSpinner(),!kind){if(client.stdin.isTTY&&!client.nonInteractive&&printAlignedLabel("Project",projectSlugLink),kind=await selectEntityKind(client,settings.entities,"update",buildRetryCommand(void 0,changes)),!kind)return client.nonInteractive||!client.stdin.isTTY?2:1;settings=await getFlagSettings(client,project.id)}let entity=findEntity(settings.entities,kind);if(!entity)return reportEntityNotFound(client,kind,buildRetryCommand(void 0,changes)),1;let retryCommand=buildRetryCommand(kind,changes);for(let attribute of changes.addAttributes)if(findAttribute(entity,attribute.key))return output_manager_default.fatal(`Attribute "${attribute.key}" already exists on entity "${entity.kind}". Use --set-attribute-type to change its type.`),1;for(let key of changes.removeAttributes)if(!findAttribute(entity,key))return output_manager_default.fatal(`Attribute ${import_chalk80.default.bold(`${kind}.${key}`)} does not exist.`),1;for(let attribute of changes.setAttributeTypes)if(!findAttribute(entity,attribute.key))return output_manager_default.fatal(`Attribute ${import_chalk80.default.bold(`${kind}.${attribute.key}`)} does not exist. Use --add-attribute to add it.`),1;let updatedEntity=applyChanges(entity,changes),entities2=settings.entities.map(candidate=>candidate.kind===kind?updatedEntity:candidate);try{validateEntities(entities2)}catch(err){return output_manager_default.fatal(err.message),1}let typeChanges=changes.setAttributeTypes.filter(attribute=>findAttribute(entity,attribute.key)?.type!==attribute.type),guardedKeys=[...changes.removeAttributes,...typeChanges.map(attribute=>attribute.key)];if(guardedKeys.length>0){output_manager_default.spinner("Checking flags and segments for references\u2026");let sources=await loadEntityUsageSources(client,project.id);output_manager_default.stopSpinner();for(let key of guardedKeys){let usage=collectEntityUsage(sources,kind,key);if(reportEntityInUse(client,{kind,attribute:key,usage,retryCommand}))return 1}}output_manager_default.spinner("Updating entity\u2026");let updated=await updateFlagSettings(client,project.id,{entities:entities2});output_manager_default.stopSpinner();let result=findEntity(updated.entities,kind)??updatedEntity;return json?(client.stdout.write(`${JSON.stringify({entity:result},null,2)}
|
|
342
|
-
`),0):(output_manager_default.success(`Feature flag entity ${import_chalk80.default.bold(result.kind)} updated`),printEntityDetails(result,projectSlugLink),0)}function parseChanges(input){input.label!==void 0&&validateEntityLabel(input.label);let addAttributes=parseAttributeInputs(input.addInputs),setAttributeTypes=parseAttributeInputs(input.setTypeInputs),removeAttributes=input.removeInputs.map(value=>value.trim());for(let key of removeAttributes)validateAttributeKey(key);let removed=new Set(removeAttributes);for(let attribute of[...addAttributes,...setAttributeTypes])if(removed.has(attribute.key))throw new Error(`Attribute "${attribute.key}" can not be removed and changed in the same command.`);let added=new Set(addAttributes.map(attribute=>attribute.key));for(let attribute of setAttributeTypes)if(added.has(attribute.key))throw new Error(`Attribute "${attribute.key}" can not be added and have its type changed in the same command.`);return{label:input.label,addAttributes,removeAttributes,setAttributeTypes}}function applyChanges(entity,changes){let removed=new Set(changes.removeAttributes),typeByKey=new Map(changes.setAttributeTypes.map(attribute=>[attribute.key,attribute.type]));return{...entity,label:changes.label??entity.label,attributes:[...entity.attributes.filter(attribute=>!removed.has(attribute.key)).map(attribute=>{let type=typeByKey.get(attribute.key);return type!==void 0&&type!==attribute.type?{key:attribute.key,type}:attribute}),...changes.addAttributes]}}function buildRetryCommand(kind,changes){let parts=[`flags entities update ${kind===void 0?"<kind>":quoteArg(kind)}`];changes.label!==void 0&&parts.push(`--label ${quoteArg(changes.label)}`);for(let attribute of changes.addAttributes)parts.push(`--add-attribute ${quoteArg(`${attribute.key}:${attribute.type}`)}`);for(let key of changes.removeAttributes)parts.push(`--remove-attribute ${quoteArg(key)}`);for(let attribute of changes.setAttributeTypes)parts.push(`--set-attribute-type ${quoteArg(`${attribute.key}:${attribute.type}`)}`);return parts.join(" ")}var import_chalk81=__toESM(require_source(),1),import_pluralize6=__toESM(require_pluralize(),1);async function entitiesRm(client,argv){let parsedArgs=parseEntityArguments(client,argv,entitiesRemoveSubcommand.options),{args,flags}=parsedArgs;if(args.length>1){let message="Provide only one entity kind to delete.";return entityAgentError(client,{reason:AGENT_REASON.INVALID_ARGUMENTS,message,next:[{command:"flags entities delete <kind> --yes",when:"replace <kind> with the single entity kind to delete"}]}),client.nonInteractive||output_manager_default.fatal(message),2}let kind=args[0],skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);if(client.nonInteractive||!client.stdin.isTTY){if(!kind)return await selectEntityKind(client,[],"delete","flags entities delete <kind> --yes"),2;if(!skipConfirmation)return reportMissingConfirmation(client,kind),1}let context=await resolveEntitiesProject(client,projectName);if(isExitCodeResult(context))return context.exitCode;let{project,projectSlugLink}=context;output_manager_default.spinner("Fetching feature flag settings\u2026");let settings=await getFlagSettings(client,project.id),prompted=!1;if(output_manager_default.stopSpinner(),!kind&&(printAlignedLabel("Project",projectSlugLink),kind=await selectEntityKind(client,settings.entities,"delete","flags entities delete <kind> --yes"),prompted=!0,!kind))return 1;let entity=findEntity(settings.entities,kind);if(!entity)return reportEntityNotFound(client,kind,"flags entities delete <kind> --yes"),1;if(!skipConfirmation){prompted||printAlignedLabel("Project",projectSlugLink);let confirmed=await client.input.confirm(`Delete entity ${import_chalk81.default.bold(entity.kind)} and its ${(0,import_pluralize6.default)("attribute",entity.attributes.length,!0)}?`,!1);if(prompted=!0,!confirmed)return output_manager_default.log("Aborted"),0}if(prompted&&(settings=await getFlagSettings(client,project.id),!findEntity(settings.entities,kind)))return reportEntityNotFound(client,kind,"flags entities delete <kind> --yes"),1;output_manager_default.spinner("Checking flags and segments for references\u2026");let sources=await loadEntityUsageSources(client,project.id);return output_manager_default.stopSpinner(),reportEntityInUse(client,{kind,usage:collectEntityUsage(sources,kind),retryCommand:`flags entities delete ${quoteArg(kind)} --yes`})?1:(output_manager_default.spinner("Deleting entity\u2026"),await updateFlagSettings(client,project.id,{entities:settings.entities.filter(candidate=>candidate.kind!==kind)}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag entity ${import_chalk81.default.bold(entity.kind)} deleted`),0)}function reportMissingConfirmation(client,kind){entityAgentError(client,{reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`Add --yes to delete entity ${kind}.`,next:[{command:`flags entities delete ${quoteArg(kind)} --yes`,when:"delete the entity"}]}),client.nonInteractive||output_manager_default.fatal("Missing required flag --yes. Add --yes to delete the entity without prompting.")}var commands={ls:{command:entitiesListSubcommand,run:entitiesLs},create:{command:entitiesCreateSubcommand,run:entitiesCreate},update:{command:entitiesUpdateSubcommand,run:entitiesUpdate},delete:{command:entitiesRemoveSubcommand,run:entitiesRm}},aliases=Object.fromEntries(Object.entries(commands).map(([name,{command}])=>[name,getCommandAliases(command)]));async function entities(client){let telemetry=new FlagsEntitiesTelemetryClient({opts:{store:client.telemetryEventStore}});try{let parsed=parseArguments(client.argv.slice(4),getFlagsSpecification(entitiesSubcommand.options),{permissive:!0}),{subcommand,args,subcommandOriginal}=getSubcommand(parsed.args,aliases),entry=typeof subcommand=="string"?commands[subcommand]:void 0;return parsed.flags["--help"]||!entry?(parsed.flags["--help"]?telemetry.trackCliFlagHelp("flags entities",entry?subcommandOriginal:void 0):output_manager_default.fatal(getInvalidSubcommand(aliases)),output_manager_default.print(help(entry?.command??entitiesSubcommand,{parent:entry?{...entitiesSubcommand,name:"flags entities"}:flagsCommand,columns:client.stderr.columns})),parsed.flags["--help"]?0:2):(telemetry.trackSubcommand(subcommand,subcommandOriginal),subcommand==="create"&&subcommandOriginal==="add"&&warnDeprecatedSubcommand(client,"flags entities add","flags entities create"),subcommand==="delete"&&subcommandOriginal==="remove"&&warnDeprecatedSubcommand(client,"flags entities remove","flags entities delete"),await entry.run(client,args))}catch(err){return output_manager_default.stopSpinner(),printError(err),1}}var import_pluralize7=__toESM(require_pluralize(),1);function parseEntityLabelOperations(input){let operations;if(input.data!==void 0){if(input.set.length||input.remove.length)throw new Error("Can't combine --data with --set or --remove.");let data;try{data=JSON.parse(input.data)}catch{throw new Error("--data must be a JSON array of label operations.")}if(!Array.isArray(data)||data.length===0)throw new Error("--data must be a non-empty JSON array of label operations.");operations=data}else operations=[...input.remove.map(value=>({operation:"delete",value})),...input.set.map(valueLabel=>{let separator=valueLabel.indexOf("=");if(separator===-1)throw new Error('Use --set VALUE=LABEL, for example --set "pro=Pro Plan".');return{operation:"upsert",value:valueLabel.slice(0,separator),label:valueLabel.slice(separator+1)}})];return validateEntityLabelOperations(operations)}var MAX_LABEL_OPERATIONS=100;function validateEntityLabelOperations(operations){if(operations.length>MAX_LABEL_OPERATIONS)throw new Error(`Cannot update more than ${MAX_LABEL_OPERATIONS} labels at once. Split the operations into smaller batches.`);let values=new Set;return operations.map(item=>{if(!item||typeof item!="object")throw new Error("Each label operation must be an object.");let record=item,{operation,value,label}=record;if(operation!=="upsert"&&operation!=="delete")throw new Error('Label operations must use "upsert" or "delete".');let keys=operation==="upsert"?["operation","value","label"]:["operation","value"];if(Object.keys(record).some(key=>!keys.includes(key)))throw new Error(`Label ${operation} operations accept only ${keys.join(", ")}.`);if(validateLabelString(value,"value"),values.has(value))throw new Error("Each value can have only one label operation per command.");return values.add(value),operation==="delete"?{operation,value}:(validateLabelString(label,"label"),{operation,value,label})})}function validateLabelString(value,field){if(typeof value!="string"||Array.from(value).length>128)throw new Error(`Label ${field} must be a string of at most 128 characters.`)}function updateEntityLabelsBulk(client,projectId,items){return client.fetch(`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/labels/bulk`,{method:"PATCH",body:{items},retry:{retries:0},bailOn429:!0})}function parseLabelPagination(limit=20,next,attribute){if(!Number.isSafeInteger(limit)||limit<1)throw new Error("The --limit option must be a positive integer.");if(next===void 0)return{limit};try{if(!/^[A-Za-z0-9_-]+$/.test(next)||next.length>4096)throw new Error;let cursor=JSON.parse(Buffer.from(next,"base64url").toString("utf8"));if(!cursor||cursor.version!==1||typeof cursor.projectId!="string"||!cursor.projectId||cursor.attribute!==attribute||typeof cursor.after!="string")throw new Error;return{limit,cursor}}catch{throw new Error("Invalid or expired --next cursor for this list view. Omit --next to restart the list.")}}function paginateLabelItems(items,{limit,cursor},projectId,attribute,key){let remaining=items.filter(item=>cursor===void 0||key(item)>cursor.after).sort((a,b)=>key(a)<key(b)?-1:key(a)>key(b)?1:0),page=remaining.slice(0,limit),next=remaining.length>page.length?Buffer.from(JSON.stringify({version:1,projectId,attribute,after:key(page[page.length-1])})).toString("base64url"):null;return{items:page,pagination:{next}}}var FlagsLabelsTelemetryClient=class extends TelemetryClient{trackSubcommand(subcommand,actual){this.trackCliSubcommand({subcommand,value:actual})}trackArguments(args,flags){for(let[index,arg]of["attribute","value","label"].entries())index<args.length&&this.trackCliArgument({arg,value:this.redactedValue});this.trackCliOptionProject(flags["--project"]);for(let option of["set","remove","data","next"])flags[`--${option}`]!==void 0&&this.trackCliOption({option,value:this.redactedValue});flags["--limit"]!==void 0&&this.trackCliOption({option:"limit",value:String(flags["--limit"])}),flags["--json"]&&this.trackCliFlag("json")}};async function labels(client){let argv=client.argv.slice(4),telemetry=new FlagsLabelsTelemetryClient({opts:{store:client.telemetryEventStore}}),json=client.nonInteractive||argv.includes("--json"),inspectCommand="flags entities ls --json",reason=AGENT_REASON.INVALID_ARGUMENTS,recovery="Inspect entities and labels before retrying";function next(){return[{command:buildCommandWithGlobalFlags(client.argv,inspectCommand,void 0,{preserveProject:inspectCommand.startsWith("flags ")}),when:recovery}]}function printRecovery(){output_manager_default.print(` ${recovery}:
|
|
342
|
+
`),0):(output_manager_default.success(`Feature flag entity ${import_chalk80.default.bold(result.kind)} updated`),printEntityDetails(result,projectSlugLink),0)}function parseChanges(input){input.label!==void 0&&validateEntityLabel(input.label);let addAttributes=parseAttributeInputs(input.addInputs),setAttributeTypes=parseAttributeInputs(input.setTypeInputs),removeAttributes=input.removeInputs.map(value=>value.trim());for(let key of removeAttributes)validateAttributeKey(key);let removed=new Set(removeAttributes);for(let attribute of[...addAttributes,...setAttributeTypes])if(removed.has(attribute.key))throw new Error(`Attribute "${attribute.key}" can not be removed and changed in the same command.`);let added=new Set(addAttributes.map(attribute=>attribute.key));for(let attribute of setAttributeTypes)if(added.has(attribute.key))throw new Error(`Attribute "${attribute.key}" can not be added and have its type changed in the same command.`);return{label:input.label,addAttributes,removeAttributes,setAttributeTypes}}function applyChanges(entity,changes){let removed=new Set(changes.removeAttributes),typeByKey=new Map(changes.setAttributeTypes.map(attribute=>[attribute.key,attribute.type]));return{...entity,label:changes.label??entity.label,attributes:[...entity.attributes.filter(attribute=>!removed.has(attribute.key)).map(attribute=>{let type=typeByKey.get(attribute.key);return type!==void 0&&type!==attribute.type?{key:attribute.key,type}:attribute}),...changes.addAttributes]}}function buildRetryCommand(kind,changes){let parts=[`flags entities update ${kind===void 0?"<kind>":quoteArg(kind)}`];changes.label!==void 0&&parts.push(`--label ${quoteArg(changes.label)}`);for(let attribute of changes.addAttributes)parts.push(`--add-attribute ${quoteArg(`${attribute.key}:${attribute.type}`)}`);for(let key of changes.removeAttributes)parts.push(`--remove-attribute ${quoteArg(key)}`);for(let attribute of changes.setAttributeTypes)parts.push(`--set-attribute-type ${quoteArg(`${attribute.key}:${attribute.type}`)}`);return parts.join(" ")}var import_chalk81=__toESM(require_source(),1),import_pluralize6=__toESM(require_pluralize(),1);async function entitiesRm(client,argv){let parsedArgs=parseEntityArguments(client,argv,entitiesRemoveSubcommand.options),{args,flags}=parsedArgs;if(args.length>1){let message="Provide only one entity kind to delete.";return entityAgentError(client,{reason:AGENT_REASON.INVALID_ARGUMENTS,message,next:[{command:"flags entities delete <kind> --yes",when:"replace <kind> with the single entity kind to delete"}]}),client.nonInteractive||output_manager_default.fatal(message),2}let kind=args[0],skipConfirmation=flags["--yes"],projectName=getProjectNameFromFlags(flags);if(client.nonInteractive||!client.stdin.isTTY){if(!kind)return await selectEntityKind(client,[],"delete","flags entities delete <kind> --yes"),2;if(!skipConfirmation)return reportMissingConfirmation(client,kind),1}let context=await resolveEntitiesProject(client,projectName);if(isExitCodeResult(context))return context.exitCode;let{project,projectSlugLink}=context;output_manager_default.spinner("Fetching feature flag settings\u2026");let settings=await getFlagSettings(client,project.id),prompted=!1;if(output_manager_default.stopSpinner(),!kind&&(printAlignedLabel("Project",projectSlugLink),kind=await selectEntityKind(client,settings.entities,"delete","flags entities delete <kind> --yes"),prompted=!0,!kind))return 1;let entity=findEntity(settings.entities,kind);if(!entity)return reportEntityNotFound(client,kind,"flags entities delete <kind> --yes"),1;if(!skipConfirmation){prompted||printAlignedLabel("Project",projectSlugLink);let confirmed=await client.input.confirm(`Delete entity ${import_chalk81.default.bold(entity.kind)} and its ${(0,import_pluralize6.default)("attribute",entity.attributes.length,!0)}?`,!1);if(prompted=!0,!confirmed)return output_manager_default.log("Aborted"),0}if(prompted&&(settings=await getFlagSettings(client,project.id),!findEntity(settings.entities,kind)))return reportEntityNotFound(client,kind,"flags entities delete <kind> --yes"),1;output_manager_default.spinner("Checking flags and segments for references\u2026");let sources=await loadEntityUsageSources(client,project.id);return output_manager_default.stopSpinner(),reportEntityInUse(client,{kind,usage:collectEntityUsage(sources,kind),retryCommand:`flags entities delete ${quoteArg(kind)} --yes`})?1:(output_manager_default.spinner("Deleting entity\u2026"),await updateFlagSettings(client,project.id,{entities:settings.entities.filter(candidate=>candidate.kind!==kind)}),output_manager_default.stopSpinner(),output_manager_default.success(`Feature flag entity ${import_chalk81.default.bold(entity.kind)} deleted`),0)}function reportMissingConfirmation(client,kind){entityAgentError(client,{reason:AGENT_REASON.CONFIRMATION_REQUIRED,message:`Add --yes to delete entity ${kind}.`,next:[{command:`flags entities delete ${quoteArg(kind)} --yes`,when:"delete the entity"}]}),client.nonInteractive||output_manager_default.fatal("Missing required option --yes. Add --yes to delete the entity without prompting.")}var commands={ls:{command:entitiesListSubcommand,run:entitiesLs},create:{command:entitiesCreateSubcommand,run:entitiesCreate},update:{command:entitiesUpdateSubcommand,run:entitiesUpdate},delete:{command:entitiesRemoveSubcommand,run:entitiesRm}},aliases=Object.fromEntries(Object.entries(commands).map(([name,{command}])=>[name,getCommandAliases(command)]));async function entities(client){let telemetry=new FlagsEntitiesTelemetryClient({opts:{store:client.telemetryEventStore}});try{let parsed=parseArguments(client.argv.slice(4),getFlagsSpecification(entitiesSubcommand.options),{permissive:!0}),{subcommand,args,subcommandOriginal}=getSubcommand(parsed.args,aliases),entry=typeof subcommand=="string"?commands[subcommand]:void 0;return parsed.flags["--help"]||!entry?(parsed.flags["--help"]?telemetry.trackCliFlagHelp("flags entities",entry?subcommandOriginal:void 0):output_manager_default.fatal(getInvalidSubcommand(aliases)),output_manager_default.print(help(entry?.command??entitiesSubcommand,{stream:client.stderr,parent:entry?{...entitiesSubcommand,name:"flags entities"}:flagsCommand,columns:client.stderr.columns})),parsed.flags["--help"]?0:2):(telemetry.trackSubcommand(subcommand,subcommandOriginal),subcommand==="create"&&subcommandOriginal==="add"&&warnDeprecatedSubcommand(client,"flags entities add","flags entities create"),subcommand==="delete"&&subcommandOriginal==="remove"&&warnDeprecatedSubcommand(client,"flags entities remove","flags entities delete"),await entry.run(client,args))}catch(err){return output_manager_default.stopSpinner(),printError(err),1}}var import_pluralize7=__toESM(require_pluralize(),1);function parseEntityLabelOperations(input){let operations;if(input.data!==void 0){if(input.set.length||input.remove.length)throw new Error("Can't combine --data with --set or --remove.");let data;try{data=JSON.parse(input.data)}catch{throw new Error("--data must be a JSON array of label operations.")}if(!Array.isArray(data)||data.length===0)throw new Error("--data must be a non-empty JSON array of label operations.");operations=data}else operations=[...input.remove.map(value=>({operation:"delete",value})),...input.set.map(valueLabel=>{let separator=valueLabel.indexOf("=");if(separator===-1)throw new Error('Use --set VALUE=LABEL, for example --set "pro=Pro Plan".');return{operation:"upsert",value:valueLabel.slice(0,separator),label:valueLabel.slice(separator+1)}})];return validateEntityLabelOperations(operations)}var MAX_LABEL_OPERATIONS=100;function validateEntityLabelOperations(operations){if(operations.length>MAX_LABEL_OPERATIONS)throw new Error(`Cannot update more than ${MAX_LABEL_OPERATIONS} labels at once. Split the operations into smaller batches.`);let values=new Set;return operations.map(item=>{if(!item||typeof item!="object")throw new Error("Each label operation must be an object.");let record=item,{operation,value,label}=record;if(operation!=="upsert"&&operation!=="delete")throw new Error('Label operations must use "upsert" or "delete".');let keys=operation==="upsert"?["operation","value","label"]:["operation","value"];if(Object.keys(record).some(key=>!keys.includes(key)))throw new Error(`Label ${operation} operations accept only ${keys.join(", ")}.`);if(validateLabelString(value,"value"),values.has(value))throw new Error("Each value can have only one label operation per command.");return values.add(value),operation==="delete"?{operation,value}:(validateLabelString(label,"label"),{operation,value,label})})}function validateLabelString(value,field){if(typeof value!="string"||Array.from(value).length>128)throw new Error(`Label ${field} must be a string of at most 128 characters.`)}function updateEntityLabelsBulk(client,projectId,items){return client.fetch(`/v1/projects/${encodeURIComponent(projectId)}/feature-flags/labels/bulk`,{method:"PATCH",body:{items},retry:{retries:0},bailOn429:!0})}function parseLabelPagination(limit=20,next,attribute){if(!Number.isSafeInteger(limit)||limit<1)throw new Error("The --limit option must be a positive integer.");if(next===void 0)return{limit};try{if(!/^[A-Za-z0-9_-]+$/.test(next)||next.length>4096)throw new Error;let cursor=JSON.parse(Buffer.from(next,"base64url").toString("utf8"));if(!cursor||cursor.version!==1||typeof cursor.projectId!="string"||!cursor.projectId||cursor.attribute!==attribute||typeof cursor.after!="string")throw new Error;return{limit,cursor}}catch{throw new Error("Invalid or expired --next cursor for this list view. Omit --next to restart the list.")}}function paginateLabelItems(items,{limit,cursor},projectId,attribute,key){let remaining=items.filter(item=>cursor===void 0||key(item)>cursor.after).sort((a,b)=>key(a)<key(b)?-1:key(a)>key(b)?1:0),page=remaining.slice(0,limit),next=remaining.length>page.length?Buffer.from(JSON.stringify({version:1,projectId,attribute,after:key(page[page.length-1])})).toString("base64url"):null;return{items:page,pagination:{next}}}var FlagsLabelsTelemetryClient=class extends TelemetryClient{trackSubcommand(subcommand,actual){this.trackCliSubcommand({subcommand,value:actual})}trackArguments(args,flags){for(let[index,arg]of["attribute","value","label"].entries())index<args.length&&this.trackCliArgument({arg,value:this.redactedValue});this.trackCliOptionProject(flags["--project"]);for(let option of["set","remove","data","next"])flags[`--${option}`]!==void 0&&this.trackCliOption({option,value:this.redactedValue});flags["--limit"]!==void 0&&this.trackCliOption({option:"limit",value:String(flags["--limit"])}),flags["--json"]&&this.trackCliFlag("json")}};async function labels(client){let argv=client.argv.slice(4),telemetry=new FlagsLabelsTelemetryClient({opts:{store:client.telemetryEventStore}}),json=client.nonInteractive||argv.includes("--json"),inspectCommand="flags entities ls --json",reason=AGENT_REASON.INVALID_ARGUMENTS,recovery="Inspect entities and labels before retrying";function next(){return[{command:buildCommandWithGlobalFlags(client.argv,inspectCommand,void 0,{preserveProject:inspectCommand.startsWith("flags ")}),when:recovery}]}function printRecovery(){output_manager_default.print(` ${recovery}:
|
|
343
343
|
${next()[0].command}
|
|
344
344
|
`)}function fail(message){if(json){let status2=reason===AGENT_REASON.MISSING_ARGUMENTS||reason===AGENT_REASON.NOT_LINKED?AGENT_STATUS.ACTION_REQUIRED:AGENT_STATUS.ERROR;client.stdout.write(`${JSON.stringify({status:status2,reason,message,next:next()},null,2)}
|
|
345
345
|
`)}else output_manager_default.fatal(message),printRecovery();return getExitCodeForReason(reason)}try{let printNextPage2=function(cursor){if(!json&&cursor&&pageOptions){let globalArgs=getGlobalFlagsFromArgs(client.argv.slice(2));globalArgs.some(arg=>arg==="--scope"||arg==="-S"||arg.startsWith("--scope="))||globalArgs.push("--scope",org.slug);let command2=getCommandNamePlain(["flags","labels","ls",...target===void 0?[]:[target],"--project",project.name,"--limit",String(pageOptions.limit),"--next",cursor,...globalArgs].map(quoteArg).join(" "));output_manager_default.print(`
|
|
346
|
-
`),printNextPageCommand(command2)}};var printNextPage=printNextPage2;let parsed=parseArguments(argv,getFlagsSpecification(labelsListSubcommand.options),{permissive:!0}),aliases2=Object.fromEntries(labelsSubcommand.subcommands.map(command2=>[command2.name,getCommandAliases(command2)])),{subcommand,subcommandOriginal}=getSubcommand(parsed.args,aliases2),command=labelsSubcommand.subcommands.find(command2=>command2.name===subcommand);if(parsed.flags["--help"])return telemetry.trackCliFlagHelp("flags labels",command?subcommandOriginal:void 0),output_manager_default.print(help(command??labelsSubcommand,{parent:command?{...labelsSubcommand,name:"flags labels"}:flagsCommand,columns:client.stderr.columns})),0;if(!command)return reason=parsed.args.length?AGENT_REASON.INVALID_ARGUMENTS:AGENT_REASON.MISSING_ARGUMENTS,fail(getInvalidSubcommand(aliases2));telemetry.trackSubcommand(command.name,subcommandOriginal);let{args:positional,flags}=parseArguments(argv,getFlagsSpecification(command.options)),[target,...args]=positional.slice(1);if(telemetry.trackArguments(positional.slice(1),flags),json=!!flags["--json"]||client.nonInteractive,target===void 0&&command.name!=="ls")return reason=AGENT_REASON.MISSING_ARGUMENTS,fail('Provide an attribute as ENTITY.ATTRIBUTE. Example: vercel flags labels set user.plan pro "Pro Plan".');let[kind,attributeKey]=target?.split(".")??[];if(target!==void 0){if(target.split(".").length!==2)return fail("Use an attribute as ENTITY.ATTRIBUTE, for example user.plan.");validateEntityKind(kind),validateAttributeKey(attributeKey)}let pageOptions=command.name==="ls"?parseLabelPagination(flags["--limit"],flags["--next"],target??null):void 0;if(args.length!==command.arguments.length-1)return args.length<command.arguments.length-1&&(reason=AGENT_REASON.MISSING_ARGUMENTS),fail(command.name==="set"?'Provide a value and a label. Example: vercel flags labels set user.plan pro "Pro Plan".':command.name==="remove"?"Provide one value. Example: vercel flags labels remove user.plan pro.":`The ${command.name} command accepts only one attribute as ENTITY.ATTRIBUTE.`);let operations=command.name==="set"?validateEntityLabelOperations([{operation:"upsert",value:args[0],label:args[1]}]):command.name==="remove"?validateEntityLabelOperations([{operation:"delete",value:args[0]}]):parseEntityLabelOperations({set:flags["--set"]??[],remove:flags["--remove"]??[],data:flags["--data"]});if(command.name==="apply"&&operations.length===0)return reason=AGENT_REASON.MISSING_ARGUMENTS,fail("Provide --set VALUE=LABEL, --remove VALUE, or --data JSON.");reason=AGENT_REASON.API_ERROR;let projectName=getProjectNameFromFlags(flags),context=await getLinkedFlagsProject(client,projectName,{projectNotFoundHandling:"return"});if(context.status==="error")return inspectCommand="project ls",recovery="Check the project and team context before retrying",fail("Failed to resolve the project. Check the project and team settings.");if(context.status==="not_linked")return reason=projectName?AGENT_REASON.PROJECT_NOT_FOUND:AGENT_REASON.NOT_LINKED,inspectCommand=projectName?"project ls":"link",recovery=projectName?"Select an accessible project before retrying":"Link a project before retrying",fail(projectName?`Project ${JSON.stringify(projectName)} was not found or is not accessible. Check --project and your team scope.`:"Your codebase isn't linked to a project. Pass --project <name>, or run vercel link to link it.");let{project,org}=context;if(client.config.currentTeam=org.type==="team"?org.id:void 0,pageOptions?.cursor&&pageOptions.cursor.projectId!==project.id)return reason=AGENT_REASON.INVALID_ARGUMENTS,fail("The --next cursor belongs to a different project. Omit --next to restart the list.");let projectSlugLink=formatProject(org.slug,project.name);output_manager_default.spinner("Fetching attribute labels\u2026");let settings=await getFlagSettings(client,project.id);if(output_manager_default.stopSpinner(),pageOptions&&target===void 0){let available=settings.entities.flatMap(entity2=>entity2.attributes.filter(attribute2=>attribute2.labels?.length).map(attribute2=>({id:null,attributes:[{entityKind:entity2.kind,attributeKey:attribute2.key}],labelCount:attribute2.labels.length}))),{items:lists,pagination}=paginateLabelItems(available,pageOptions,project.id,null,list7=>`${list7.attributes[0].entityKind}.${list7.attributes[0].attributeKey}`);if(json)client.stdout.write(`${JSON.stringify({status:AGENT_STATUS.OK,lists,pagination},null,2)}
|
|
346
|
+
`),printNextPageCommand(command2)}};var printNextPage=printNextPage2;let parsed=parseArguments(argv,getFlagsSpecification(labelsListSubcommand.options),{permissive:!0}),aliases2=Object.fromEntries(labelsSubcommand.subcommands.map(command2=>[command2.name,getCommandAliases(command2)])),{subcommand,subcommandOriginal}=getSubcommand(parsed.args,aliases2),command=labelsSubcommand.subcommands.find(command2=>command2.name===subcommand);if(parsed.flags["--help"])return telemetry.trackCliFlagHelp("flags labels",command?subcommandOriginal:void 0),output_manager_default.print(help(command??labelsSubcommand,{stream:client.stderr,parent:command?{...labelsSubcommand,name:"flags labels"}:flagsCommand,columns:client.stderr.columns})),0;if(!command)return reason=parsed.args.length?AGENT_REASON.INVALID_ARGUMENTS:AGENT_REASON.MISSING_ARGUMENTS,fail(getInvalidSubcommand(aliases2));telemetry.trackSubcommand(command.name,subcommandOriginal);let{args:positional,flags}=parseArguments(argv,getFlagsSpecification(command.options)),[target,...args]=positional.slice(1);if(telemetry.trackArguments(positional.slice(1),flags),json=!!flags["--json"]||client.nonInteractive,target===void 0&&command.name!=="ls")return reason=AGENT_REASON.MISSING_ARGUMENTS,fail('Provide an attribute as ENTITY.ATTRIBUTE. Example: vercel flags labels set user.plan pro "Pro Plan".');let[kind,attributeKey]=target?.split(".")??[];if(target!==void 0){if(target.split(".").length!==2)return fail("Use an attribute as ENTITY.ATTRIBUTE, for example user.plan.");validateEntityKind(kind),validateAttributeKey(attributeKey)}let pageOptions=command.name==="ls"?parseLabelPagination(flags["--limit"],flags["--next"],target??null):void 0;if(args.length!==command.arguments.length-1)return args.length<command.arguments.length-1&&(reason=AGENT_REASON.MISSING_ARGUMENTS),fail(command.name==="set"?'Provide a value and a label. Example: vercel flags labels set user.plan pro "Pro Plan".':command.name==="remove"?"Provide one value. Example: vercel flags labels remove user.plan pro.":`The ${command.name} command accepts only one attribute as ENTITY.ATTRIBUTE.`);let operations=command.name==="set"?validateEntityLabelOperations([{operation:"upsert",value:args[0],label:args[1]}]):command.name==="remove"?validateEntityLabelOperations([{operation:"delete",value:args[0]}]):parseEntityLabelOperations({set:flags["--set"]??[],remove:flags["--remove"]??[],data:flags["--data"]});if(command.name==="apply"&&operations.length===0)return reason=AGENT_REASON.MISSING_ARGUMENTS,fail("Provide --set VALUE=LABEL, --remove VALUE, or --data JSON.");reason=AGENT_REASON.API_ERROR;let projectName=getProjectNameFromFlags(flags),context=await getLinkedFlagsProject(client,projectName,{projectNotFoundHandling:"return"});if(context.status==="error")return inspectCommand="project ls",recovery="Check the project and team context before retrying",fail("Failed to resolve the project. Check the project and team settings.");if(context.status==="not_linked")return reason=projectName?AGENT_REASON.PROJECT_NOT_FOUND:AGENT_REASON.NOT_LINKED,inspectCommand=projectName?"project ls":"link",recovery=projectName?"Select an accessible project before retrying":"Link a project before retrying",fail(projectName?`Project ${JSON.stringify(projectName)} was not found or is not accessible. Check --project and your team scope.`:"Your codebase isn't linked to a project. Pass --project <name>, or run vercel link to link it.");let{project,org}=context;if(client.config.currentTeam=org.type==="team"?org.id:void 0,pageOptions?.cursor&&pageOptions.cursor.projectId!==project.id)return reason=AGENT_REASON.INVALID_ARGUMENTS,fail("The --next cursor belongs to a different project. Omit --next to restart the list.");let projectSlugLink=formatProject(org.slug,project.name);output_manager_default.spinner("Fetching attribute labels\u2026");let settings=await getFlagSettings(client,project.id);if(output_manager_default.stopSpinner(),pageOptions&&target===void 0){let available=settings.entities.flatMap(entity2=>entity2.attributes.filter(attribute2=>attribute2.labels?.length).map(attribute2=>({id:null,attributes:[{entityKind:entity2.kind,attributeKey:attribute2.key}],labelCount:attribute2.labels.length}))),{items:lists,pagination}=paginateLabelItems(available,pageOptions,project.id,null,list7=>`${list7.attributes[0].entityKind}.${list7.attributes[0].attributeKey}`);if(json)client.stdout.write(`${JSON.stringify({status:AGENT_STATUS.OK,lists,pagination},null,2)}
|
|
347
347
|
`);else if(printAlignedLabel("Project",projectSlugLink),lists.length===0)output_manager_default.log(pageOptions.cursor?"No more label lists found.":"No label lists found.");else{let rows=lists.map(list7=>[`${list7.attributes[0].entityKind}.${list7.attributes[0].attributeKey}`,String(list7.labelCount)]);output_manager_default.print(`
|
|
348
348
|
${formatTable(["Attribute","Labels"],["l","r"],[{name:"",rows}])}
|
|
349
349
|
`)}return printNextPage2(pagination.next),0}let entity=findEntity(settings.entities,kind),attribute=entity&&findAttribute(entity,attributeKey);if(!attribute)return reason=AGENT_REASON.NOT_FOUND,fail(entity?`Attribute ${kind}.${attributeKey} was not found in this project.`:`Entity ${kind} was not found in this project.`);if(inspectCommand=`flags labels ls ${quoteArg(`${kind}.${attributeKey}`)} --json`,pageOptions){let{items:labels2,pagination}=paginateLabelItems(attribute.labels??[],pageOptions,project.id,`${kind}.${attributeKey}`,label=>label.value);if(json)client.stdout.write(`${JSON.stringify({status:AGENT_STATUS.OK,entityKind:kind,attributeKey,labels:labels2,pagination},null,2)}
|
|
@@ -358,7 +358,7 @@ ${formatTable(["Value","Label"],["l","l"],[{name:"",rows}])}
|
|
|
358
358
|
Add one with: ${getCommandName("flags rules add "+context.flag.slug+" --environment "+context.environment+" --condition user.plan:eq:pro --variant on"+projectFlag)}`),0}output_manager_default.log(`${(0,import_pluralize8.default)("conditional rule",rules2.length,!0)} found for ${import_chalk83.default.bold(context.flag.slug)} in ${environmentLabel} ${import_chalk83.default.gray(lsStamp())}`),printRulesTable(rules2,context.flag.variants,context.settings)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function outputJson6(client,data){client.stdout.write(`${JSON.stringify(data,null,2)}
|
|
359
359
|
`)}function printRulesTable(rules2,variants,settings){let headers=["Position","ID","Conditions","Outcome"],rows=rules2.map((rule,index)=>[String(index+1),import_chalk83.default.bold(rule.id),rule.conditions.map(condition=>formatFlagRuleCondition(condition,settings)).join("; "),formatFlagRuleOutcome(rule.outcome,variants)]),table2=formatTable(headers,["r","l","l","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
360
360
|
${table2}
|
|
361
|
-
`)}var import_chalk84=__toESM(require_source(),1);async function rulesAdd(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesAddSubcommand2.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],conditionInputs=flags["--condition"]??[],variantSelector=normalizeOptionalInput(flags["--variant"]),baseSelector=normalizeOptionalInput(flags["--by"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),weightInputs=flags["--weight"]??[],rollFromVariantSelector=normalizeOptionalInput(flags["--from-variant"]),rollToVariantSelector=normalizeOptionalInput(flags["--to-variant"]),stageInputs=(flags["--stage"]??[]).map(input=>input.trim()),finalPercentage=flags["--final-percentage"],start=normalizeOptionalInput(flags["--start"]),position=flags["--position"],message=normalizeOptionalInput(flags["--message"]);telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionCondition(conditionInputs),telemetryClient.trackCliOptionVariant(variantSelector),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionWeight(weightInputs),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionFromVariant(rollFromVariantSelector),telemetryClient.trackCliOptionToVariant(rollToVariantSelector),telemetryClient.trackCliOptionStage(stageInputs),telemetryClient.trackCliOptionFinalPercentage(finalPercentage),telemetryClient.trackCliOptionStart(start),telemetryClient.trackCliOptionPosition(position),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]);let outcomeOptions={variantSelector,baseSelector,defaultVariantSelector,weightInputs,rollFromVariantSelector,rollToVariantSelector,stageInputs,finalPercentage,start};if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to add a rule to"),output_manager_default.log(`Example: ${getCommandName("flags rules add my-feature --environment production --condition user.plan:eq:pro --variant on")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment to add the rule to:",fetchSettings:needsFlagRuleOutcomeSettings(outcomeOptions)||conditionInputs.length>0});if(isExitCodeResult2(context))return context.exitCode;let conditions=parseFlagRuleConditions(conditionInputs,context.settings),outcome=resolveFlagRuleOutcome(context.flag,context.settings,{...outcomeOptions,requireOutcome:!0}),rule=createFlagRule(conditions,outcome),envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),nextEnvConfig=addFlagRule(envConfig,rule,position),nextPosition=nextEnvConfig.rules.findIndex(candidate=>candidate.id===rule.id)+1,updateMessage=await resolveFlagUpdateMessage(client,message,`Add rule ${rule.id} to ${context.environment}`);output_manager_default.spinner(`Adding rule to ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner(),output_manager_default.success(`Rule ${import_chalk84.default.bold(rule.id)} added to ${import_chalk84.default.bold(context.flag.slug)} in ${import_chalk84.default.bold(context.environment)}`),output_manager_default.log(` ${import_chalk84.default.dim("Position:")} ${nextPosition}`),output_manager_default.log(` ${import_chalk84.default.dim("Outcome:")} ${formatFlagRuleOutcome(rule.outcome,context.flag.variants)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk85=__toESM(require_source(),1),import_fast_deep_equal8=__toESM(require_fast_deep_equal(),1);async function rulesUpdate(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesUpdateSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,ruleId]=args,environment=flags["--environment"],conditionInputs=flags["--condition"]??[],variantSelector=normalizeOptionalInput(flags["--variant"]),baseSelector=normalizeOptionalInput(flags["--by"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),weightInputs=flags["--weight"]??[],rollFromVariantSelector=normalizeOptionalInput(flags["--from-variant"]),rollToVariantSelector=normalizeOptionalInput(flags["--to-variant"]),stageInputs=(flags["--stage"]??[]).map(input=>input.trim()),finalPercentage=flags["--final-percentage"],start=normalizeOptionalInput(flags["--start"]),message=normalizeOptionalInput(flags["--message"]);telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliArgumentRule(ruleId),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionCondition(conditionInputs),telemetryClient.trackCliOptionVariant(variantSelector),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionWeight(weightInputs),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionFromVariant(rollFromVariantSelector),telemetryClient.trackCliOptionToVariant(rollToVariantSelector),telemetryClient.trackCliOptionStage(stageInputs),telemetryClient.trackCliOptionFinalPercentage(finalPercentage),telemetryClient.trackCliOptionStart(start),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]);let outcomeOptions={variantSelector,baseSelector,defaultVariantSelector,weightInputs,rollFromVariantSelector,rollToVariantSelector,stageInputs,finalPercentage,start};if(!flagArg||!ruleId)return output_manager_default.error("Please provide a flag slug or ID and rule ID to update"),output_manager_default.log(`Example: ${getCommandName("flags rules update my-feature rule_123 --environment production --variant on")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment containing the rule:",fetchSettings:needsFlagRuleOutcomeSettings(outcomeOptions)||conditionInputs.length>0});if(isExitCodeResult2(context))return context.exitCode;let envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),currentRule=findFlagRule(envConfig.rules??[],ruleId),hasOutcomeOptions=hasFlagRuleOutcomeOptions(outcomeOptions),nextConditions=conditionInputs.length>0?parseFlagRuleConditions(conditionInputs,context.settings):void 0,resolvedOutcome=hasOutcomeOptions?resolveFlagRuleOutcome(context.flag,context.settings,{...outcomeOptions,currentOutcome:currentRule.outcome}):void 0;if(!nextConditions&&!resolvedOutcome)return output_manager_default.warn("No rule changes were provided"),0;let nextEnvConfig=updateFlagRule(envConfig,ruleId,{conditions:nextConditions,outcome:resolvedOutcome});if((0,import_fast_deep_equal8.default)(context.envConfig,nextEnvConfig))return output_manager_default.warn("No rule changes were provided"),0;let updateMessage=await resolveFlagUpdateMessage(client,message,`Update rule ${ruleId} in ${context.environment}`);output_manager_default.spinner(`Updating rule in ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner();let nextRule=findFlagRule(nextEnvConfig.rules,ruleId);output_manager_default.success(`Rule ${import_chalk85.default.bold(ruleId)} updated for ${import_chalk85.default.bold(context.flag.slug)} in ${import_chalk85.default.bold(context.environment)}`),output_manager_default.log(` ${import_chalk85.default.dim("Conditions:")} ${nextRule.conditions.map(condition=>formatFlagRuleCondition(condition,context.settings)).join(", ")}`),output_manager_default.log(` ${import_chalk85.default.dim("Outcome:")} ${formatFlagRuleOutcome(nextRule.outcome,context.flag.variants)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk86=__toESM(require_source(),1);async function rulesRemove(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesRemoveSubcommand2.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,ruleId]=args,environment=flags["--environment"],message=normalizeOptionalInput(flags["--message"]);if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliArgumentRule(ruleId),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]),!flagArg||!ruleId)return output_manager_default.error("Please provide a flag slug or ID and rule ID to remove"),output_manager_default.log(`Example: ${getCommandName("flags rules remove my-feature rule_123 --environment production")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment containing the rule:"});if(isExitCodeResult2(context))return context.exitCode;let envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),nextEnvConfig=removeFlagRule(envConfig,ruleId),updateMessage=await resolveFlagUpdateMessage(client,message,`Remove rule ${ruleId} from ${context.environment}`);output_manager_default.spinner(`Removing rule from ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner(),output_manager_default.success(`Rule ${import_chalk86.default.bold(ruleId)} removed from ${import_chalk86.default.bold(context.flag.slug)} in ${import_chalk86.default.bold(context.environment)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk87=__toESM(require_source(),1),import_fast_deep_equal9=__toESM(require_fast_deep_equal(),1);async function rulesMove(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesMoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,ruleId]=args,environment=flags["--environment"],position=flags["--position"],message=normalizeOptionalInput(flags["--message"]);if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliArgumentRule(ruleId),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionPosition(position),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]),!flagArg||!ruleId||position===void 0)return output_manager_default.error("Please provide a flag slug or ID, rule ID, and destination position"),output_manager_default.log(`Example: ${getCommandName("flags rules move my-feature rule_123 --environment production --position 1")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment containing the rule:"});if(isExitCodeResult2(context))return context.exitCode;let envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),nextEnvConfig=moveFlagRule(envConfig,ruleId,position);if((0,import_fast_deep_equal9.default)(context.envConfig,nextEnvConfig))return output_manager_default.warn(`Rule ${import_chalk87.default.bold(ruleId)} is already at position ${position} in ${context.environment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,`Move rule ${ruleId} to position ${position} in ${context.environment}`);output_manager_default.spinner(`Moving rule in ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner(),output_manager_default.success(`Rule ${import_chalk87.default.bold(ruleId)} moved to position ${position} for ${import_chalk87.default.bold(context.flag.slug)} in ${import_chalk87.default.bold(context.environment)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG14={ls:getCommandAliases(rulesListSubcommand2),add:getCommandAliases(rulesAddSubcommand2),update:getCommandAliases(rulesUpdateSubcommand),rm:getCommandAliases(rulesRemoveSubcommand2),move:getCommandAliases(rulesMoveSubcommand)};async function rules(client){let telemetry=new FlagsRulesTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(rulesSubcommand2.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG14),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags rules",subcommand),output_manager_default.print(help(rulesSubcommand2,{parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:rulesSubcommand2,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesListSubcommand2),0):(telemetry.trackCliSubcommandList(subcommandOriginal),rulesLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesAddSubcommand2),0):(telemetry.trackCliSubcommandAdd(subcommandOriginal),rulesAdd(client,args));case"update":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesUpdateSubcommand),0):(telemetry.trackCliSubcommandUpdate(subcommandOriginal),rulesUpdate(client,args));case"rm":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesRemoveSubcommand2),0):(telemetry.trackCliSubcommandRemove(subcommandOriginal),rulesRemove(client,args));case"move":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesMoveSubcommand),0):(telemetry.trackCliSubcommandMove(subcommandOriginal),rulesMove(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG14)),output_manager_default.print(help(rulesSubcommand2,{parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsTargetsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandAdd(actual){this.trackCliSubcommand({subcommand:"add",value:actual})}trackCliSubcommandRemove(actual){this.trackCliSubcommand({subcommand:"rm",value:actual})}},FlagsTargetsCommandTelemetryClient=class extends FlagsRulesCommandTelemetryClient{trackCliArgumentTarget(targets2){targets2?.length&&this.trackCliArgument({arg:"target",value:this.redactedValue})}};var import_chalk89=__toESM(require_source(),1),import_pluralize9=__toESM(require_pluralize(),1);function formatFlagTargetSelector(target){return`${target.entity}.${target.attribute}=${target.value}`}function parseFlagTargetInput(input,options={}){let separatorIndex=input.indexOf("=");if(separatorIndex===-1)throw new Error(`Invalid target "${input}". Use ENTITY.ATTRIBUTE=VALUE, for example user.id=user_123.`);let{kind:entity,attribute}=parseEntityAttributeSelector(input.slice(0,separatorIndex)),rawValue=input.slice(separatorIndex+1);if(!options.allowLabel){if(!rawValue)throw new Error(`Invalid target "${input}". Value cannot be empty.`);return{entity,attribute,value:rawValue}}let labelIndex=rawValue.indexOf("|"),value=(labelIndex===-1?rawValue:rawValue.slice(0,labelIndex)).trim();if(!value)throw new Error(`Invalid target "${input}". Value cannot be empty.`);if(labelIndex===-1)return{entity,attribute,value};let label=rawValue.slice(labelIndex+1).trim();if(!label)throw new Error(`Invalid target "${input}". Label cannot be empty; use ENTITY.ATTRIBUTE=VALUE|LABEL or omit the "|".`);return validateLabelString(label,"label"),{entity,attribute,value,label}}function parseFlagTargetInputs(inputs,settings){let seen=new Map;for(let input of inputs){let target=parseFlagTargetInput(input,{allowLabel:!0});assertTargetableAttribute(target,settings);let key=formatFlagTargetSelector(target),existing=seen.get(key);existing?target.label&&(existing.label=target.label):seen.set(key,target)}return[...seen.values()]}function assertTargetableAttribute(target,settings){let entity=settings.entities.find(candidate=>candidate.kind===target.entity);if(!entity){let available=settings.entities.map(candidate=>candidate.kind);throw new Error(available.length>0?`Entity "${target.entity}" does not exist. Available entities: ${available.join(", ")}.`:`Entity "${target.entity}" does not exist. Define entities before adding targets.`)}let attribute=entity.attributes.find(candidate=>candidate.key===target.attribute);if(!attribute){let available=entity.attributes.map(candidate=>`${entity.kind}.${candidate.key}`);throw new Error(available.length>0?`Attribute "${target.entity}.${target.attribute}" does not exist. Available attributes: ${available.join(", ")}.`:`Attribute "${target.entity}.${target.attribute}" does not exist.`)}if(attribute.type!=="string")throw new Error(`Only string attributes can be targeted directly. ${target.entity}.${target.attribute} is a ${attribute.type} attribute.`)}function listFlagTargets(targets2){let entries=[];for(let[variantId,entities2]of Object.entries(targets2??{}))for(let[entity,attributes]of Object.entries(entities2))for(let[attribute,values]of Object.entries(attributes))for(let item of values)entries.push({variantId,entity,attribute,value:item.value,...item.note?{note:item.note}:{}});return entries}function findFlagTargetVariantId(targets2,target){for(let[variantId,entities2]of Object.entries(targets2??{}))if(entities2[target.entity]?.[target.attribute]?.some(item=>item.value===target.value))return variantId}function addFlagTargets(targets2,selectors,variantId){let next=structuredClone(targets2??{}),results=[];for(let selector of selectors){let previousVariantId=findFlagTargetVariantId(next,selector);if(previousVariantId===variantId){results.push({...selector,status:"unchanged"});continue}let previous=previousVariantId?deleteTargetValue(next,previousVariantId,selector):void 0,entities2=next[variantId]??={},attributes=entities2[selector.entity]??={};(attributes[selector.attribute]??=[]).push(previous?.note?{value:selector.value,note:previous.note}:{value:selector.value}),results.push(previousVariantId?{...selector,status:"moved",previousVariantId}:{...selector,status:"added"})}return{targets:next,results}}function removeFlagTargets(targets2,selectors){let next=structuredClone(targets2??{}),results=[],seen=new Set;for(let selector of selectors){let key=formatFlagTargetSelector(selector);if(seen.has(key))continue;seen.add(key);let variantId=findFlagTargetVariantId(next,selector);if(!variantId)throw new Error(`Target "${formatFlagTargetSelector(selector)}" does not exist.`);deleteTargetValue(next,variantId,selector),results.push({...selector,variantId})}return{targets:next,results}}function deleteTargetValue(targets2,variantId,selector){let entities2=targets2[variantId],attributes=entities2?.[selector.entity],values=attributes?.[selector.attribute];if(!entities2||!attributes||!values)return;let removed=values.find(item=>item.value===selector.value),remaining=values.filter(item=>item.value!==selector.value);return remaining.length>0?(attributes[selector.attribute]=remaining,removed):(delete attributes[selector.attribute],Object.keys(attributes).length===0&&delete entities2[selector.entity],Object.keys(entities2).length===0&&delete targets2[variantId],removed)}function buildTargetsEnvironmentConfig(flag,environment,targets2){return{...flag.environments[environment],targets:targets2}}var import_chalk88=__toESM(require_source(),1);function formatTargetValue2(target,settings){let label=target.label??resolveTargetingLabel(settings,target.entity,target.attribute,target.value),selector=formatFlagTargetSelector(target);return label?`${selector} ${import_chalk88.default.gray(label)}`:selector}function formatTargetVariant(flag,variantId){let variant=flag.variants.find(candidate=>candidate.id===variantId);return formatFlagVariantSummary(variant,variantId)}async function targetsLs(client,argv){let telemetryClient=new FlagsTargetsCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(targetsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],json=flags["--json"];if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliFlagJson(json),telemetryClient.trackCliOptionProject(flags["--project"]),!flagArg)return output_manager_default.error("Please provide a flag slug or ID to list targets for"),output_manager_default.log(`Example: ${getCommandName("flags targets list my-feature --environment production")}`),2;if(json&&!environment)return output_manager_default.error("Missing required option --environment when using --json"),output_manager_default.log(`Example: ${getCommandName("flags targets list my-feature --environment production --json")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:flags["--project"],flagArg,environment,promptMessage:"Select an environment to list targets for:",fetchSettings:!json});if(isExitCodeResult2(context))return context.exitCode;let{envConfig}=context,targets2=envConfig.targets??{};if(json)return client.stdout.write(`${JSON.stringify({flag:context.flag.slug,environment:context.environment,active:envConfig.active,...envConfig.reuse?{reuse:envConfig.reuse}:{},targets:targets2},null,2)}
|
|
361
|
+
`)}var import_chalk84=__toESM(require_source(),1);async function rulesAdd(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesAddSubcommand2.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],conditionInputs=flags["--condition"]??[],variantSelector=normalizeOptionalInput(flags["--variant"]),baseSelector=normalizeOptionalInput(flags["--by"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),weightInputs=flags["--weight"]??[],rollFromVariantSelector=normalizeOptionalInput(flags["--from-variant"]),rollToVariantSelector=normalizeOptionalInput(flags["--to-variant"]),stageInputs=(flags["--stage"]??[]).map(input=>input.trim()),finalPercentage=flags["--final-percentage"],start=normalizeOptionalInput(flags["--start"]),position=flags["--position"],message=normalizeOptionalInput(flags["--message"]);telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionCondition(conditionInputs),telemetryClient.trackCliOptionVariant(variantSelector),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionWeight(weightInputs),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionFromVariant(rollFromVariantSelector),telemetryClient.trackCliOptionToVariant(rollToVariantSelector),telemetryClient.trackCliOptionStage(stageInputs),telemetryClient.trackCliOptionFinalPercentage(finalPercentage),telemetryClient.trackCliOptionStart(start),telemetryClient.trackCliOptionPosition(position),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]);let outcomeOptions={variantSelector,baseSelector,defaultVariantSelector,weightInputs,rollFromVariantSelector,rollToVariantSelector,stageInputs,finalPercentage,start};if(!flagArg)return output_manager_default.error("Please provide a flag slug or ID to add a rule to"),output_manager_default.log(`Example: ${getCommandName("flags rules add my-feature --environment production --condition user.plan:eq:pro --variant on")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment to add the rule to:",fetchSettings:needsFlagRuleOutcomeSettings(outcomeOptions)||conditionInputs.length>0});if(isExitCodeResult2(context))return context.exitCode;let conditions=parseFlagRuleConditions(conditionInputs,context.settings),outcome=resolveFlagRuleOutcome(context.flag,context.settings,{...outcomeOptions,requireOutcome:!0}),rule=createFlagRule(conditions,outcome),envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),nextEnvConfig=addFlagRule(envConfig,rule,position),nextPosition=nextEnvConfig.rules.findIndex(candidate=>candidate.id===rule.id)+1,updateMessage=await resolveFlagUpdateMessage(client,message,`Add rule ${rule.id} to ${context.environment}`);output_manager_default.spinner(`Adding rule to ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner(),output_manager_default.success(`Rule ${import_chalk84.default.bold(rule.id)} added to ${import_chalk84.default.bold(context.flag.slug)} in ${import_chalk84.default.bold(context.environment)}`),output_manager_default.log(` ${import_chalk84.default.dim("Position:")} ${nextPosition}`),output_manager_default.log(` ${import_chalk84.default.dim("Outcome:")} ${formatFlagRuleOutcome(rule.outcome,context.flag.variants)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk85=__toESM(require_source(),1),import_fast_deep_equal8=__toESM(require_fast_deep_equal(),1);async function rulesUpdate(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesUpdateSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,ruleId]=args,environment=flags["--environment"],conditionInputs=flags["--condition"]??[],variantSelector=normalizeOptionalInput(flags["--variant"]),baseSelector=normalizeOptionalInput(flags["--by"]),defaultVariantSelector=normalizeOptionalInput(flags["--default-variant"]),weightInputs=flags["--weight"]??[],rollFromVariantSelector=normalizeOptionalInput(flags["--from-variant"]),rollToVariantSelector=normalizeOptionalInput(flags["--to-variant"]),stageInputs=(flags["--stage"]??[]).map(input=>input.trim()),finalPercentage=flags["--final-percentage"],start=normalizeOptionalInput(flags["--start"]),message=normalizeOptionalInput(flags["--message"]);telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliArgumentRule(ruleId),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionCondition(conditionInputs),telemetryClient.trackCliOptionVariant(variantSelector),telemetryClient.trackCliOptionBy(baseSelector),telemetryClient.trackCliOptionWeight(weightInputs),telemetryClient.trackCliOptionDefaultVariant(defaultVariantSelector),telemetryClient.trackCliOptionFromVariant(rollFromVariantSelector),telemetryClient.trackCliOptionToVariant(rollToVariantSelector),telemetryClient.trackCliOptionStage(stageInputs),telemetryClient.trackCliOptionFinalPercentage(finalPercentage),telemetryClient.trackCliOptionStart(start),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]);let outcomeOptions={variantSelector,baseSelector,defaultVariantSelector,weightInputs,rollFromVariantSelector,rollToVariantSelector,stageInputs,finalPercentage,start};if(!flagArg||!ruleId)return output_manager_default.error("Please provide a flag slug or ID and rule ID to update"),output_manager_default.log(`Example: ${getCommandName("flags rules update my-feature rule_123 --environment production --variant on")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment containing the rule:",fetchSettings:needsFlagRuleOutcomeSettings(outcomeOptions)||conditionInputs.length>0});if(isExitCodeResult2(context))return context.exitCode;let envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),currentRule=findFlagRule(envConfig.rules??[],ruleId),hasOutcomeOptions=hasFlagRuleOutcomeOptions(outcomeOptions),nextConditions=conditionInputs.length>0?parseFlagRuleConditions(conditionInputs,context.settings):void 0,resolvedOutcome=hasOutcomeOptions?resolveFlagRuleOutcome(context.flag,context.settings,{...outcomeOptions,currentOutcome:currentRule.outcome}):void 0;if(!nextConditions&&!resolvedOutcome)return output_manager_default.warn("No rule changes were provided"),0;let nextEnvConfig=updateFlagRule(envConfig,ruleId,{conditions:nextConditions,outcome:resolvedOutcome});if((0,import_fast_deep_equal8.default)(context.envConfig,nextEnvConfig))return output_manager_default.warn("No rule changes were provided"),0;let updateMessage=await resolveFlagUpdateMessage(client,message,`Update rule ${ruleId} in ${context.environment}`);output_manager_default.spinner(`Updating rule in ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner();let nextRule=findFlagRule(nextEnvConfig.rules,ruleId);output_manager_default.success(`Rule ${import_chalk85.default.bold(ruleId)} updated for ${import_chalk85.default.bold(context.flag.slug)} in ${import_chalk85.default.bold(context.environment)}`),output_manager_default.log(` ${import_chalk85.default.dim("Conditions:")} ${nextRule.conditions.map(condition=>formatFlagRuleCondition(condition,context.settings)).join(", ")}`),output_manager_default.log(` ${import_chalk85.default.dim("Outcome:")} ${formatFlagRuleOutcome(nextRule.outcome,context.flag.variants)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk86=__toESM(require_source(),1);async function rulesRemove(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesRemoveSubcommand2.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,ruleId]=args,environment=flags["--environment"],message=normalizeOptionalInput(flags["--message"]);if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliArgumentRule(ruleId),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]),!flagArg||!ruleId)return output_manager_default.error("Please provide a flag slug or ID and rule ID to remove"),output_manager_default.log(`Example: ${getCommandName("flags rules remove my-feature rule_123 --environment production")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment containing the rule:"});if(isExitCodeResult2(context))return context.exitCode;let envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),nextEnvConfig=removeFlagRule(envConfig,ruleId),updateMessage=await resolveFlagUpdateMessage(client,message,`Remove rule ${ruleId} from ${context.environment}`);output_manager_default.spinner(`Removing rule from ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner(),output_manager_default.success(`Rule ${import_chalk86.default.bold(ruleId)} removed from ${import_chalk86.default.bold(context.flag.slug)} in ${import_chalk86.default.bold(context.environment)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var import_chalk87=__toESM(require_source(),1),import_fast_deep_equal9=__toESM(require_fast_deep_equal(),1);async function rulesMove(client,argv){let telemetryClient=new FlagsRulesCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(rulesMoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,ruleId]=args,environment=flags["--environment"],position=flags["--position"],message=normalizeOptionalInput(flags["--message"]);if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliArgumentRule(ruleId),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionPosition(position),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliOptionProject(flags["--project"]),!flagArg||!ruleId||position===void 0)return output_manager_default.error("Please provide a flag slug or ID, rule ID, and destination position"),output_manager_default.log(`Example: ${getCommandName("flags rules move my-feature rule_123 --environment production --position 1")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:parsedArgs.flags["--project"],flagArg,environment,promptMessage:"Select an environment containing the rule:"});if(isExitCodeResult2(context))return context.exitCode;let envConfig=getFlagRulesEnvironmentConfig(context.flag,context.environment),nextEnvConfig=moveFlagRule(envConfig,ruleId,position);if((0,import_fast_deep_equal9.default)(context.envConfig,nextEnvConfig))return output_manager_default.warn(`Rule ${import_chalk87.default.bold(ruleId)} is already at position ${position} in ${context.environment}`),0;let updateMessage=await resolveFlagUpdateMessage(client,message,`Move rule ${ruleId} to position ${position} in ${context.environment}`);output_manager_default.spinner(`Moving rule in ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:nextEnvConfig},message:updateMessage});output_manager_default.stopSpinner(),output_manager_default.success(`Rule ${import_chalk87.default.bold(ruleId)} moved to position ${position} for ${import_chalk87.default.bold(context.flag.slug)} in ${import_chalk87.default.bold(context.environment)}`),warnIfRuleChangesAreBypassed(updatedFlag,context.environment)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG14={ls:getCommandAliases(rulesListSubcommand2),add:getCommandAliases(rulesAddSubcommand2),update:getCommandAliases(rulesUpdateSubcommand),rm:getCommandAliases(rulesRemoveSubcommand2),move:getCommandAliases(rulesMoveSubcommand)};async function rules(client){let telemetry=new FlagsRulesTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(rulesSubcommand2.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG14),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags rules",subcommand),output_manager_default.print(help(rulesSubcommand2,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:rulesSubcommand2,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesListSubcommand2),0):(telemetry.trackCliSubcommandList(subcommandOriginal),rulesLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesAddSubcommand2),0):(telemetry.trackCliSubcommandAdd(subcommandOriginal),rulesAdd(client,args));case"update":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesUpdateSubcommand),0):(telemetry.trackCliSubcommandUpdate(subcommandOriginal),rulesUpdate(client,args));case"rm":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesRemoveSubcommand2),0):(telemetry.trackCliSubcommandRemove(subcommandOriginal),rulesRemove(client,args));case"move":return needHelp?(telemetry.trackCliFlagHelp("flags rules",subcommandOriginal),printHelp(rulesMoveSubcommand),0):(telemetry.trackCliSubcommandMove(subcommandOriginal),rulesMove(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG14)),output_manager_default.print(help(rulesSubcommand2,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsTargetsTelemetryClient=class extends TelemetryClient{trackCliSubcommandList(actual){this.trackCliSubcommand({subcommand:"ls",value:actual})}trackCliSubcommandAdd(actual){this.trackCliSubcommand({subcommand:"add",value:actual})}trackCliSubcommandRemove(actual){this.trackCliSubcommand({subcommand:"rm",value:actual})}},FlagsTargetsCommandTelemetryClient=class extends FlagsRulesCommandTelemetryClient{trackCliArgumentTarget(targets2){targets2?.length&&this.trackCliArgument({arg:"target",value:this.redactedValue})}};var import_chalk89=__toESM(require_source(),1),import_pluralize9=__toESM(require_pluralize(),1);function formatFlagTargetSelector(target){return`${target.entity}.${target.attribute}=${target.value}`}function parseFlagTargetInput(input,options={}){let separatorIndex=input.indexOf("=");if(separatorIndex===-1)throw new Error(`Invalid target "${input}". Use ENTITY.ATTRIBUTE=VALUE, for example user.id=user_123.`);let{kind:entity,attribute}=parseEntityAttributeSelector(input.slice(0,separatorIndex)),rawValue=input.slice(separatorIndex+1);if(!options.allowLabel){if(!rawValue)throw new Error(`Invalid target "${input}". Value cannot be empty.`);return{entity,attribute,value:rawValue}}let labelIndex=rawValue.indexOf("|"),value=(labelIndex===-1?rawValue:rawValue.slice(0,labelIndex)).trim();if(!value)throw new Error(`Invalid target "${input}". Value cannot be empty.`);if(labelIndex===-1)return{entity,attribute,value};let label=rawValue.slice(labelIndex+1).trim();if(!label)throw new Error(`Invalid target "${input}". Label cannot be empty; use ENTITY.ATTRIBUTE=VALUE|LABEL or omit the "|".`);return validateLabelString(label,"label"),{entity,attribute,value,label}}function parseFlagTargetInputs(inputs,settings){let seen=new Map;for(let input of inputs){let target=parseFlagTargetInput(input,{allowLabel:!0});assertTargetableAttribute(target,settings);let key=formatFlagTargetSelector(target),existing=seen.get(key);existing?target.label&&(existing.label=target.label):seen.set(key,target)}return[...seen.values()]}function assertTargetableAttribute(target,settings){let entity=settings.entities.find(candidate=>candidate.kind===target.entity);if(!entity){let available=settings.entities.map(candidate=>candidate.kind);throw new Error(available.length>0?`Entity "${target.entity}" does not exist. Available entities: ${available.join(", ")}.`:`Entity "${target.entity}" does not exist. Define entities before adding targets.`)}let attribute=entity.attributes.find(candidate=>candidate.key===target.attribute);if(!attribute){let available=entity.attributes.map(candidate=>`${entity.kind}.${candidate.key}`);throw new Error(available.length>0?`Attribute "${target.entity}.${target.attribute}" does not exist. Available attributes: ${available.join(", ")}.`:`Attribute "${target.entity}.${target.attribute}" does not exist.`)}if(attribute.type!=="string")throw new Error(`Only string attributes can be targeted directly. ${target.entity}.${target.attribute} is a ${attribute.type} attribute.`)}function listFlagTargets(targets2){let entries=[];for(let[variantId,entities2]of Object.entries(targets2??{}))for(let[entity,attributes]of Object.entries(entities2))for(let[attribute,values]of Object.entries(attributes))for(let item of values)entries.push({variantId,entity,attribute,value:item.value,...item.note?{note:item.note}:{}});return entries}function findFlagTargetVariantId(targets2,target){for(let[variantId,entities2]of Object.entries(targets2??{}))if(entities2[target.entity]?.[target.attribute]?.some(item=>item.value===target.value))return variantId}function addFlagTargets(targets2,selectors,variantId){let next=structuredClone(targets2??{}),results=[];for(let selector of selectors){let previousVariantId=findFlagTargetVariantId(next,selector);if(previousVariantId===variantId){results.push({...selector,status:"unchanged"});continue}let previous=previousVariantId?deleteTargetValue(next,previousVariantId,selector):void 0,entities2=next[variantId]??={},attributes=entities2[selector.entity]??={};(attributes[selector.attribute]??=[]).push(previous?.note?{value:selector.value,note:previous.note}:{value:selector.value}),results.push(previousVariantId?{...selector,status:"moved",previousVariantId}:{...selector,status:"added"})}return{targets:next,results}}function removeFlagTargets(targets2,selectors){let next=structuredClone(targets2??{}),results=[],seen=new Set;for(let selector of selectors){let key=formatFlagTargetSelector(selector);if(seen.has(key))continue;seen.add(key);let variantId=findFlagTargetVariantId(next,selector);if(!variantId)throw new Error(`Target "${formatFlagTargetSelector(selector)}" does not exist.`);deleteTargetValue(next,variantId,selector),results.push({...selector,variantId})}return{targets:next,results}}function deleteTargetValue(targets2,variantId,selector){let entities2=targets2[variantId],attributes=entities2?.[selector.entity],values=attributes?.[selector.attribute];if(!entities2||!attributes||!values)return;let removed=values.find(item=>item.value===selector.value),remaining=values.filter(item=>item.value!==selector.value);return remaining.length>0?(attributes[selector.attribute]=remaining,removed):(delete attributes[selector.attribute],Object.keys(attributes).length===0&&delete entities2[selector.entity],Object.keys(entities2).length===0&&delete targets2[variantId],removed)}function buildTargetsEnvironmentConfig(flag,environment,targets2){return{...flag.environments[environment],targets:targets2}}var import_chalk88=__toESM(require_source(),1);function formatTargetValue2(target,settings){let label=target.label??resolveTargetingLabel(settings,target.entity,target.attribute,target.value),selector=formatFlagTargetSelector(target);return label?`${selector} ${import_chalk88.default.gray(label)}`:selector}function formatTargetVariant(flag,variantId){let variant=flag.variants.find(candidate=>candidate.id===variantId);return formatFlagVariantSummary(variant,variantId)}async function targetsLs(client,argv){let telemetryClient=new FlagsTargetsCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(targetsListSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg]=args,environment=flags["--environment"],json=flags["--json"];if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliFlagJson(json),telemetryClient.trackCliOptionProject(flags["--project"]),!flagArg)return output_manager_default.error("Please provide a flag slug or ID to list targets for"),output_manager_default.log(`Example: ${getCommandName("flags targets list my-feature --environment production")}`),2;if(json&&!environment)return output_manager_default.error("Missing required option --environment when using --json"),output_manager_default.log(`Example: ${getCommandName("flags targets list my-feature --environment production --json")}`),2;try{let context=await resolveRulesCommandContext(client,{projectName:flags["--project"],flagArg,environment,promptMessage:"Select an environment to list targets for:",fetchSettings:!json});if(isExitCodeResult2(context))return context.exitCode;let{envConfig}=context,targets2=envConfig.targets??{};if(json)return client.stdout.write(`${JSON.stringify({flag:context.flag.slug,environment:context.environment,active:envConfig.active,...envConfig.reuse?{reuse:envConfig.reuse}:{},targets:targets2},null,2)}
|
|
362
362
|
`),0;let entries=listFlagTargets(targets2),lsStamp=stamp_default(),inactiveMode=describeInactiveTargetingMode(context.flag,envConfig);if(entries.length===0){let projectFlag=flags["--project"]?` --project ${flags["--project"]}`:"";return output_manager_default.log(`No targets found for ${import_chalk89.default.bold(context.flag.slug)} in ${context.environment} ${import_chalk89.default.gray(lsStamp())}`),output_manager_default.log(`
|
|
363
363
|
Add one with: ${getCommandName(`flags targets add ${context.flag.slug} --environment ${context.environment} user.id=user_123${projectFlag}`)}`),0}output_manager_default.log(`${(0,import_pluralize9.default)("target",entries.length,!0)} found for ${import_chalk89.default.bold(context.flag.slug)} in ${context.environment} ${import_chalk89.default.gray(lsStamp())}`),printTargetsTable(entries,context.flag,context.settings),inactiveMode&&output_manager_default.print(`${import_chalk89.default.yellow("!")} ${import_chalk89.default.bold(context.environment)} ${inactiveMode}; these targets are not evaluated until targeting is active again.
|
|
364
364
|
`)}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function printTargetsTable(entries,flag,settings){let headers=["Attribute","Value","Label","Variant"],rows=entries.map(entry=>[`${entry.entity}.${entry.attribute}`,import_chalk89.default.bold(entry.value),resolveTargetingLabel(settings,entry.entity,entry.attribute,entry.value)??entry.note??"",formatTargetVariant(flag,entry.variantId)]),table2=formatTable(headers,["l","l","l","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
@@ -367,11 +367,11 @@ ${table2}
|
|
|
367
367
|
`),output_manager_default.print(` ${getCommandName(["flags labels set",quoteArg(`${error.entityKind}.${error.attributeKey}`),quoteArg(error.value),quoteArg(item&&"label"in item?item.label:"")].join(" "))}
|
|
368
368
|
`)}return 1}}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}function resolveTargetVariant(flag,variantSelector){if(variantSelector)return resolveVariantOrThrow(variantSelector,flag.variants,"--variant");if(flag.kind==="boolean")return getBooleanVariant(flag,!0);output_manager_default.error(`Missing required option --variant. Flag ${import_chalk90.default.bold(flag.slug)} is a ${flag.kind} flag, so choose which variant the targets receive.`),output_manager_default.log(`Example: ${getCommandName(`flags targets add ${flag.slug} --environment production --variant <VARIANT> user.id=user_123`)}`)}function buildLabelItems(selectors,settings){let items=selectors.filter(selector=>selector.label!==void 0&&selector.label!==resolveTargetingLabel(settings,selector.entity,selector.attribute,selector.value)).map(selector=>({operation:"upsert",entityKind:selector.entity,attributeKey:selector.attribute,value:selector.value,label:selector.label}));if(items.length>MAX_LABEL_OPERATIONS)throw new Error(`Cannot set more than ${MAX_LABEL_OPERATIONS} labels at once. Split the targets into smaller batches.`);return items}async function saveLabels(client,projectId,items){if(items.length!==0){output_manager_default.spinner("Saving labels...");try{return await updateEntityLabelsBulk(client,projectId,items)}catch(err){let message=err instanceof Error?err.message:String(err);return{labels:[],errors:items.map(item=>({entityKind:item.entityKind,attributeKey:item.attributeKey,value:item.value,code:isAPIError(err)?err.code??"api_error":"error",message}))}}finally{output_manager_default.stopSpinner()}}}function writeJson(client,flag,environment,targets2,labels2){client.stdout.write(`${JSON.stringify({flag,environment,targets:targets2,...labels2?{labels:labels2}:{}},null,2)}
|
|
369
369
|
`)}var import_chalk91=__toESM(require_source(),1),import_pluralize11=__toESM(require_pluralize(),1);var EXAMPLE2="flags targets remove my-feature --environment production user.id=user_123";async function targetsRemove(client,argv){let telemetryClient=new FlagsTargetsCommandTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(targetsRemoveSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,[flagArg,...targetInputs]=args,environment=flags["--environment"],message=normalizeOptionalInput(flags["--message"]),json=flags["--json"];if(telemetryClient.trackCliArgumentFlag(flagArg),telemetryClient.trackCliArgumentTarget(targetInputs),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliOptionMessage(message),telemetryClient.trackCliFlagJson(json),telemetryClient.trackCliOptionProject(flags["--project"]),!flagArg||targetInputs.length===0)return output_manager_default.error("Please provide a flag slug or ID and at least one target as ENTITY.ATTRIBUTE=VALUE"),output_manager_default.log(`Example: ${getCommandName(EXAMPLE2)}`),2;if(json&&!environment)return output_manager_default.error("Missing required option --environment when using --json"),output_manager_default.log(`Example: ${getCommandName(`${EXAMPLE2} --json`)}`),2;try{let selectors=targetInputs.map(input=>parseFlagTargetInput(input)),context=await resolveRulesCommandContext(client,{projectName:flags["--project"],flagArg,environment,promptMessage:"Select an environment to remove targets from:",fetchSettings:!json});if(isExitCodeResult2(context))return context.exitCode;let{targets:targets2,results}=removeFlagTargets(context.envConfig.targets,selectors),defaultMessage=`Remove ${(0,import_pluralize11.default)("target",results.length,!0)} from ${context.environment}`,updateMessage=json?message??defaultMessage:await resolveFlagUpdateMessage(client,message,defaultMessage);output_manager_default.spinner(`Removing targets from ${context.environment}...`);let updatedFlag=await updateFlag(client,context.projectId,flagArg,{environments:{[context.environment]:buildTargetsEnvironmentConfig(context.flag,context.environment,targets2)},message:updateMessage});if(output_manager_default.stopSpinner(),json)return client.stdout.write(`${JSON.stringify({flag:updatedFlag.slug,environment:context.environment,targets:updatedFlag.environments[context.environment]?.targets??targets2},null,2)}
|
|
370
|
-
`),0;output_manager_default.success(`${(0,import_pluralize11.default)("target",results.length,!0)} removed from ${import_chalk91.default.bold(context.flag.slug)} in ${import_chalk91.default.bold(context.environment)}`);for(let result of results)output_manager_default.log(` ${formatTargetValue2(result,context.settings)} ${import_chalk91.default.dim("(was")} ${formatTargetVariant(context.flag,result.variantId)}${import_chalk91.default.dim(")")}`);warnIfRuleChangesAreBypassed(updatedFlag,context.environment,"target")}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG15={ls:getCommandAliases(targetsListSubcommand),add:getCommandAliases(targetsAddSubcommand),rm:getCommandAliases(targetsRemoveSubcommand)};async function targets(client){let telemetry=new FlagsTargetsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(targetsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG15),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags targets",subcommand),output_manager_default.print(help(targetsSubcommand,{parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{parent:targetsSubcommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags targets",subcommandOriginal),printHelp(targetsListSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),targetsLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags targets",subcommandOriginal),printHelp(targetsAddSubcommand),0):(telemetry.trackCliSubcommandAdd(subcommandOriginal),targetsAdd(client,args));case"rm":return needHelp?(telemetry.trackCliFlagHelp("flags targets",subcommandOriginal),printHelp(targetsRemoveSubcommand),0):(telemetry.trackCliSubcommandRemove(subcommandOriginal),targetsRemove(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG15)),output_manager_default.print(help(targetsSubcommand,{parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsTargetingTelemetryClient=class extends TelemetryClient{trackCliSubcommandEnable(actual){this.trackCliSubcommand({subcommand:"enable",value:actual})}};var COMMAND_CONFIG16={enable:getCommandAliases(targetingEnableSubcommand)};async function targeting(client,args){let telemetry=new FlagsTargetingTelemetryClient({opts:{store:client.telemetryEventStore}}),{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(args,COMMAND_CONFIG16);switch(subcommand){case"enable":return telemetry.trackCliSubcommandEnable(subcommandOriginal),useTargeting(client,subArgs);default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG16)),output_manager_default.print(help(targetingSubcommand,{parent:flagsCommand,columns:client.stderr.columns})),2}}var import_env=__toESM(require_dist(),1);init_dist();async function emitDatafiles(client){try{parseArguments(client.argv.slice(4),getFlagsSpecification(prepareSubcommand.options))}catch(err){return printError(err),2}try{let localEnv={};try{localEnv=(0,import_env.loadEnvConfig)(client.cwd,!0).combinedEnv}catch(err){output_manager_default.debug(`Failed to load local env files: ${err}`)}return await prepareFlagsDefinitions({cwd:client.cwd,env:{...localEnv,...process.env},userAgentSuffix:ua_default,output:output_manager_default}),0}catch(err){return printError(err),1}}var import_env2=__toESM(require_dist(),1);async function override(client,argv){let parsedArgs,flagsSpecification=getFlagsSpecification(overrideSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,decryptToken=flags["--decrypt"];return decryptToken?handleDecrypt(client,decryptToken):handleEncrypt(client,args,flags)}async function handleEncrypt(client,args,flags){let expiration=flags["--expiration"]??"1y";if(args.length===0)return output_manager_default.error(`Please provide at least one flag override as flag=value.
|
|
370
|
+
`),0;output_manager_default.success(`${(0,import_pluralize11.default)("target",results.length,!0)} removed from ${import_chalk91.default.bold(context.flag.slug)} in ${import_chalk91.default.bold(context.environment)}`);for(let result of results)output_manager_default.log(` ${formatTargetValue2(result,context.settings)} ${import_chalk91.default.dim("(was")} ${formatTargetVariant(context.flag,result.variantId)}${import_chalk91.default.dim(")")}`);warnIfRuleChangesAreBypassed(updatedFlag,context.environment,"target")}catch(err){return output_manager_default.stopSpinner(),printError(err),1}return 0}var COMMAND_CONFIG15={ls:getCommandAliases(targetsListSubcommand),add:getCommandAliases(targetsAddSubcommand),rm:getCommandAliases(targetsRemoveSubcommand)};async function targets(client){let telemetry=new FlagsTargetsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(targetsSubcommand.options),parsedArgs;try{parsedArgs=parseArguments(client.argv.slice(4),flagsSpecification,{permissive:!0})}catch(err){return printError(err),2}let{subcommand,args,subcommandOriginal}=getSubcommand(parsedArgs.args,COMMAND_CONFIG15),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags targets",subcommand),output_manager_default.print(help(targetsSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:targetsSubcommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags targets",subcommandOriginal),printHelp(targetsListSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),targetsLs(client,args));case"add":return needHelp?(telemetry.trackCliFlagHelp("flags targets",subcommandOriginal),printHelp(targetsAddSubcommand),0):(telemetry.trackCliSubcommandAdd(subcommandOriginal),targetsAdd(client,args));case"rm":return needHelp?(telemetry.trackCliFlagHelp("flags targets",subcommandOriginal),printHelp(targetsRemoveSubcommand),0):(telemetry.trackCliSubcommandRemove(subcommandOriginal),targetsRemove(client,args));default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG15)),output_manager_default.print(help(targetsSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),2}}var FlagsTargetingTelemetryClient=class extends TelemetryClient{trackCliSubcommandEnable(actual){this.trackCliSubcommand({subcommand:"enable",value:actual})}};var COMMAND_CONFIG16={enable:getCommandAliases(targetingEnableSubcommand)};async function targeting(client,args){let telemetry=new FlagsTargetingTelemetryClient({opts:{store:client.telemetryEventStore}}),{subcommand,args:subArgs,subcommandOriginal}=getSubcommand(args,COMMAND_CONFIG16);switch(subcommand){case"enable":return telemetry.trackCliSubcommandEnable(subcommandOriginal),useTargeting(client,subArgs);default:return output_manager_default.error(getInvalidSubcommand(COMMAND_CONFIG16)),output_manager_default.print(help(targetingSubcommand,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns})),2}}var import_env=__toESM(require_dist(),1);init_dist();async function emitDatafiles(client){try{parseArguments(client.argv.slice(4),getFlagsSpecification(prepareSubcommand.options))}catch(err){return printError(err),2}try{let localEnv={};try{localEnv=(0,import_env.loadEnvConfig)(client.cwd,!0).combinedEnv}catch(err){output_manager_default.debug(`Failed to load local env files: ${err}`)}return await prepareFlagsDefinitions({cwd:client.cwd,env:{...localEnv,...process.env},userAgentSuffix:ua_default,output:output_manager_default}),0}catch(err){return printError(err),1}}var import_env2=__toESM(require_dist(),1);async function override(client,argv){let parsedArgs,flagsSpecification=getFlagsSpecification(overrideSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,decryptToken=flags["--decrypt"];return decryptToken?handleDecrypt(client,decryptToken):handleEncrypt(client,args,flags)}async function handleEncrypt(client,args,flags){let expiration=flags["--expiration"]??"1y";if(args.length===0)return output_manager_default.error(`Please provide at least one flag override as flag=value.
|
|
371
371
|
Example: vercel flags override my-flag=true`),2;let overrides={};for(let arg of args){let eqIndex=arg.indexOf("=");if(eqIndex===-1)return output_manager_default.error(`Invalid override format: "${arg}". Expected flag=value.`),1;let key=arg.slice(0,eqIndex),rawValue=arg.slice(eqIndex+1);overrides[key]=parseValue(rawValue)}let secret=resolveSecret(client);if(!secret)return output_manager_default.error("FLAGS_SECRET not found. Set it in the environment, .env.local, or .env file."),1;try{let encrypted=await encryptOverrides(overrides,secret,expiration);return client.stdout.write(encrypted+`
|
|
372
372
|
`),0}catch(err){return printError(err),1}}async function handleDecrypt(client,token){let secret=resolveSecret(client);if(!secret)return output_manager_default.error("FLAGS_SECRET not found. Set it in the environment, .env.local, or .env file."),1;try{let overrides=await decryptOverrides(token,secret);return overrides===void 0?(output_manager_default.error("Invalid token: not a valid flag overrides token."),2):(client.stdout.write(JSON.stringify(overrides,null,2)+`
|
|
373
373
|
`),0)}catch(err){return printError(err),1}}function parseValue(raw){if(raw==="true")return!0;if(raw==="false")return!1;let num=Number(raw);return!Number.isNaN(num)&&raw.trim()!==""?num:raw}function resolveSecret(client){let{combinedEnv}=(0,import_env2.loadEnvConfig)(client.cwd,!0);return combinedEnv.FLAGS_SECRET}async function encryptOverrides(overrides,secret,expirationTime){let encodedSecret=base64url_exports.decode(secret);if(encodedSecret.length!==32)throw new Error("Invalid FLAGS_SECRET: must be a 256-bit base64url-encoded key (32 bytes).");return new EncryptJWT({o:overrides,pur:"overrides"}).setExpirationTime(expirationTime).setProtectedHeader({alg:"dir",enc:"A256GCM"}).encrypt(encodedSecret)}async function decryptOverrides(encryptedData,secret){let encodedSecret=base64url_exports.decode(secret);if(encodedSecret.length!==32)throw new Error("Invalid FLAGS_SECRET: must be a 256-bit base64url-encoded key (32 bytes).");let{payload}=await jwtDecrypt(encryptedData,encodedSecret);if(!(payload.pur!=="overrides"||!payload.o))return payload.o}var import_chalk92=__toESM(require_source(),1),import_ms7=__toESM(require_ms(),1),import_pluralize12=__toESM(require_pluralize(),1);var MAX_LISTED_VARIANTS=3,MAX_VARIANT_LENGTH=30;function isPackedDatafile(data){return typeof data=="object"&&data!==null&&typeof data.definitions=="object"&&data.definitions!==null}function printDatafileSummary(datafile2,{projectLabel,environment,jsonCommand}){let envName=datafile2.environment??environment,slugs=Object.keys(datafile2.definitions).sort(),segmentCount=Object.keys(datafile2.segments??{}).length,source=[envName?`the ${envName} datafile`:"the datafile",projectLabel??datafile2.projectId].filter(Boolean).join(" for "),details=[datafile2.revision!==void 0?`revision ${datafile2.revision}`:null,datafile2.configUpdatedAt!==void 0?`updated ${(0,import_ms7.default)(Math.max(0,Date.now()-datafile2.configUpdatedAt))} ago`:null].filter(Boolean),detailsSuffix=details.length>0?` ${import_chalk92.default.gray(`(${details.join(", ")})`)}`:"",segmentsSuffix=segmentCount>0?` and ${(0,import_pluralize12.default)("segment",segmentCount,!0)}`:"";if(slugs.length===0)output_manager_default.log(`No feature flags in ${source}${detailsSuffix}`);else{output_manager_default.log(`${(0,import_pluralize12.default)("feature flag",slugs.length,!0)}${segmentsSuffix} in ${source}${detailsSuffix}`);let rows=slugs.map(slug=>formatFlagRow(slug,datafile2.definitions[slug],envName)),table2=formatTable(["Name","Serves","Rules","Targets","Reuses"],["l","l","r","r","l"],[{name:"",rows}]);output_manager_default.print(`
|
|
374
374
|
${table2}
|
|
375
375
|
`)}output_manager_default.log(`To see the full datafile including rules, run ${jsonCommand}`)}function formatFlagRow(slug,definition,envName){let{config,reusedEnvironment}=resolveEnvironmentConfig(definition,envName),reuses=reusedEnvironment??"";return config===void 0||typeof config=="object"&&"reuse"in config?[import_chalk92.default.bold(slug),import_chalk92.default.gray("unknown"),"","",reuses]:typeof config=="number"?[import_chalk92.default.bold(slug),formatServes(definition,new Set([config])),"","",reuses]:[import_chalk92.default.bold(slug),formatServes(definition,collectServedVariants(definition,config)),String(config.rules?.length??0),String(countTargets(config.targets)),reuses]}function resolveEnvironmentConfig(definition,envName){let environments=definition.environments??{},name=envName??Object.keys(environments)[0],config=name!==void 0?environments[name]:void 0,reusedEnvironment,visited=new Set([name]);for(;typeof config=="object"&&config!==null&&"reuse"in config;){if(reusedEnvironment??=config.reuse,visited.has(config.reuse))return{config:void 0,reusedEnvironment};visited.add(config.reuse),config=environments[config.reuse]}return{config,reusedEnvironment}}function collectServedVariants(definition,config){let served=new Set,addOutcome=outcome=>{if(typeof outcome=="number"){served.add(outcome);return}switch(outcome?.type){case"split":outcome.weights.forEach((weight,index)=>{weight>0&&served.add(index)}),served.add(outcome.defaultVariant);return;case"rollout":served.add(outcome.rollFromVariant),served.add(outcome.rollToVariant),served.add(outcome.defaultVariant);return;case"experiment":if(definition.experiment){addOutcome({type:"split",...definition.experiment});return}break}definition.variants.forEach((_,index)=>served.add(index))};addOutcome(config.fallthrough);for(let rule of config.rules??[])addOutcome(rule?.outcome);return config.targets?.forEach((targetList,index)=>{countTargets([targetList])>0&&served.add(index)}),served}function formatServes(definition,served){let values=[...served].sort((a,b)=>a-b).map(index=>definition.variants[index]);return values.length===1?values[0]===void 0?import_chalk92.default.gray("unknown"):truncateEnd(formatVariantValue(values[0]),MAX_VARIANT_LENGTH,{omission:"\u2026"}):values.length<=MAX_LISTED_VARIANTS&&values.every(value=>typeof value=="boolean"||typeof value=="number")?values.map(value=>formatVariantValue(value)).join(", "):(0,import_pluralize12.default)("variant",values.length,!0)}function countTargets(targets2){let count=0;for(let targetList of targets2??[])for(let attributes of Object.values(targetList))for(let values of Object.values(attributes))count+=Array.isArray(values)?values.length:0;return count}var FlagsDatafileTelemetryClient=class extends TelemetryClient{trackCliFlagJson(json){json&&this.trackCliFlag("json")}trackCliOptionProject(project){project&&this.trackCliOption({option:"project",value:this.redactedValue})}trackCliOptionEnvironment(environment){environment&&this.trackCliOption({option:"environment",value:environment})}trackCliFlagSdkKey(sdkKey){sdkKey&&this.trackCliFlag("sdk-key")}};var DATAFILE_URL="https://flags.vercel.com/v1/datafile",ENVIRONMENTS=["production","preview","development"],MAX_SDK_KEY_BYTES=4096,SDK_KEY_FORMAT=/^vf_(?:server|client)_[\x21-\x7E]+$/;function commandName(json,subcommands){return json?getCommandNamePlain(subcommands):getCommandName(subcommands)}function sdkKeyInputHint(json){return`Pipe it to stdin instead, for example ${commandName(json,"flags datafile --sdk-key < sdk-key.txt")}.`}async function datafile(client,argv){let telemetryClient=new FlagsDatafileTelemetryClient({opts:{store:client.telemetryEventStore}}),parsedArgs,flagsSpecification=getFlagsSpecification(datafileSubcommand.options);try{parsedArgs=parseArguments(argv,flagsSpecification)}catch(err){return printError(err),2}let{args,flags}=parsedArgs,projectName=getProjectNameFromFlags(flags),environment=flags["--environment"],useSdkKey=!!flags["--sdk-key"],json=!!flags["--json"];if(telemetryClient.trackCliOptionProject(projectName),telemetryClient.trackCliOptionEnvironment(environment),telemetryClient.trackCliFlagSdkKey(useSdkKey),telemetryClient.trackCliFlagJson(json),argv.some(arg=>arg.startsWith("--sdk-key="))||args.some(arg=>SDK_KEY_PATTERN.test(arg)))return outputError(client,json,"INVALID_ARGUMENTS",`SDK keys can't be passed as arguments. ${sdkKeyInputHint(json)}`);if(args.length>0)return outputError(client,json,"INVALID_ARGUMENTS",`${commandName(json,"flags datafile")} doesn't take arguments.`);if(environment!==void 0&&!ENVIRONMENTS.includes(environment))return outputError(client,json,"INVALID_ARGUMENTS",`Invalid environment "${environment}". Must be one of: ${ENVIRONMENTS.join(", ")}.`);if(useSdkKey){if(environment)return outputError(client,json,"MUTUAL_EXCLUSIVITY","The --environment option cannot be used with --sdk-key, as SDK keys are already bound to an environment.");if(projectName)return outputError(client,json,"MUTUAL_EXCLUSIVITY","The --project option cannot be used with --sdk-key, as SDK keys are already bound to a project.");let sdkKey=await readSdkKey(client,json);return typeof sdkKey=="number"?sdkKey:(json||output_manager_default.spinner("Fetching datafile"),fetchAndPrintDatafile(client,json,sdkKey,{},"Bearer",{jsonCommand:getJsonCommand(["--sdk-key"])}))}let link=await getLinkedFlagsProject(client,projectName);if(link.status==="error")return link.exitCode;if(link.status==="not_linked")return outputError(client,json,"NOT_LINKED",`Your codebase isn't linked to a project on Vercel. Pass --project <name>, or run ${commandName(json,"link")} to link it.`);let{project,org}=link;json||output_manager_default.spinner(`Fetching ${environment?`${environment} `:""}datafile for ${formatProject(org.slug,project.name)}`);let token,authScheme="Bearer",targetEnvironment=environment??"development",headers={"x-vercel-flags-project-id":project.id};try{let oidcToken=targetEnvironment==="development"?await getDevelopmentOidcToken(client,project.id,org.id):void 0;if(oidcToken)token=oidcToken;else{if(await client.ensureAuthorized(),!client.authConfig.token)return output_manager_default.stopSpinner(),outputError(client,json,"NOT_AUTHORIZED",`No user token is available. Run ${commandName(json,"login")} and retry the datafile command.`);token=client.authConfig.token,authScheme="VercelUser",headers["x-vercel-flags-team-id"]=org.id,headers["x-vercel-env"]=targetEnvironment}}catch(err){return output_manager_default.stopSpinner(),printUnexpectedError(client,json,err)}return fetchAndPrintDatafile(client,json,token,headers,authScheme,{projectLabel:formatProject(org.slug,project.name),environment:targetEnvironment,jsonCommand:getJsonCommand([...projectName?["--project",quoteArg(projectName)]:[],...environment?["--environment",environment]:[]])})}function getJsonCommand(args){return getCommandName(["flags datafile",...args,"--json"].join(" "))}async function readSdkKey(client,json){let sdkKey;if(!client.stdin.isTTY)sdkKey=(await readStdinText(client.stdin,MAX_SDK_KEY_BYTES)).trim();else if(!client.nonInteractive&&!json)sdkKey=(await client.input.password({message:"SDK key",mask:!0,validate:value=>value.trim().length>0?!0:"Enter an SDK key."})).trim();else return missingSdkKey(client,json,"Missing SDK key.");return sdkKey?SDK_KEY_PATTERN.test(sdkKey)?SDK_KEY_FORMAT.test(sdkKey)?sdkKey:outputError(client,json,"INVALID_ARGUMENTS","The SDK key can't contain spaces, line breaks, or other control characters."):outputError(client,json,"INVALID_ARGUMENTS","The SDK key must start with vf_server_ or vf_client_."):missingSdkKey(client,json,"No SDK key was read from stdin.")}function missingSdkKey(client,json,problem){let reason=AGENT_REASON.MISSING_KEY,machine=json||shouldEmitNonInteractiveCommandError(client),message=`${problem} ${sdkKeyInputHint(machine)}`;return machine?writeActionRequired(client,{status:AGENT_STATUS.ACTION_REQUIRED,reason,message,next:[{command:`${buildCommandWithGlobalFlags(client.argv,`flags datafile --sdk-key${json?" --json":""}`)} < <SDK_KEY_FILE>`,when:"Replace <SDK_KEY_FILE> with a file that contains the SDK key"}]}):output_manager_default.error(message),getExitCodeForReason(reason)}async function getDevelopmentOidcToken(client,projectId,accountId){try{let result=await client.fetch(`/projects/${projectId}/token`,{method:"POST",accountId,retry:{retries:0},bailOn429:!0,body:JSON.stringify({source:"vercel-cli"}),headers:{"Content-Type":"application/json"}});return typeof result.token=="string"&&result.token.trim()?result.token:void 0}catch{output_manager_default.debug("Development OIDC token unavailable; using user authentication.");return}}async function fetchAndPrintDatafile(client,json,token,extraHeaders,authScheme,summary){try{let res=await fetch(DATAFILE_URL,{redirect:"error",headers:{accept:"application/json",authorization:`${authScheme} ${token}`,"user-agent":ua_default,...extraHeaders}});if(output_manager_default.stopSpinner(),!res.ok){let body=await res.text().catch(()=>"");return outputError(client,json,"DATAFILE_FETCH_FAILED",redactSecret(`Failed to fetch datafile (${res.status} ${res.statusText})${body?`: ${body}`:""}`,token))}let data=await res.json();return json?client.stdout.write(`${JSON.stringify({datafile:data},null,2)}
|
|
376
376
|
`):isPackedDatafile(data)?printDatafileSummary(data,summary):client.stdout.write(`${JSON.stringify(data,null,2)}
|
|
377
|
-
`),0}catch(err){return output_manager_default.stopSpinner(),printUnexpectedError(client,json,err,token)}}function redactSecret(text,secret){return secret?text.split(secret).join("[REDACTED]"):text}function printUnexpectedError(client,json,err,secret=""){let message=err instanceof Error?err.message:String(err),redacted=redactSecret(message,secret);return json?outputError(client,json,"UNEXPECTED_ERROR",redacted):(printError(redacted===message?err:new Error(redacted)),1)}var COMMAND_CONFIG17={ls:getCommandAliases(listSubcommand),stale:getCommandAliases(staleSubcommand),inspect:getCommandAliases(inspectSubcommand),versions:getCommandAliases(versionsSubcommand),evaluations:getCommandAliases(evaluationsSubcommand),create:getCommandAliases(createSubcommand),open:getCommandAliases(openSubcommand),update:getCommandAliases(updateSubcommand),set:getCommandAliases(setSubcommand),targeting:getCommandAliases(targetingSubcommand),"use-targeting":getCommandAliases(useTargetingSubcommand),split:getCommandAliases(splitSubcommand),rollout:getCommandAliases(rolloutSubcommand),delete:getCommandAliases(removeSubcommand),archive:getCommandAliases(archiveSubcommand),unarchive:getCommandAliases(unarchiveSubcommand),disable:getCommandAliases(disableSubcommand),enable:getCommandAliases(enableSubcommand),rules:getCommandAliases(rulesSubcommand2),targets:getCommandAliases(targetsSubcommand),segments:getCommandAliases(segmentsSubcommand),entities:getCommandAliases(entitiesSubcommand),labels:getCommandAliases(labelsSubcommand),"sdk-keys":getCommandAliases(sdkKeysSubcommand),connections:getCommandAliases(connectionsSubcommand),prepare:getCommandAliases(prepareSubcommand),datafile:getCommandAliases(datafileSubcommand),override:getCommandAliases(overrideSubcommand)};async function main10(client){let telemetry=new FlagsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(flagsCommand.options),
|
|
377
|
+
`),0}catch(err){return output_manager_default.stopSpinner(),printUnexpectedError(client,json,err,token)}}function redactSecret(text,secret){return secret?text.split(secret).join("[REDACTED]"):text}function printUnexpectedError(client,json,err,secret=""){let message=err instanceof Error?err.message:String(err),redacted=redactSecret(message,secret);return json?outputError(client,json,"UNEXPECTED_ERROR",redacted):(printError(redacted===message?err:new Error(redacted)),1)}var COMMAND_CONFIG17={ls:getCommandAliases(listSubcommand),stale:getCommandAliases(staleSubcommand),inspect:getCommandAliases(inspectSubcommand),versions:getCommandAliases(versionsSubcommand),evaluations:getCommandAliases(evaluationsSubcommand),create:getCommandAliases(createSubcommand),open:getCommandAliases(openSubcommand),update:getCommandAliases(updateSubcommand),set:getCommandAliases(setSubcommand),targeting:getCommandAliases(targetingSubcommand),"use-targeting":getCommandAliases(useTargetingSubcommand),split:getCommandAliases(splitSubcommand),rollout:getCommandAliases(rolloutSubcommand),delete:getCommandAliases(removeSubcommand),archive:getCommandAliases(archiveSubcommand),unarchive:getCommandAliases(unarchiveSubcommand),disable:getCommandAliases(disableSubcommand),enable:getCommandAliases(enableSubcommand),rules:getCommandAliases(rulesSubcommand2),targets:getCommandAliases(targetsSubcommand),segments:getCommandAliases(segmentsSubcommand),entities:getCommandAliases(entitiesSubcommand),labels:getCommandAliases(labelsSubcommand),"sdk-keys":getCommandAliases(sdkKeysSubcommand),connections:getCommandAliases(connectionsSubcommand),prepare:getCommandAliases(prepareSubcommand),datafile:getCommandAliases(datafileSubcommand),override:getCommandAliases(overrideSubcommand)};async function main10(client){let telemetry=new FlagsTelemetryClient({opts:{store:client.telemetryEventStore}}),flagsSpecification=getFlagsSpecification(flagsCommand.options),argv=client.argv.slice(2),parsedArgs;try{parsedArgs=parseArguments(argv,flagsSpecification,{permissive:!0,commandShorthands:findCommandShorthands(commandsStructs,argv)})}catch(err){return printError(err),2}let subArgs=parsedArgs.args.slice(1),{subcommand,args,subcommandOriginal}=getSubcommand(subArgs,COMMAND_CONFIG17),needHelp=parsedArgs.flags["--help"];if(!subcommand&&needHelp)return telemetry.trackCliFlagHelp("flags",subcommand),output_manager_default.print(help(flagsCommand,{stream:client.stderr,columns:client.stderr.columns})),0;function printHelp(command){output_manager_default.print(help(command,{stream:client.stderr,parent:flagsCommand,columns:client.stderr.columns}))}switch(subcommand){case"ls":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(listSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),ls(client,args));case"inspect":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(inspectSubcommand),0):(telemetry.trackCliSubcommandInspect(subcommandOriginal),inspect5(client,args));case"versions":return telemetry.trackCliSubcommandVersions(subcommandOriginal),versions(client,needHelp?[...args,"--help"]:args);case"evaluations":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(evaluationsSubcommand),0):(telemetry.trackCliSubcommandEvaluations(subcommandOriginal),evaluations(client,args));case"stale":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(staleSubcommand),0):(telemetry.trackCliSubcommandStale(subcommandOriginal),stale(client,args));case"open":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(openSubcommand),0):(telemetry.trackCliSubcommandOpen(subcommandOriginal),openFlag(client,args));case"create":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(createSubcommand),0):(telemetry.trackCliSubcommandCreate(subcommandOriginal),subcommandOriginal==="add"&&warnDeprecatedSubcommand(client,"flags add","flags create"),create(client,args));case"update":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(updateSubcommand),0):(telemetry.trackCliSubcommandUpdate(subcommandOriginal),update(client,args));case"set":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(setSubcommand),0):(telemetry.trackCliSubcommandSet(subcommandOriginal),set(client,args));case"use-targeting":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(useTargetingSubcommand),0):(telemetry.trackCliSubcommandUseTargeting(subcommandOriginal),warnDeprecatedSubcommand(client,"flags use-targeting","flags targeting enable"),useTargeting(client,args));case"targeting":return telemetry.trackCliSubcommandTargeting(subcommandOriginal),targeting(client,args);case"split":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(splitSubcommand),0):(telemetry.trackCliSubcommandSplit(subcommandOriginal),split(client,args));case"rollout":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(rolloutSubcommand),0):(telemetry.trackCliSubcommandRollout(subcommandOriginal),rollout(client,args));case"delete":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(removeSubcommand),0):(telemetry.trackCliSubcommandDelete(subcommandOriginal),subcommandOriginal==="remove"&&warnDeprecatedSubcommand(client,"flags remove","flags delete"),rm(client,args));case"archive":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(archiveSubcommand),0):(telemetry.trackCliSubcommandArchive(subcommandOriginal),archive(client,args));case"unarchive":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(unarchiveSubcommand),0):(telemetry.trackCliSubcommandUnarchive(subcommandOriginal),unarchive(client,args));case"disable":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(disableSubcommand),0):(telemetry.trackCliSubcommandDisable(subcommandOriginal),disable3(client,args));case"enable":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(enableSubcommand),0):(telemetry.trackCliSubcommandEnable(subcommandOriginal),enable3(client,args));case"rules":return telemetry.trackCliSubcommandRules(subcommandOriginal),rules(client);case"targets":return telemetry.trackCliSubcommandTargets(subcommandOriginal),targets(client);case"sdk-keys":return telemetry.trackCliSubcommandSdkKeys(subcommandOriginal),sdkKeys(client);case"connections":return telemetry.trackCliSubcommandConnections(subcommandOriginal),connections(client);case"segments":return telemetry.trackCliSubcommandSegments(subcommandOriginal),segments(client);case"entities":return telemetry.trackCliSubcommandEntities(subcommandOriginal),entities(client);case"labels":return telemetry.trackCliSubcommandLabels(subcommandOriginal),labels(client);case"prepare":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(prepareSubcommand),0):(telemetry.trackCliSubcommandPrepare(subcommandOriginal),emitDatafiles(client));case"datafile":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(datafileSubcommand),0):(telemetry.trackCliSubcommandDatafile(subcommandOriginal),datafile(client,args));case"override":return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(overrideSubcommand),0):(telemetry.trackCliSubcommandOverride(subcommandOriginal),override(client,args));default:return needHelp?(telemetry.trackCliFlagHelp("flags",subcommandOriginal),printHelp(listSubcommand),0):(telemetry.trackCliSubcommandList(subcommandOriginal),ls(client,args))}}export{feedback,main9 as firewall,main10 as flags};
|