@koda-sl/baker-cli 0.513.0 → 0.515.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1231) hide show
  1. package/README.md +3 -3
  2. package/dist/account-BA3IO3AN.js +139 -0
  3. package/dist/account-LVJFHDA3.js +82 -0
  4. package/dist/account-LVJFHDA3.js.map +1 -0
  5. package/dist/account-PTJ6OK6Z.js +82 -0
  6. package/dist/account-PTJ6OK6Z.js.map +1 -0
  7. package/dist/account-assets-T3VVNBUG.js +290 -0
  8. package/dist/account-level-MPFWRPEK.js +611 -0
  9. package/dist/account-level-MPFWRPEK.js.map +1 -0
  10. package/dist/account-reads-5CXFLJ5Q.js +219 -0
  11. package/dist/account-users-B7DCJEFD.js +64 -0
  12. package/dist/account-users-B7DCJEFD.js.map +1 -0
  13. package/dist/account-writes-W5EOTS7P.js +68 -0
  14. package/dist/account-writes-W5EOTS7P.js.map +1 -0
  15. package/dist/accounts-4R3MBNJG.js +76 -0
  16. package/dist/accounts-5WF7VE7J.js +115 -0
  17. package/dist/accounts-IQTEH4BX.js +701 -0
  18. package/dist/accounts-IQTEH4BX.js.map +1 -0
  19. package/dist/accounts-SV7JZUCC.js +80 -0
  20. package/dist/accounts-SV7JZUCC.js.map +1 -0
  21. package/dist/accounts-VPWCLF6X.js +114 -0
  22. package/dist/actions-D7OWCP36.js +55 -0
  23. package/dist/active-entities-WDPW7652.js +103 -0
  24. package/dist/activecampaign-LBS4M4C4.js +938 -0
  25. package/dist/activecampaign-LBS4M4C4.js.map +1 -0
  26. package/dist/activities-WGPHYSFU.js +75 -0
  27. package/dist/ad-group-writes-JL56DPC4.js +172 -0
  28. package/dist/ad-group-writes-JL56DPC4.js.map +1 -0
  29. package/dist/ad-groups-62JPLIK3.js +70 -0
  30. package/dist/ad-groups-62JPLIK3.js.map +1 -0
  31. package/dist/ad-writes-WSKLRGB7.js +176 -0
  32. package/dist/ad-writes-WSKLRGB7.js.map +1 -0
  33. package/dist/add-HFQB2NTU.js +107 -0
  34. package/dist/add-HFQB2NTU.js.map +1 -0
  35. package/dist/add-IUYE5H6A.js +305 -0
  36. package/dist/add-IUYE5H6A.js.map +1 -0
  37. package/dist/ads-F7AUJWK7.js +115 -0
  38. package/dist/ads-JFI56MZL.js +79 -0
  39. package/dist/ads-JFI56MZL.js.map +1 -0
  40. package/dist/ads-OV3SMLKA.js +48 -0
  41. package/dist/adsets-XH2ULWPM.js +182 -0
  42. package/dist/advertisers-XXM6POO5.js +123 -0
  43. package/dist/advertisers-XXM6POO5.js.map +1 -0
  44. package/dist/analytics-MJT6DS3L.js +447 -0
  45. package/dist/analytics-MJT6DS3L.js.map +1 -0
  46. package/dist/analytics-W7EUOI2Q.js +2437 -0
  47. package/dist/analytics-W7EUOI2Q.js.map +1 -0
  48. package/dist/asset-writes-4X3AJQ4Q.js +50 -0
  49. package/dist/assign-2GQVQKKO.js +80 -0
  50. package/dist/assign-2GQVQKKO.js.map +1 -0
  51. package/dist/audience-size-VHXBNNIB.js +76 -0
  52. package/dist/audience-size-VHXBNNIB.js.map +1 -0
  53. package/dist/audience-writes-TXWPDJ2F.js +327 -0
  54. package/dist/audience-writes-TXWPDJ2F.js.map +1 -0
  55. package/dist/audiences-B2LFKWIS.js +280 -0
  56. package/dist/audiences-B2LFKWIS.js.map +1 -0
  57. package/dist/audiences-MBBXWEOI.js +86 -0
  58. package/dist/audiences-YUG5JLL4.js +85 -0
  59. package/dist/audit-VT2WSZWM.js +154 -0
  60. package/dist/audit-VT2WSZWM.js.map +1 -0
  61. package/dist/audit-WFXS5ELM.js +88 -0
  62. package/dist/autocomplete-ZYMHHV7E.js +114 -0
  63. package/dist/autocomplete-ZYMHHV7E.js.map +1 -0
  64. package/dist/avatars-WZ2JDMHH.js +38 -0
  65. package/dist/bid-pricing-5F3GBSAI.js +103 -0
  66. package/dist/bid-pricing-5F3GBSAI.js.map +1 -0
  67. package/dist/brand-IZTTBZII.js +22 -0
  68. package/dist/brief-OPQ7ICOY.js +543 -0
  69. package/dist/brief-OPQ7ICOY.js.map +1 -0
  70. package/dist/businesses-24JNY46Z.js +54 -0
  71. package/dist/campaign-groups-BDCDTMBF.js +99 -0
  72. package/dist/campaign-groups-BDCDTMBF.js.map +1 -0
  73. package/dist/campaign-writes-73H7G3JM.js +168 -0
  74. package/dist/campaign-writes-73H7G3JM.js.map +1 -0
  75. package/dist/campaign-writes-FNVOHONL.js +176 -0
  76. package/dist/campaign-writes-FNVOHONL.js.map +1 -0
  77. package/dist/campaigns-FUDZUVHN.js +78 -0
  78. package/dist/campaigns-FUDZUVHN.js.map +1 -0
  79. package/dist/campaigns-J65Q4WAZ.js +113 -0
  80. package/dist/campaigns-J65Q4WAZ.js.map +1 -0
  81. package/dist/campaigns-KXYGSH27.js +130 -0
  82. package/dist/campaigns-U5FQ2VWL.js +111 -0
  83. package/dist/canvas-IQ753Q2O.js +46 -0
  84. package/dist/capabilities-ZITW4RF7.js +147 -0
  85. package/dist/capabilities-ZITW4RF7.js.map +1 -0
  86. package/dist/cards-NSNAFTEB.js +85 -0
  87. package/dist/catalogs-OWQGGCIO.js +130 -0
  88. package/dist/catalogs-OWQGGCIO.js.map +1 -0
  89. package/dist/catalogs-VZYAATUR.js +781 -0
  90. package/dist/catalogs-VZYAATUR.js.map +1 -0
  91. package/dist/changes-RDWMNSTK.js +135 -0
  92. package/dist/chatgpt-27NEJVGF.js +47 -0
  93. package/dist/chats-AL2SYBJO.js +279 -0
  94. package/dist/chats-AL2SYBJO.js.map +1 -0
  95. package/dist/check-U2YLRD6H.js +107 -0
  96. package/dist/check-U2YLRD6H.js.map +1 -0
  97. package/dist/chunk-2F4DELSV.js +200 -0
  98. package/dist/chunk-2GYCWRF3.js +170 -0
  99. package/dist/chunk-2L7F7KR4.js +61 -0
  100. package/dist/chunk-44ZRCSR7.js +228 -0
  101. package/dist/chunk-46YLDIQG.js +4254 -0
  102. package/dist/chunk-4EDWXZ3I.js +363 -0
  103. package/dist/chunk-4FFBGR5L.js +66 -0
  104. package/dist/chunk-4UZUUSVL.js +592 -0
  105. package/dist/chunk-4XHCEYHI.js +831 -0
  106. package/dist/chunk-4Z6PVR3M.js +479 -0
  107. package/dist/chunk-5Y5FZV2W.js +122 -0
  108. package/dist/chunk-6DPSWLGY.js +324 -0
  109. package/dist/chunk-6DPSWLGY.js.map +1 -0
  110. package/dist/chunk-6HJXLGDV.js +392 -0
  111. package/dist/chunk-6S5CWGDA.js +429 -0
  112. package/dist/chunk-6VYROVWO.js +494 -0
  113. package/dist/chunk-AQRXXC6E.js +319 -0
  114. package/dist/chunk-ARBXT73X.js +387 -0
  115. package/dist/chunk-BEZHQIEI.js +97 -0
  116. package/dist/chunk-BFURWHVR.js +547 -0
  117. package/dist/chunk-EZSPVWLQ.js +169 -0
  118. package/dist/chunk-FCHZ5TNG.js +26 -0
  119. package/dist/chunk-FLWDFPXE.js +23 -0
  120. package/dist/chunk-FQMEX3GX.js +846 -0
  121. package/dist/chunk-G4FG5EQO.js +110 -0
  122. package/dist/chunk-G4FG5EQO.js.map +1 -0
  123. package/dist/chunk-GE3VT3CA.js +51 -0
  124. package/dist/chunk-GGK2CX6B.js +24026 -0
  125. package/dist/chunk-GGK2CX6B.js.map +1 -0
  126. package/dist/chunk-GHZ6HP2X.js +358 -0
  127. package/dist/chunk-GHZ6HP2X.js.map +1 -0
  128. package/dist/chunk-HCQJYI6X.js +74 -0
  129. package/dist/chunk-HGBJQGO5.js +142 -0
  130. package/dist/chunk-HHVWV5BJ.js +191 -0
  131. package/dist/chunk-I3WGTSDY.js +76 -0
  132. package/dist/chunk-I7AYMJZA.js +783 -0
  133. package/dist/chunk-IDSDJHRS.js +106 -0
  134. package/dist/chunk-ILPHIYAL.js +207 -0
  135. package/dist/chunk-IWKD56AY.js +156 -0
  136. package/dist/chunk-JLAQWMVF.js +3868 -0
  137. package/dist/chunk-JOE42ZW6.js +2984 -0
  138. package/dist/chunk-JOE42ZW6.js.map +1 -0
  139. package/dist/chunk-K6NULQN7.js +57 -0
  140. package/dist/chunk-L2BRAC2J.js +19 -0
  141. package/dist/chunk-LGMI4LSY.js +455 -0
  142. package/dist/chunk-LNODLR7W.js +149 -0
  143. package/dist/chunk-LQ2BRGMX.js +274 -0
  144. package/dist/chunk-M7QZSEHF.js +175 -0
  145. package/dist/chunk-NB2FU6EZ.js +179 -0
  146. package/dist/chunk-NFII3MTG.js +207 -0
  147. package/dist/chunk-NKQWDEB7.js +115 -0
  148. package/dist/chunk-NKQWDEB7.js.map +1 -0
  149. package/dist/chunk-OG47L5GG.js +275 -0
  150. package/dist/chunk-PC3FJEZH.js +7211 -0
  151. package/dist/chunk-PC3FJEZH.js.map +1 -0
  152. package/dist/chunk-Q3GSVLE5.js +4274 -0
  153. package/dist/chunk-Q3GSVLE5.js.map +1 -0
  154. package/dist/chunk-QIOFOD4K.js +344 -0
  155. package/dist/chunk-R2SYF5FC.js +249 -0
  156. package/dist/chunk-RTH2I55B.js +942 -0
  157. package/dist/chunk-S6VFDNSQ.js +63 -0
  158. package/dist/chunk-SG2TDQEE.js +150 -0
  159. package/dist/chunk-SOPVIIUW.js +68 -0
  160. package/dist/chunk-SOPVIIUW.js.map +1 -0
  161. package/dist/chunk-T3P6O2VU.js +89 -0
  162. package/dist/chunk-TU5LQUJM.js +74 -0
  163. package/dist/chunk-TU7DWSTW.js +69 -0
  164. package/dist/chunk-TXDE2QJ3.js +604 -0
  165. package/dist/chunk-TYXZ2SRW.js +287 -0
  166. package/dist/chunk-UDIEKCIR.js +203 -0
  167. package/dist/chunk-UQHHGT67.js +676 -0
  168. package/dist/chunk-USCADMM3.js +163 -0
  169. package/dist/chunk-UUGISMNE.js +910 -0
  170. package/dist/chunk-VDPOCAQ2.js +197 -0
  171. package/dist/chunk-VEJ3QX6M.js +103 -0
  172. package/dist/chunk-VFJB7OG6.js +91 -0
  173. package/dist/chunk-VPABGAN4.js +188 -0
  174. package/dist/chunk-VRIPVLE7.js +8954 -0
  175. package/dist/chunk-WLESMH4J.js +45 -0
  176. package/dist/chunk-XOQNM7I4.js +396 -0
  177. package/dist/chunk-XOQNM7I4.js.map +1 -0
  178. package/dist/chunk-YILZR3XI.js +224 -0
  179. package/dist/chunk-YJFLXOH4.js +191 -0
  180. package/dist/chunk-YWHZYR6S.js +297 -0
  181. package/dist/chunk-Z35KUMBW.js +219 -0
  182. package/dist/chunk-Z7I2ZFXS.js +1646 -0
  183. package/dist/claim-GOLUTAJ3.js +200 -0
  184. package/dist/claim-GOLUTAJ3.js.map +1 -0
  185. package/dist/cli.js +34 -34
  186. package/dist/companies-CSN7DPYW.js +198 -0
  187. package/dist/companies-CSN7DPYW.js.map +1 -0
  188. package/dist/company-MOSPLRZJ.js +308 -0
  189. package/dist/company-MOSPLRZJ.js.map +1 -0
  190. package/dist/complete-777BDV45.js +84 -0
  191. package/dist/complete-777BDV45.js.map +1 -0
  192. package/dist/config-55WGRLY3.js +88 -0
  193. package/dist/connect-3YY7MF3I.js +45 -0
  194. package/dist/conversation-6K2TNYBQ.js +96 -0
  195. package/dist/conversation-6K2TNYBQ.js.map +1 -0
  196. package/dist/conversion-report-WYYB3BK2.js +127 -0
  197. package/dist/conversion-report-WYYB3BK2.js.map +1 -0
  198. package/dist/conversion-upload-command-VM2P57K6.js +439 -0
  199. package/dist/conversion-writes-DHOPMA7X.js +122 -0
  200. package/dist/conversion-writes-DHOPMA7X.js.map +1 -0
  201. package/dist/conversions-KWY7BNDN.js +78 -0
  202. package/dist/conversions-KWY7BNDN.js.map +1 -0
  203. package/dist/conversions-MLRK35ZV.js +140 -0
  204. package/dist/conversions-MLRK35ZV.js.map +1 -0
  205. package/dist/copy-writes-E3V5TUVU.js +170 -0
  206. package/dist/copy-writes-E3V5TUVU.js.map +1 -0
  207. package/dist/create-3WOZO2XT.js +239 -0
  208. package/dist/create-3WOZO2XT.js.map +1 -0
  209. package/dist/create-7IFYLX7P.js +210 -0
  210. package/dist/create-7IFYLX7P.js.map +1 -0
  211. package/dist/create-FOHIQC3E.js +62 -0
  212. package/dist/create-FOHIQC3E.js.map +1 -0
  213. package/dist/create-UWQSQTK6.js +135 -0
  214. package/dist/create-UWQSQTK6.js.map +1 -0
  215. package/dist/creatives-2DR3QHJW.js +58 -0
  216. package/dist/creatives-DUR5Z5AN.js +89 -0
  217. package/dist/creatives-KN3MT533.js +223 -0
  218. package/dist/creatives-KN3MT533.js.map +1 -0
  219. package/dist/credentials-IP4L37XP.js +290 -0
  220. package/dist/credentials-IP4L37XP.js.map +1 -0
  221. package/dist/critique-LGDNMLBL.js +232 -0
  222. package/dist/critique-LGDNMLBL.js.map +1 -0
  223. package/dist/critique-LJMFAURK.js +1451 -0
  224. package/dist/critique-LJMFAURK.js.map +1 -0
  225. package/dist/crm-BNYW7PF7.js +323 -0
  226. package/dist/crm-BNYW7PF7.js.map +1 -0
  227. package/dist/crm-DMADHALO.js +227 -0
  228. package/dist/crm-DMADHALO.js.map +1 -0
  229. package/dist/currency-X4KEACEP.js +88 -0
  230. package/dist/custom-conversions-OIA5Y2GX.js +128 -0
  231. package/dist/customers-663K2OCP.js +59 -0
  232. package/dist/delete-5W3YVA4L.js +67 -0
  233. package/dist/delete-5W3YVA4L.js.map +1 -0
  234. package/dist/delete-6U7E6YUW.js +57 -0
  235. package/dist/delete-6U7E6YUW.js.map +1 -0
  236. package/dist/delete-G4NY6ZG6.js +69 -0
  237. package/dist/delete-G4NY6ZG6.js.map +1 -0
  238. package/dist/demographics-UZ7BCQ7K.js +141 -0
  239. package/dist/demographics-UZ7BCQ7K.js.map +1 -0
  240. package/dist/discard-RKCZNKMN.js +69 -0
  241. package/dist/discard-RKCZNKMN.js.map +1 -0
  242. package/dist/discover-2W42JB56.js +172 -0
  243. package/dist/domain-PLA2O4FW.js +101 -0
  244. package/dist/domain-PLA2O4FW.js.map +1 -0
  245. package/dist/download-4EFLVSA4.js +172 -0
  246. package/dist/download-4EFLVSA4.js.map +1 -0
  247. package/dist/draft-2ZX73IRO.js +238 -0
  248. package/dist/draft-6XMZYSMR.js +283 -0
  249. package/dist/draft-6XMZYSMR.js.map +1 -0
  250. package/dist/draft-CKLIIWXZ.js +308 -0
  251. package/dist/draft-IUEULQDT.js +310 -0
  252. package/dist/draft-IUEULQDT.js.map +1 -0
  253. package/dist/draft-JMNAGW7C.js +220 -0
  254. package/dist/draft-JMNAGW7C.js.map +1 -0
  255. package/dist/draft-L5Q6KEER.js +100 -0
  256. package/dist/draft-MJRMZGMP.js +103 -0
  257. package/dist/draft-WPMVLRME.js +335 -0
  258. package/dist/draft-WPMVLRME.js.map +1 -0
  259. package/dist/experiment-3VRHCQN5.js +1397 -0
  260. package/dist/experiments-S4TSXCK6.js +236 -0
  261. package/dist/experiments-S4TSXCK6.js.map +1 -0
  262. package/dist/facets-D3JG7OSO.js +117 -0
  263. package/dist/facets-D3JG7OSO.js.map +1 -0
  264. package/dist/feedback-IRSRPXV6.js +111 -0
  265. package/dist/feedback-IRSRPXV6.js.map +1 -0
  266. package/dist/feedback-record-DT3R4NA3.js +265 -0
  267. package/dist/feedback-record-DT3R4NA3.js.map +1 -0
  268. package/dist/fetch-YLQP5VQL.js +179 -0
  269. package/dist/fetch-YLQP5VQL.js.map +1 -0
  270. package/dist/fit-BEFCY2B4.js +65 -0
  271. package/dist/flows-FDMF3F3P.js +250 -0
  272. package/dist/flows-FDMF3F3P.js.map +1 -0
  273. package/dist/fonts-C6XN5667.js +39 -0
  274. package/dist/forecast-4YHMKO54.js +121 -0
  275. package/dist/forecast-4YHMKO54.js.map +1 -0
  276. package/dist/forecast-LYN6ZGQC.js +169 -0
  277. package/dist/funding-TCEPQXRQ.js +85 -0
  278. package/dist/funnel-CQIT3F23.js +397 -0
  279. package/dist/funnel-CQIT3F23.js.map +1 -0
  280. package/dist/ga4-JE3HS36B.js +55 -0
  281. package/dist/get-KBSKPTAV.js +59 -0
  282. package/dist/get-KBSKPTAV.js.map +1 -0
  283. package/dist/get-OSVQVMP6.js +82 -0
  284. package/dist/get-OSVQVMP6.js.map +1 -0
  285. package/dist/google-24FDG4C4.js +3267 -0
  286. package/dist/google-ads-XCJVAXWF.js +198 -0
  287. package/dist/google-ads-XCJVAXWF.js.map +1 -0
  288. package/dist/gsc-RMVOYIM3.js +30 -0
  289. package/dist/history-4TN2A6BL.js +136 -0
  290. package/dist/history-4TN2A6BL.js.map +1 -0
  291. package/dist/history-5IWW2X33.js +102 -0
  292. package/dist/history-5IWW2X33.js.map +1 -0
  293. package/dist/history-GIXIG276.js +69 -0
  294. package/dist/history-GIXIG276.js.map +1 -0
  295. package/dist/hubspot-5WB7TQBG.js +782 -0
  296. package/dist/hubspot-5WB7TQBG.js.map +1 -0
  297. package/dist/ideas-M66FU45H.js +45 -0
  298. package/dist/images-MM5OPUKV.js +92 -0
  299. package/dist/ingest-GU3WEBN3.js +110 -0
  300. package/dist/ingest-GU3WEBN3.js.map +1 -0
  301. package/dist/ingest-KMLYCFF4.js +26 -0
  302. package/dist/insights-HATH3IC6.js +439 -0
  303. package/dist/insights-HATH3IC6.js.map +1 -0
  304. package/dist/insights-VKPIVJMK.js +132 -0
  305. package/dist/insights-VKPIVJMK.js.map +1 -0
  306. package/dist/inspect-4JO2J3D6.js +192 -0
  307. package/dist/inspect-4JO2J3D6.js.map +1 -0
  308. package/dist/instant-experiences-A2SIQNB5.js +260 -0
  309. package/dist/instant-experiences-A2SIQNB5.js.map +1 -0
  310. package/dist/intent-YCQCUCV3.js +95 -0
  311. package/dist/job-SM2OQ2LO.js +202 -0
  312. package/dist/job-create-ECZHPVKH.js +109 -0
  313. package/dist/job-status-QSYDKIIV.js +74 -0
  314. package/dist/keyword-gap-PUSF7EKY.js +130 -0
  315. package/dist/keyword-metrics-JXBM22ZD.js +200 -0
  316. package/dist/keyword-metrics-JXBM22ZD.js.map +1 -0
  317. package/dist/keywords-for-site-OAYA7KP7.js +131 -0
  318. package/dist/keywords-for-site-OAYA7KP7.js.map +1 -0
  319. package/dist/landing-OZU5RRFV.js +28 -0
  320. package/dist/languages-Q5SKO4AM.js +40 -0
  321. package/dist/leads-QAYS7AJO.js +540 -0
  322. package/dist/leads-QAYS7AJO.js.map +1 -0
  323. package/dist/leads-VOSFVNUK.js +115 -0
  324. package/dist/leads-VOSFVNUK.js.map +1 -0
  325. package/dist/learn-NBBJRMVZ.js +207 -0
  326. package/dist/learn-NBBJRMVZ.js.map +1 -0
  327. package/dist/line-item-writes-VBBB3TRS.js +211 -0
  328. package/dist/line-item-writes-VBBB3TRS.js.map +1 -0
  329. package/dist/line-items-2V5FY33R.js +107 -0
  330. package/dist/link-WZSNUQQ2.js +67 -0
  331. package/dist/link-WZSNUQQ2.js.map +1 -0
  332. package/dist/linkedin-CDFCOHKI.js +1316 -0
  333. package/dist/linkedin-CDFCOHKI.js.map +1 -0
  334. package/dist/linkedin-person-MVRI7LLC.js +139 -0
  335. package/dist/linkedin-person-MVRI7LLC.js.map +1 -0
  336. package/dist/list-6S54IAUX.js +67 -0
  337. package/dist/list-6S54IAUX.js.map +1 -0
  338. package/dist/list-QRJ4E3SC.js +154 -0
  339. package/dist/list-QRJ4E3SC.js.map +1 -0
  340. package/dist/list-RZUDFLJN.js +306 -0
  341. package/dist/list-RZUDFLJN.js.map +1 -0
  342. package/dist/locations-RFTE42OS.js +69 -0
  343. package/dist/locations-RFTE42OS.js.map +1 -0
  344. package/dist/locations-VQYREHYI.js +40 -0
  345. package/dist/log-53SAPZZ3.js +95 -0
  346. package/dist/log-53SAPZZ3.js.map +1 -0
  347. package/dist/lookup-MELV3RUL.js +23 -0
  348. package/dist/make-ZF3YIMKW.js +1370 -0
  349. package/dist/make-ZF3YIMKW.js.map +1 -0
  350. package/dist/map-J37QFJSV.js +436 -0
  351. package/dist/map-J37QFJSV.js.map +1 -0
  352. package/dist/mcp-B7WSZQFD.js +729 -0
  353. package/dist/mcp-B7WSZQFD.js.map +1 -0
  354. package/dist/media-BPI2VE6A.js +89 -0
  355. package/dist/media-EEWZZU3P.js +18 -0
  356. package/dist/media-sources-EQI3U4TC.js +35 -0
  357. package/dist/members-GYVMSCKL.js +47 -0
  358. package/dist/members-GYVMSCKL.js.map +1 -0
  359. package/dist/meta-SMJUQP37.js +122 -0
  360. package/dist/metrics-EMAP7ESR.js +152 -0
  361. package/dist/normalize-MFN3WCH5.js +144 -0
  362. package/dist/normalize-MFN3WCH5.js.map +1 -0
  363. package/dist/options-DLHDHO7H.js +125 -0
  364. package/dist/options-DLHDHO7H.js.map +1 -0
  365. package/dist/organization-C2VOA2SD.js +949 -0
  366. package/dist/organization-C2VOA2SD.js.map +1 -0
  367. package/dist/output-4QBQEM4C.js +24 -0
  368. package/dist/page-photos-HRKPDQBM.js +118 -0
  369. package/dist/page-photos-HRKPDQBM.js.map +1 -0
  370. package/dist/pages-DTQWQUKP.js +67 -0
  371. package/dist/performance-NIF3CESZ.js +27 -0
  372. package/dist/performance-T6TBVHVU.js +5541 -0
  373. package/dist/performance-T6TBVHVU.js.map +1 -0
  374. package/dist/pixels-2BKADWE6.js +109 -0
  375. package/dist/pixels-F6BZNTDD.js +62 -0
  376. package/dist/pixels-F6BZNTDD.js.map +1 -0
  377. package/dist/plan-A6VC3ZO7.js +208 -0
  378. package/dist/plan-A6VC3ZO7.js.map +1 -0
  379. package/dist/preview-GGIGXPJW.js +218 -0
  380. package/dist/preview-GGIGXPJW.js.map +1 -0
  381. package/dist/promoted-tweet-writes-WU2SKKZF.js +183 -0
  382. package/dist/promoted-tweet-writes-WU2SKKZF.js.map +1 -0
  383. package/dist/promoted-tweets-653Q5AC6.js +119 -0
  384. package/dist/properties-VWKO3AAK.js +101 -0
  385. package/dist/publish-IOTMJCCY.js +344 -0
  386. package/dist/publish-IOTMJCCY.js.map +1 -0
  387. package/dist/query-CXIOL7WI.js +62 -0
  388. package/dist/query-OOP63DJF.js +236 -0
  389. package/dist/query-RBZFAIDK.js +247 -0
  390. package/dist/questionnaire-7SHYRTMJ.js +94 -0
  391. package/dist/questionnaire-7SHYRTMJ.js.map +1 -0
  392. package/dist/read-GOULD7YL.js +141 -0
  393. package/dist/reddit-JIHMAKAQ.js +29 -0
  394. package/dist/refresh-OQZ263CS.js +97 -0
  395. package/dist/refresh-OQZ263CS.js.map +1 -0
  396. package/dist/release-4CHFURO3.js +63 -0
  397. package/dist/release-4CHFURO3.js.map +1 -0
  398. package/dist/relevant-pages-FS7GBVXK.js +99 -0
  399. package/dist/remove-IJQPHPDI.js +53 -0
  400. package/dist/remove-IJQPHPDI.js.map +1 -0
  401. package/dist/reopen-YTLPVKUR.js +66 -0
  402. package/dist/reopen-YTLPVKUR.js.map +1 -0
  403. package/dist/rerun-C7NB7B35.js +95 -0
  404. package/dist/rerun-C7NB7B35.js.map +1 -0
  405. package/dist/research-PNBACCCP.js +72 -0
  406. package/dist/research-TLHNPK3O.js +265 -0
  407. package/dist/research-TLHNPK3O.js.map +1 -0
  408. package/dist/reset-JVLW7HA2.js +57 -0
  409. package/dist/reset-JVLW7HA2.js.map +1 -0
  410. package/dist/reset-Y6FXLAQE.js +57 -0
  411. package/dist/reset-Y6FXLAQE.js.map +1 -0
  412. package/dist/resolve-RCFAYPWR.js +124 -0
  413. package/dist/resolve-RCFAYPWR.js.map +1 -0
  414. package/dist/retry-3V3IGDRR.js +65 -0
  415. package/dist/retry-3V3IGDRR.js.map +1 -0
  416. package/dist/retry-AEKQLQMP.js +63 -0
  417. package/dist/retry-AEKQLQMP.js.map +1 -0
  418. package/dist/revenue-3R6JLYCQ.js +91 -0
  419. package/dist/revenue-3R6JLYCQ.js.map +1 -0
  420. package/dist/rule-writes-K4P3XBJW.js +525 -0
  421. package/dist/rule-writes-K4P3XBJW.js.map +1 -0
  422. package/dist/rules-34BQAWU3.js +99 -0
  423. package/dist/rules-34BQAWU3.js.map +1 -0
  424. package/dist/rules-HY7S2YTD.js +217 -0
  425. package/dist/rules-add-CM5XUYNS.js +465 -0
  426. package/dist/rules-add-CM5XUYNS.js.map +1 -0
  427. package/dist/run-MD64RDHZ.js +69 -0
  428. package/dist/run-MD64RDHZ.js.map +1 -0
  429. package/dist/run-QCNRR3CA.js +70 -0
  430. package/dist/scaffold-ad-NADPY3CB.js +1516 -0
  431. package/dist/scaffold-ad-NADPY3CB.js.map +1 -0
  432. package/dist/scaffold-static-ad-5YEYYVYH.js +1015 -0
  433. package/dist/scaffold-static-ad-5YEYYVYH.js.map +1 -0
  434. package/dist/scaffold-video-W7DF2CBJ.js +888 -0
  435. package/dist/scaffold-video-W7DF2CBJ.js.map +1 -0
  436. package/dist/schedule-CTRRF6TS.js +64 -0
  437. package/dist/schedule-CTRRF6TS.js.map +1 -0
  438. package/dist/scheduled-agents-OXYAVSIE.js +55 -0
  439. package/dist/schema-BEUYOGSW.js +135 -0
  440. package/dist/schema-BEUYOGSW.js.map +1 -0
  441. package/dist/search-GFJKWPKN.js +177 -0
  442. package/dist/search-GFJKWPKN.js.map +1 -0
  443. package/dist/select-S72CCL57.js +106 -0
  444. package/dist/select-S72CCL57.js.map +1 -0
  445. package/dist/sends-WBYTALR7.js +349 -0
  446. package/dist/sends-WBYTALR7.js.map +1 -0
  447. package/dist/set-prompt-YYFDRXRI.js +198 -0
  448. package/dist/set-prompt-YYFDRXRI.js.map +1 -0
  449. package/dist/setup-links-D4JJLESN.js +144 -0
  450. package/dist/setup-links-D4JJLESN.js.map +1 -0
  451. package/dist/shared-CGEJI2RB.js +32 -0
  452. package/dist/shopify-DQWEYPDX.js +3958 -0
  453. package/dist/shopify-DQWEYPDX.js.map +1 -0
  454. package/dist/site-BBZAUZA3.js +180 -0
  455. package/dist/site-BBZAUZA3.js.map +1 -0
  456. package/dist/sitemaps-5SP7PVQ6.js +87 -0
  457. package/dist/sites-YZDPHBST.js +101 -0
  458. package/dist/sources-7FIBHL6A.js +457 -0
  459. package/dist/sources-7FIBHL6A.js.map +1 -0
  460. package/dist/sources-FLUGHSVP.js +30 -0
  461. package/dist/stale-HP54JS5X.js +76 -0
  462. package/dist/stale-HP54JS5X.js.map +1 -0
  463. package/dist/stats-EGGNFTKI.js +34 -0
  464. package/dist/status-CLSWQFCQ.js +65 -0
  465. package/dist/status-CLSWQFCQ.js.map +1 -0
  466. package/dist/studies-6VUUOMZD.js +250 -0
  467. package/dist/study-writes-IR7RSSTK.js +470 -0
  468. package/dist/study-writes-IR7RSSTK.js.map +1 -0
  469. package/dist/sync-4YTVVEVC.js +57 -0
  470. package/dist/sync-4YTVVEVC.js.map +1 -0
  471. package/dist/sync-SCM6JGJP.js +279 -0
  472. package/dist/sync-definition-OGQ5XTQE.js +69 -0
  473. package/dist/tag-manager-REKD4WGU.js +43 -0
  474. package/dist/tags-CZTRQNXV.js +26 -0
  475. package/dist/tags-FDQXWTCQ.js +23 -0
  476. package/dist/tags-FDQXWTCQ.js.map +1 -0
  477. package/dist/tags-R67DKRZ6.js +23 -0
  478. package/dist/tags-R67DKRZ6.js.map +1 -0
  479. package/dist/tags-SA2LU6AW.js +227 -0
  480. package/dist/tags-SA2LU6AW.js.map +1 -0
  481. package/dist/tags-ZOXX6VRE.js +23 -0
  482. package/dist/tags-ZOXX6VRE.js.map +1 -0
  483. package/dist/targeting-BQUD54MF.js +762 -0
  484. package/dist/targeting-BQUD54MF.js.map +1 -0
  485. package/dist/targeting-constants-MRQB4N5I.js +118 -0
  486. package/dist/targeting-criteria-HSAESZIR.js +113 -0
  487. package/dist/targets-UUVCEG3F.js +106 -0
  488. package/dist/targets-UUVCEG3F.js.map +1 -0
  489. package/dist/terms-D2KAFHKJ.js +102 -0
  490. package/dist/testimonials-G3OCNPBY.js +32 -0
  491. package/dist/themes-X56KIX3Z.js +95 -0
  492. package/dist/top-companies-2RLNCSVS.js +111 -0
  493. package/dist/top-companies-2RLNCSVS.js.map +1 -0
  494. package/dist/transcript-U46AEOEI.js +165 -0
  495. package/dist/transcript-U46AEOEI.js.map +1 -0
  496. package/dist/translate-AS7JVKYM.js +609 -0
  497. package/dist/translate-AS7JVKYM.js.map +1 -0
  498. package/dist/triggers-ECRBPYYF.js +144 -0
  499. package/dist/triggers-ECRBPYYF.js.map +1 -0
  500. package/dist/tweets-JN6ARKF6.js +123 -0
  501. package/dist/unlink-VDNCSRJV.js +70 -0
  502. package/dist/unlink-VDNCSRJV.js.map +1 -0
  503. package/dist/unstage-5C27F2LZ.js +96 -0
  504. package/dist/unstage-5C27F2LZ.js.map +1 -0
  505. package/dist/unstage-ATDXUYP2.js +88 -0
  506. package/dist/unstage-ATDXUYP2.js.map +1 -0
  507. package/dist/update-FJ6TBV3E.js +101 -0
  508. package/dist/update-FJ6TBV3E.js.map +1 -0
  509. package/dist/update-HDBJCSTI.js +66 -0
  510. package/dist/update-HDBJCSTI.js.map +1 -0
  511. package/dist/update-U43DJRGV.js +155 -0
  512. package/dist/update-U43DJRGV.js.map +1 -0
  513. package/dist/update-Z7TIUBMJ.js +192 -0
  514. package/dist/update-Z7TIUBMJ.js.map +1 -0
  515. package/dist/upload-LXCFSRIU.js +129 -0
  516. package/dist/upload-LXCFSRIU.js.map +1 -0
  517. package/dist/url-options-C543MY7L.js +131 -0
  518. package/dist/url-options-C543MY7L.js.map +1 -0
  519. package/dist/url-params-TEFCXQ5N.js +101 -0
  520. package/dist/url-params-TEFCXQ5N.js.map +1 -0
  521. package/dist/validate-VR3HEOMJ.js +122 -0
  522. package/dist/validate-VR3HEOMJ.js.map +1 -0
  523. package/dist/videos-36AXDUGZ.js +41 -0
  524. package/dist/viewer-check-6HL4OUQY.js +83 -0
  525. package/dist/web-7BRJRQX7.js +143 -0
  526. package/dist/web-7BRJRQX7.js.map +1 -0
  527. package/dist/winning-ads-GMM5W2O4.js +86 -0
  528. package/dist/write-commands-B25W4FP5.js +713 -0
  529. package/dist/write-commands-DO2YUOMG.js +1502 -0
  530. package/dist/write-commands-DO2YUOMG.js.map +1 -0
  531. package/dist/write-commands-GNNEUVDW.js +206 -0
  532. package/dist/write-commands-NXJQQ62W.js +1172 -0
  533. package/dist/write-commands-NXJQQ62W.js.map +1 -0
  534. package/dist/x-JNR5SO6F.js +47 -0
  535. package/package.json +1 -1
  536. package/dist/account-UUAEQWO3.js +0 -80
  537. package/dist/account-UUAEQWO3.js.map +0 -1
  538. package/dist/account-WLQBAQMD.js +0 -80
  539. package/dist/account-WLQBAQMD.js.map +0 -1
  540. package/dist/account-ZY655BIU.js +0 -139
  541. package/dist/account-assets-O7IA37RE.js +0 -290
  542. package/dist/account-level-EU7BWCO7.js +0 -609
  543. package/dist/account-level-EU7BWCO7.js.map +0 -1
  544. package/dist/account-reads-SNOWDHHF.js +0 -219
  545. package/dist/account-users-NV37Z2XJ.js +0 -62
  546. package/dist/account-users-NV37Z2XJ.js.map +0 -1
  547. package/dist/account-writes-TU3WJRSI.js +0 -66
  548. package/dist/account-writes-TU3WJRSI.js.map +0 -1
  549. package/dist/accounts-FT2SRKMD.js +0 -76
  550. package/dist/accounts-K5XLEO6W.js +0 -114
  551. package/dist/accounts-MZ6SETJJ.js +0 -78
  552. package/dist/accounts-MZ6SETJJ.js.map +0 -1
  553. package/dist/accounts-SNB65ZEW.js +0 -115
  554. package/dist/accounts-U7ZBEAY6.js +0 -699
  555. package/dist/accounts-U7ZBEAY6.js.map +0 -1
  556. package/dist/actions-4JYHXRFH.js +0 -55
  557. package/dist/active-entities-3BAPHE4P.js +0 -103
  558. package/dist/activecampaign-IDBV26HH.js +0 -936
  559. package/dist/activecampaign-IDBV26HH.js.map +0 -1
  560. package/dist/activities-LKLPORDI.js +0 -75
  561. package/dist/ad-group-writes-HLBWN4E4.js +0 -170
  562. package/dist/ad-group-writes-HLBWN4E4.js.map +0 -1
  563. package/dist/ad-groups-33NZD6J3.js +0 -68
  564. package/dist/ad-groups-33NZD6J3.js.map +0 -1
  565. package/dist/ad-writes-7ZDNDZ2E.js +0 -174
  566. package/dist/ad-writes-7ZDNDZ2E.js.map +0 -1
  567. package/dist/add-AF42LQQQ.js +0 -105
  568. package/dist/add-AF42LQQQ.js.map +0 -1
  569. package/dist/add-LJRZYJ7I.js +0 -303
  570. package/dist/add-LJRZYJ7I.js.map +0 -1
  571. package/dist/ads-KBE5JXCH.js +0 -115
  572. package/dist/ads-LXWXOQHX.js +0 -48
  573. package/dist/ads-X3AM6M7L.js +0 -77
  574. package/dist/ads-X3AM6M7L.js.map +0 -1
  575. package/dist/adsets-YWBJFPAZ.js +0 -182
  576. package/dist/advertisers-6FOCN2W3.js +0 -121
  577. package/dist/advertisers-6FOCN2W3.js.map +0 -1
  578. package/dist/analytics-64HBRJJE.js +0 -2435
  579. package/dist/analytics-64HBRJJE.js.map +0 -1
  580. package/dist/analytics-VY5NL2GL.js +0 -445
  581. package/dist/analytics-VY5NL2GL.js.map +0 -1
  582. package/dist/asset-writes-72DEVXGO.js +0 -48
  583. package/dist/assign-N2I2BM67.js +0 -78
  584. package/dist/assign-N2I2BM67.js.map +0 -1
  585. package/dist/audience-size-H5DEZXJN.js +0 -74
  586. package/dist/audience-size-H5DEZXJN.js.map +0 -1
  587. package/dist/audience-writes-KCHLNFSI.js +0 -325
  588. package/dist/audience-writes-KCHLNFSI.js.map +0 -1
  589. package/dist/audiences-34IQKOGS.js +0 -85
  590. package/dist/audiences-QAH42HIM.js +0 -86
  591. package/dist/audiences-WCDWN64L.js +0 -268
  592. package/dist/audiences-WCDWN64L.js.map +0 -1
  593. package/dist/audit-2AAF6AOX.js +0 -152
  594. package/dist/audit-2AAF6AOX.js.map +0 -1
  595. package/dist/audit-7ED6CUTQ.js +0 -88
  596. package/dist/autocomplete-3GSKRNCZ.js +0 -112
  597. package/dist/autocomplete-3GSKRNCZ.js.map +0 -1
  598. package/dist/avatars-N6W6HUPP.js +0 -38
  599. package/dist/bid-pricing-IMITXHXN.js +0 -101
  600. package/dist/bid-pricing-IMITXHXN.js.map +0 -1
  601. package/dist/brand-ITWQVZD2.js +0 -22
  602. package/dist/brief-JJNEYPYB.js +0 -541
  603. package/dist/brief-JJNEYPYB.js.map +0 -1
  604. package/dist/businesses-MGP2YCEU.js +0 -54
  605. package/dist/campaign-groups-TTQLP32Q.js +0 -97
  606. package/dist/campaign-groups-TTQLP32Q.js.map +0 -1
  607. package/dist/campaign-writes-MAKPHQ3V.js +0 -166
  608. package/dist/campaign-writes-MAKPHQ3V.js.map +0 -1
  609. package/dist/campaign-writes-XO74BALZ.js +0 -174
  610. package/dist/campaign-writes-XO74BALZ.js.map +0 -1
  611. package/dist/campaigns-5BIDXYSR.js +0 -111
  612. package/dist/campaigns-LS65QM6W.js +0 -76
  613. package/dist/campaigns-LS65QM6W.js.map +0 -1
  614. package/dist/campaigns-XZOQ2VTK.js +0 -130
  615. package/dist/campaigns-XZPXCS7I.js +0 -111
  616. package/dist/campaigns-XZPXCS7I.js.map +0 -1
  617. package/dist/canvas-SL3RMOY5.js +0 -46
  618. package/dist/capabilities-LSR5GCE6.js +0 -145
  619. package/dist/capabilities-LSR5GCE6.js.map +0 -1
  620. package/dist/cards-A7GQVC7B.js +0 -85
  621. package/dist/catalogs-JLCSFZYC.js +0 -779
  622. package/dist/catalogs-JLCSFZYC.js.map +0 -1
  623. package/dist/catalogs-T23RKYFC.js +0 -128
  624. package/dist/catalogs-T23RKYFC.js.map +0 -1
  625. package/dist/changes-36C754R4.js +0 -135
  626. package/dist/chatgpt-3WFOPURY.js +0 -47
  627. package/dist/chats-GGYTXNJS.js +0 -277
  628. package/dist/chats-GGYTXNJS.js.map +0 -1
  629. package/dist/check-P7UPBBG7.js +0 -105
  630. package/dist/check-P7UPBBG7.js.map +0 -1
  631. package/dist/chunk-2TOIY2WN.js +0 -4254
  632. package/dist/chunk-3GAR4AZK.js +0 -149
  633. package/dist/chunk-4D46PS6J.js +0 -344
  634. package/dist/chunk-4GAEB6NK.js +0 -228
  635. package/dist/chunk-5XTGG4PV.js +0 -274
  636. package/dist/chunk-6JCX3YLM.js +0 -249
  637. package/dist/chunk-7J3NZBPV.js +0 -2982
  638. package/dist/chunk-7J3NZBPV.js.map +0 -1
  639. package/dist/chunk-7NF73SCB.js +0 -106
  640. package/dist/chunk-ALMYGH5U.js +0 -479
  641. package/dist/chunk-AQKRSEBQ.js +0 -103
  642. package/dist/chunk-B2POVFR2.js +0 -175
  643. package/dist/chunk-BL6RTOK3.js +0 -297
  644. package/dist/chunk-C6CBBZBO.js +0 -203
  645. package/dist/chunk-CCEDZTP7.js +0 -391
  646. package/dist/chunk-CCEDZTP7.js.map +0 -1
  647. package/dist/chunk-CKQTJ2LV.js +0 -89
  648. package/dist/chunk-D3KLDIPQ.js +0 -45
  649. package/dist/chunk-DL2UJNJ7.js +0 -8954
  650. package/dist/chunk-DM3Q6F5F.js +0 -26
  651. package/dist/chunk-DQ54POZN.js +0 -363
  652. package/dist/chunk-EDLZGTGN.js +0 -216
  653. package/dist/chunk-EDLZGTGN.js.map +0 -1
  654. package/dist/chunk-EXSHBYNQ.js +0 -349
  655. package/dist/chunk-EXSHBYNQ.js.map +0 -1
  656. package/dist/chunk-FFFJBNHA.js +0 -63
  657. package/dist/chunk-FKQK22IX.js +0 -51
  658. package/dist/chunk-FLK6QHOY.js +0 -142
  659. package/dist/chunk-GACSA5A6.js +0 -1646
  660. package/dist/chunk-GU5MXV2Y.js +0 -191
  661. package/dist/chunk-HGUYC5K6.js +0 -76
  662. package/dist/chunk-HJKYTNAZ.js +0 -61
  663. package/dist/chunk-HMIROUFV.js +0 -74
  664. package/dist/chunk-INUU3752.js +0 -392
  665. package/dist/chunk-IQHO2ABF.js +0 -197
  666. package/dist/chunk-J3UWMBOP.js +0 -547
  667. package/dist/chunk-JDR3HUEL.js +0 -191
  668. package/dist/chunk-JI77AKT6.js +0 -19
  669. package/dist/chunk-JNURZHZJ.js +0 -942
  670. package/dist/chunk-JSNMKTFM.js +0 -592
  671. package/dist/chunk-K4FLWDEX.js +0 -122
  672. package/dist/chunk-KBRJSPIM.js +0 -676
  673. package/dist/chunk-KUY26RCF.js +0 -200
  674. package/dist/chunk-LAC6YHHX.js +0 -97
  675. package/dist/chunk-M7HD42M6.js +0 -24017
  676. package/dist/chunk-M7HD42M6.js.map +0 -1
  677. package/dist/chunk-MGYC2IRC.js +0 -783
  678. package/dist/chunk-MI4HXE7M.js +0 -23
  679. package/dist/chunk-MJ7RNDD4.js +0 -910
  680. package/dist/chunk-OBJCNGZL.js +0 -207
  681. package/dist/chunk-OJGYYH6K.js +0 -179
  682. package/dist/chunk-OLBLXJNI.js +0 -224
  683. package/dist/chunk-PFTYKINE.js +0 -207
  684. package/dist/chunk-PLBITHV6.js +0 -846
  685. package/dist/chunk-Q6JMMBSQ.js +0 -831
  686. package/dist/chunk-RAQHUMKS.js +0 -169
  687. package/dist/chunk-RCJKABOS.js +0 -74
  688. package/dist/chunk-SA22KXWT.js +0 -163
  689. package/dist/chunk-SIXU5PDF.js +0 -66
  690. package/dist/chunk-SXMK5AEJ.js +0 -494
  691. package/dist/chunk-TLQOMWLQ.js +0 -69
  692. package/dist/chunk-TTLD66NI.js +0 -319
  693. package/dist/chunk-TVAIOC77.js +0 -287
  694. package/dist/chunk-TVTSA4EN.js +0 -188
  695. package/dist/chunk-V5NHJU3M.js +0 -604
  696. package/dist/chunk-VIPKDXGU.js +0 -4229
  697. package/dist/chunk-VIPKDXGU.js.map +0 -1
  698. package/dist/chunk-W4D7C74B.js +0 -387
  699. package/dist/chunk-WF25CCLD.js +0 -170
  700. package/dist/chunk-WQPUX3BA.js +0 -275
  701. package/dist/chunk-WR3FR3K3.js +0 -156
  702. package/dist/chunk-XDNJC62G.js +0 -91
  703. package/dist/chunk-XE6N4SZI.js +0 -429
  704. package/dist/chunk-XGPU2VDU.js +0 -219
  705. package/dist/chunk-XUJZO7MZ.js +0 -57
  706. package/dist/chunk-Y67LUJBE.js +0 -455
  707. package/dist/chunk-Y7XSDJEA.js +0 -3868
  708. package/dist/chunk-ZNNQK366.js +0 -7198
  709. package/dist/chunk-ZNNQK366.js.map +0 -1
  710. package/dist/chunk-ZNRGH4NS.js +0 -150
  711. package/dist/chunk-ZRP7Y2DM.js +0 -320
  712. package/dist/chunk-ZRP7Y2DM.js.map +0 -1
  713. package/dist/claim-4KUETSW3.js +0 -198
  714. package/dist/claim-4KUETSW3.js.map +0 -1
  715. package/dist/companies-XFO6WPVT.js +0 -196
  716. package/dist/companies-XFO6WPVT.js.map +0 -1
  717. package/dist/company-OJGISG7K.js +0 -306
  718. package/dist/company-OJGISG7K.js.map +0 -1
  719. package/dist/complete-CXOST5J3.js +0 -82
  720. package/dist/complete-CXOST5J3.js.map +0 -1
  721. package/dist/config-SMVIY6RW.js +0 -88
  722. package/dist/connect-HPQ32KGV.js +0 -43
  723. package/dist/conversation-D5HKCTDA.js +0 -94
  724. package/dist/conversation-D5HKCTDA.js.map +0 -1
  725. package/dist/conversion-report-DKXFHLLX.js +0 -125
  726. package/dist/conversion-report-DKXFHLLX.js.map +0 -1
  727. package/dist/conversion-upload-command-KTYAY7IG.js +0 -439
  728. package/dist/conversion-writes-7ODJDAUP.js +0 -120
  729. package/dist/conversion-writes-7ODJDAUP.js.map +0 -1
  730. package/dist/conversions-BKVGNNC6.js +0 -76
  731. package/dist/conversions-BKVGNNC6.js.map +0 -1
  732. package/dist/conversions-SYNDEB6D.js +0 -138
  733. package/dist/conversions-SYNDEB6D.js.map +0 -1
  734. package/dist/copy-writes-P4WK6OPM.js +0 -168
  735. package/dist/copy-writes-P4WK6OPM.js.map +0 -1
  736. package/dist/create-7D4VD4TC.js +0 -208
  737. package/dist/create-7D4VD4TC.js.map +0 -1
  738. package/dist/create-7QDEAWZS.js +0 -133
  739. package/dist/create-7QDEAWZS.js.map +0 -1
  740. package/dist/create-IQSYEC4M.js +0 -60
  741. package/dist/create-IQSYEC4M.js.map +0 -1
  742. package/dist/create-TQSCM7MG.js +0 -237
  743. package/dist/create-TQSCM7MG.js.map +0 -1
  744. package/dist/creatives-JPKA2RHU.js +0 -89
  745. package/dist/creatives-RNOL4F4E.js +0 -58
  746. package/dist/creatives-RXI27T2D.js +0 -221
  747. package/dist/creatives-RXI27T2D.js.map +0 -1
  748. package/dist/credentials-PYW55B52.js +0 -288
  749. package/dist/credentials-PYW55B52.js.map +0 -1
  750. package/dist/critique-2SYHNAW5.js +0 -1449
  751. package/dist/critique-2SYHNAW5.js.map +0 -1
  752. package/dist/critique-72GFZSHA.js +0 -230
  753. package/dist/critique-72GFZSHA.js.map +0 -1
  754. package/dist/crm-EATDSXXB.js +0 -225
  755. package/dist/crm-EATDSXXB.js.map +0 -1
  756. package/dist/crm-XXP3VBYD.js +0 -321
  757. package/dist/crm-XXP3VBYD.js.map +0 -1
  758. package/dist/currency-R4ORE2U3.js +0 -88
  759. package/dist/custom-conversions-5HJBB5XL.js +0 -128
  760. package/dist/customers-OFZTEXST.js +0 -57
  761. package/dist/delete-FGVZIK4R.js +0 -55
  762. package/dist/delete-FGVZIK4R.js.map +0 -1
  763. package/dist/delete-HBZZL4UA.js +0 -67
  764. package/dist/delete-HBZZL4UA.js.map +0 -1
  765. package/dist/delete-JOUXMRIX.js +0 -65
  766. package/dist/delete-JOUXMRIX.js.map +0 -1
  767. package/dist/demographics-SB7NBYOI.js +0 -139
  768. package/dist/demographics-SB7NBYOI.js.map +0 -1
  769. package/dist/discard-YYGIRDII.js +0 -67
  770. package/dist/discard-YYGIRDII.js.map +0 -1
  771. package/dist/discover-GSJRZUOC.js +0 -172
  772. package/dist/domain-3KRAJAUH.js +0 -99
  773. package/dist/domain-3KRAJAUH.js.map +0 -1
  774. package/dist/download-QCBKJ6OR.js +0 -170
  775. package/dist/download-QCBKJ6OR.js.map +0 -1
  776. package/dist/draft-7CGFFZTH.js +0 -333
  777. package/dist/draft-7CGFFZTH.js.map +0 -1
  778. package/dist/draft-BI4NW6AU.js +0 -308
  779. package/dist/draft-BI4NW6AU.js.map +0 -1
  780. package/dist/draft-DJIYEMZU.js +0 -103
  781. package/dist/draft-LPVK6YHI.js +0 -281
  782. package/dist/draft-LPVK6YHI.js.map +0 -1
  783. package/dist/draft-QF5JEUTH.js +0 -218
  784. package/dist/draft-QF5JEUTH.js.map +0 -1
  785. package/dist/draft-RIR2V6A2.js +0 -238
  786. package/dist/draft-WYDMLNYA.js +0 -308
  787. package/dist/draft-ZCL7FVBH.js +0 -100
  788. package/dist/experiment-I5CRLOVN.js +0 -1397
  789. package/dist/experiments-ZCEYRP3H.js +0 -234
  790. package/dist/experiments-ZCEYRP3H.js.map +0 -1
  791. package/dist/facets-G7ZDPI5Q.js +0 -115
  792. package/dist/facets-G7ZDPI5Q.js.map +0 -1
  793. package/dist/feedback-3U3CL2VB.js +0 -109
  794. package/dist/feedback-3U3CL2VB.js.map +0 -1
  795. package/dist/feedback-record-4ZHPENIP.js +0 -263
  796. package/dist/feedback-record-4ZHPENIP.js.map +0 -1
  797. package/dist/fetch-PNVNNWTP.js +0 -177
  798. package/dist/fetch-PNVNNWTP.js.map +0 -1
  799. package/dist/fit-53DGYRFD.js +0 -63
  800. package/dist/flows-JXLQBP5Q.js +0 -248
  801. package/dist/flows-JXLQBP5Q.js.map +0 -1
  802. package/dist/fonts-LFMBUT4R.js +0 -37
  803. package/dist/forecast-4AG5F7YC.js +0 -169
  804. package/dist/forecast-VZAXI74O.js +0 -119
  805. package/dist/forecast-VZAXI74O.js.map +0 -1
  806. package/dist/funding-5W4LX6DU.js +0 -85
  807. package/dist/funnel-EACC35UD.js +0 -395
  808. package/dist/funnel-EACC35UD.js.map +0 -1
  809. package/dist/ga4-BWVCDVIR.js +0 -55
  810. package/dist/get-AXBVYGAC.js +0 -57
  811. package/dist/get-AXBVYGAC.js.map +0 -1
  812. package/dist/get-D6A27Q4E.js +0 -80
  813. package/dist/get-D6A27Q4E.js.map +0 -1
  814. package/dist/google-NAA4BASO.js +0 -3267
  815. package/dist/google-ads-OIYUNDXQ.js +0 -196
  816. package/dist/google-ads-OIYUNDXQ.js.map +0 -1
  817. package/dist/gsc-2MPE4N32.js +0 -30
  818. package/dist/history-5MRLNTCI.js +0 -67
  819. package/dist/history-5MRLNTCI.js.map +0 -1
  820. package/dist/history-IDYNIB6R.js +0 -134
  821. package/dist/history-IDYNIB6R.js.map +0 -1
  822. package/dist/history-IOUKN3WD.js +0 -100
  823. package/dist/history-IOUKN3WD.js.map +0 -1
  824. package/dist/hubspot-HL6WGC4G.js +0 -780
  825. package/dist/hubspot-HL6WGC4G.js.map +0 -1
  826. package/dist/ideas-NK3KQHAK.js +0 -43
  827. package/dist/images-2XS3JT7E.js +0 -92
  828. package/dist/ingest-DHXWZZX4.js +0 -24
  829. package/dist/ingest-FGTJRCWK.js +0 -108
  830. package/dist/ingest-FGTJRCWK.js.map +0 -1
  831. package/dist/insights-M3CYB22P.js +0 -437
  832. package/dist/insights-M3CYB22P.js.map +0 -1
  833. package/dist/insights-XCT3ONC7.js +0 -130
  834. package/dist/insights-XCT3ONC7.js.map +0 -1
  835. package/dist/inspect-53GGYRC4.js +0 -190
  836. package/dist/inspect-53GGYRC4.js.map +0 -1
  837. package/dist/instant-experiences-HT3HB4QZ.js +0 -258
  838. package/dist/instant-experiences-HT3HB4QZ.js.map +0 -1
  839. package/dist/intent-NSHW7EJT.js +0 -95
  840. package/dist/job-DRFCQ27M.js +0 -202
  841. package/dist/job-create-2EC25Y3J.js +0 -109
  842. package/dist/job-status-UNVZRPIA.js +0 -74
  843. package/dist/keyword-gap-ITTWKBWZ.js +0 -130
  844. package/dist/keyword-metrics-LWPE3HHW.js +0 -198
  845. package/dist/keyword-metrics-LWPE3HHW.js.map +0 -1
  846. package/dist/keywords-for-site-5K25VJ35.js +0 -129
  847. package/dist/keywords-for-site-5K25VJ35.js.map +0 -1
  848. package/dist/landing-QONUUP3C.js +0 -28
  849. package/dist/languages-MEFQQBJ2.js +0 -40
  850. package/dist/leads-FSSISJGL.js +0 -113
  851. package/dist/leads-FSSISJGL.js.map +0 -1
  852. package/dist/leads-SZOGCQFK.js +0 -538
  853. package/dist/leads-SZOGCQFK.js.map +0 -1
  854. package/dist/learn-FWWJWBDN.js +0 -205
  855. package/dist/learn-FWWJWBDN.js.map +0 -1
  856. package/dist/line-item-writes-A3UQ44NG.js +0 -209
  857. package/dist/line-item-writes-A3UQ44NG.js.map +0 -1
  858. package/dist/line-items-OH426JGT.js +0 -107
  859. package/dist/link-67E4NVEX.js +0 -65
  860. package/dist/link-67E4NVEX.js.map +0 -1
  861. package/dist/linkedin-CT2OSQ2I.js +0 -1314
  862. package/dist/linkedin-CT2OSQ2I.js.map +0 -1
  863. package/dist/linkedin-person-OSNLPLJJ.js +0 -137
  864. package/dist/linkedin-person-OSNLPLJJ.js.map +0 -1
  865. package/dist/list-J4OUXAKN.js +0 -65
  866. package/dist/list-J4OUXAKN.js.map +0 -1
  867. package/dist/list-L2OQK4W3.js +0 -304
  868. package/dist/list-L2OQK4W3.js.map +0 -1
  869. package/dist/list-LHMDAA2D.js +0 -152
  870. package/dist/list-LHMDAA2D.js.map +0 -1
  871. package/dist/locations-RLWAS6AC.js +0 -40
  872. package/dist/locations-UKBOT6SB.js +0 -67
  873. package/dist/locations-UKBOT6SB.js.map +0 -1
  874. package/dist/log-4EIV54V4.js +0 -93
  875. package/dist/log-4EIV54V4.js.map +0 -1
  876. package/dist/lookup-ZJIP2M4X.js +0 -22
  877. package/dist/make-MFU3CSN7.js +0 -1368
  878. package/dist/make-MFU3CSN7.js.map +0 -1
  879. package/dist/map-VWWWMQLK.js +0 -434
  880. package/dist/map-VWWWMQLK.js.map +0 -1
  881. package/dist/mcp-EKLO2VD7.js +0 -715
  882. package/dist/mcp-EKLO2VD7.js.map +0 -1
  883. package/dist/media-XCTZJIW4.js +0 -89
  884. package/dist/media-ZWN7E777.js +0 -18
  885. package/dist/media-sources-7L622UTF.js +0 -35
  886. package/dist/members-QK5M5NCJ.js +0 -45
  887. package/dist/members-QK5M5NCJ.js.map +0 -1
  888. package/dist/meta-EHKXH257.js +0 -122
  889. package/dist/metrics-K6FDCMK7.js +0 -152
  890. package/dist/normalize-WI4OGKH5.js +0 -142
  891. package/dist/normalize-WI4OGKH5.js.map +0 -1
  892. package/dist/options-FKJ2QXI6.js +0 -123
  893. package/dist/options-FKJ2QXI6.js.map +0 -1
  894. package/dist/organization-7A7MPUDG.js +0 -947
  895. package/dist/organization-7A7MPUDG.js.map +0 -1
  896. package/dist/output-WTEPRUPE.js +0 -24
  897. package/dist/page-photos-HWKQOSCU.js +0 -116
  898. package/dist/page-photos-HWKQOSCU.js.map +0 -1
  899. package/dist/pages-J6AF5NDU.js +0 -67
  900. package/dist/performance-K4VB6L6Z.js +0 -25
  901. package/dist/performance-LHAL53YO.js +0 -5539
  902. package/dist/performance-LHAL53YO.js.map +0 -1
  903. package/dist/pixels-Z7ZGXAGB.js +0 -60
  904. package/dist/pixels-Z7ZGXAGB.js.map +0 -1
  905. package/dist/pixels-ZZTB6NWF.js +0 -109
  906. package/dist/plan-TVQSEKYL.js +0 -207
  907. package/dist/plan-TVQSEKYL.js.map +0 -1
  908. package/dist/preview-CWRGDFCP.js +0 -216
  909. package/dist/preview-CWRGDFCP.js.map +0 -1
  910. package/dist/promoted-tweet-writes-V4ZVJOJU.js +0 -181
  911. package/dist/promoted-tweet-writes-V4ZVJOJU.js.map +0 -1
  912. package/dist/promoted-tweets-KPG4IUVD.js +0 -119
  913. package/dist/properties-RBLJCVSG.js +0 -101
  914. package/dist/publish-Y465CVUD.js +0 -342
  915. package/dist/publish-Y465CVUD.js.map +0 -1
  916. package/dist/query-BJJYUGQZ.js +0 -247
  917. package/dist/query-KQ675KJZ.js +0 -236
  918. package/dist/query-QM7MBQD7.js +0 -62
  919. package/dist/questionnaire-LEZJLMAV.js +0 -93
  920. package/dist/questionnaire-LEZJLMAV.js.map +0 -1
  921. package/dist/read-QME7JYVF.js +0 -141
  922. package/dist/reddit-Z7DOVIGR.js +0 -27
  923. package/dist/refresh-A6TW2Z2F.js +0 -95
  924. package/dist/refresh-A6TW2Z2F.js.map +0 -1
  925. package/dist/release-UFESJ4TM.js +0 -61
  926. package/dist/release-UFESJ4TM.js.map +0 -1
  927. package/dist/relevant-pages-VOICMQ7U.js +0 -99
  928. package/dist/remove-YONNYA4G.js +0 -51
  929. package/dist/remove-YONNYA4G.js.map +0 -1
  930. package/dist/reopen-FYJU2IPO.js +0 -64
  931. package/dist/reopen-FYJU2IPO.js.map +0 -1
  932. package/dist/rerun-B5SBG6ZE.js +0 -93
  933. package/dist/rerun-B5SBG6ZE.js.map +0 -1
  934. package/dist/research-HW4EVOZU.js +0 -72
  935. package/dist/research-OV53DIBX.js +0 -263
  936. package/dist/research-OV53DIBX.js.map +0 -1
  937. package/dist/reset-R4SIQXFH.js +0 -55
  938. package/dist/reset-R4SIQXFH.js.map +0 -1
  939. package/dist/reset-X6ODAKYH.js +0 -55
  940. package/dist/reset-X6ODAKYH.js.map +0 -1
  941. package/dist/resolve-DNRJCLCR.js +0 -122
  942. package/dist/resolve-DNRJCLCR.js.map +0 -1
  943. package/dist/retry-D5MKBHUB.js +0 -63
  944. package/dist/retry-D5MKBHUB.js.map +0 -1
  945. package/dist/retry-DVFLE7JY.js +0 -61
  946. package/dist/retry-DVFLE7JY.js.map +0 -1
  947. package/dist/revenue-QGI6XWSK.js +0 -89
  948. package/dist/revenue-QGI6XWSK.js.map +0 -1
  949. package/dist/rule-writes-S3RN47OG.js +0 -523
  950. package/dist/rule-writes-S3RN47OG.js.map +0 -1
  951. package/dist/rules-KTJ2ZZ62.js +0 -217
  952. package/dist/rules-TR6BAC23.js +0 -97
  953. package/dist/rules-TR6BAC23.js.map +0 -1
  954. package/dist/rules-add-T5ZO5RLR.js +0 -463
  955. package/dist/rules-add-T5ZO5RLR.js.map +0 -1
  956. package/dist/run-WZ5IXWA4.js +0 -67
  957. package/dist/run-WZ5IXWA4.js.map +0 -1
  958. package/dist/run-YRR3KOUU.js +0 -68
  959. package/dist/scaffold-ad-DNUCGCIH.js +0 -1514
  960. package/dist/scaffold-ad-DNUCGCIH.js.map +0 -1
  961. package/dist/scaffold-static-ad-VR65EZAG.js +0 -1013
  962. package/dist/scaffold-static-ad-VR65EZAG.js.map +0 -1
  963. package/dist/scaffold-video-JLMKCCWE.js +0 -886
  964. package/dist/scaffold-video-JLMKCCWE.js.map +0 -1
  965. package/dist/schedule-VRHCVBZA.js +0 -62
  966. package/dist/schedule-VRHCVBZA.js.map +0 -1
  967. package/dist/scheduled-agents-DG7FTCUZ.js +0 -55
  968. package/dist/schema-WZKDWF5N.js +0 -133
  969. package/dist/schema-WZKDWF5N.js.map +0 -1
  970. package/dist/search-MN66QIKJ.js +0 -175
  971. package/dist/search-MN66QIKJ.js.map +0 -1
  972. package/dist/select-IPSM2BF2.js +0 -104
  973. package/dist/select-IPSM2BF2.js.map +0 -1
  974. package/dist/sends-6FI7WELX.js +0 -348
  975. package/dist/sends-6FI7WELX.js.map +0 -1
  976. package/dist/set-prompt-N6BD3DME.js +0 -196
  977. package/dist/set-prompt-N6BD3DME.js.map +0 -1
  978. package/dist/setup-links-GTA2AROS.js +0 -142
  979. package/dist/setup-links-GTA2AROS.js.map +0 -1
  980. package/dist/shared-ZFULUOPQ.js +0 -32
  981. package/dist/shopify-S4TG6WJH.js +0 -3956
  982. package/dist/shopify-S4TG6WJH.js.map +0 -1
  983. package/dist/site-NY622E3H.js +0 -178
  984. package/dist/site-NY622E3H.js.map +0 -1
  985. package/dist/sitemaps-F3HYH5ZP.js +0 -87
  986. package/dist/sites-JSMF72BY.js +0 -101
  987. package/dist/sources-4F2XO7Z6.js +0 -455
  988. package/dist/sources-4F2XO7Z6.js.map +0 -1
  989. package/dist/sources-562ITR77.js +0 -30
  990. package/dist/stale-JKM6MXJF.js +0 -74
  991. package/dist/stale-JKM6MXJF.js.map +0 -1
  992. package/dist/stats-QP4LFQZJ.js +0 -34
  993. package/dist/status-AUWMUDA4.js +0 -63
  994. package/dist/status-AUWMUDA4.js.map +0 -1
  995. package/dist/studies-ZOEUY6YP.js +0 -250
  996. package/dist/study-writes-DTGMCNFP.js +0 -468
  997. package/dist/study-writes-DTGMCNFP.js.map +0 -1
  998. package/dist/sync-76MCGHX4.js +0 -55
  999. package/dist/sync-76MCGHX4.js.map +0 -1
  1000. package/dist/sync-PHH65JFS.js +0 -279
  1001. package/dist/sync-definition-NJPT6ABG.js +0 -67
  1002. package/dist/tag-manager-F7PVTDBB.js +0 -43
  1003. package/dist/tags-5KBOJJ5R.js +0 -26
  1004. package/dist/tags-CSMLTHTU.js +0 -21
  1005. package/dist/tags-CSMLTHTU.js.map +0 -1
  1006. package/dist/tags-IFRZYM3G.js +0 -21
  1007. package/dist/tags-IFRZYM3G.js.map +0 -1
  1008. package/dist/tags-S44ADJ75.js +0 -21
  1009. package/dist/tags-S44ADJ75.js.map +0 -1
  1010. package/dist/tags-WR7IY3OT.js +0 -225
  1011. package/dist/tags-WR7IY3OT.js.map +0 -1
  1012. package/dist/targeting-VBQY3HUN.js +0 -760
  1013. package/dist/targeting-VBQY3HUN.js.map +0 -1
  1014. package/dist/targeting-constants-236ES5HE.js +0 -118
  1015. package/dist/targeting-criteria-FJWNK53T.js +0 -113
  1016. package/dist/targets-2EHMMXD4.js +0 -104
  1017. package/dist/targets-2EHMMXD4.js.map +0 -1
  1018. package/dist/terms-O6ODXEOK.js +0 -102
  1019. package/dist/testimonials-WAPFIGFJ.js +0 -32
  1020. package/dist/themes-B4LCQUXB.js +0 -95
  1021. package/dist/top-companies-DJ2XQKMW.js +0 -109
  1022. package/dist/top-companies-DJ2XQKMW.js.map +0 -1
  1023. package/dist/transcript-J3LGOHCM.js +0 -163
  1024. package/dist/transcript-J3LGOHCM.js.map +0 -1
  1025. package/dist/translate-6RXO4C6Z.js +0 -607
  1026. package/dist/translate-6RXO4C6Z.js.map +0 -1
  1027. package/dist/triggers-CYXPNHQB.js +0 -142
  1028. package/dist/triggers-CYXPNHQB.js.map +0 -1
  1029. package/dist/tweets-IUINLOXF.js +0 -123
  1030. package/dist/unlink-5FJI7XZB.js +0 -68
  1031. package/dist/unlink-5FJI7XZB.js.map +0 -1
  1032. package/dist/unstage-54ZE2SZK.js +0 -86
  1033. package/dist/unstage-54ZE2SZK.js.map +0 -1
  1034. package/dist/unstage-MDSSPUKV.js +0 -95
  1035. package/dist/unstage-MDSSPUKV.js.map +0 -1
  1036. package/dist/update-BVBFNFMO.js +0 -99
  1037. package/dist/update-BVBFNFMO.js.map +0 -1
  1038. package/dist/update-GV3T7ZRC.js +0 -190
  1039. package/dist/update-GV3T7ZRC.js.map +0 -1
  1040. package/dist/update-PUQWUGPJ.js +0 -64
  1041. package/dist/update-PUQWUGPJ.js.map +0 -1
  1042. package/dist/update-YQBK6C3L.js +0 -153
  1043. package/dist/update-YQBK6C3L.js.map +0 -1
  1044. package/dist/upload-PXT5JAEV.js +0 -127
  1045. package/dist/upload-PXT5JAEV.js.map +0 -1
  1046. package/dist/url-options-IHL4OU4C.js +0 -130
  1047. package/dist/url-options-IHL4OU4C.js.map +0 -1
  1048. package/dist/url-params-IYUI6SFJ.js +0 -99
  1049. package/dist/url-params-IYUI6SFJ.js.map +0 -1
  1050. package/dist/validate-AD7F7LQ5.js +0 -120
  1051. package/dist/validate-AD7F7LQ5.js.map +0 -1
  1052. package/dist/videos-ZJCTODEB.js +0 -41
  1053. package/dist/viewer-check-GWZNGWCO.js +0 -81
  1054. package/dist/web-76CWAZNW.js +0 -141
  1055. package/dist/web-76CWAZNW.js.map +0 -1
  1056. package/dist/winning-ads-W7GTXTX7.js +0 -86
  1057. package/dist/write-commands-5J47ZNO4.js +0 -206
  1058. package/dist/write-commands-K6M3RTVK.js +0 -1170
  1059. package/dist/write-commands-K6M3RTVK.js.map +0 -1
  1060. package/dist/write-commands-OTWH6BKZ.js +0 -713
  1061. package/dist/write-commands-VPU53DLB.js +0 -1498
  1062. package/dist/write-commands-VPU53DLB.js.map +0 -1
  1063. package/dist/x-V4NNNWRU.js +0 -47
  1064. /package/dist/{account-ZY655BIU.js.map → account-BA3IO3AN.js.map} +0 -0
  1065. /package/dist/{account-assets-O7IA37RE.js.map → account-assets-T3VVNBUG.js.map} +0 -0
  1066. /package/dist/{account-reads-SNOWDHHF.js.map → account-reads-5CXFLJ5Q.js.map} +0 -0
  1067. /package/dist/{accounts-FT2SRKMD.js.map → accounts-4R3MBNJG.js.map} +0 -0
  1068. /package/dist/{accounts-SNB65ZEW.js.map → accounts-5WF7VE7J.js.map} +0 -0
  1069. /package/dist/{accounts-K5XLEO6W.js.map → accounts-VPWCLF6X.js.map} +0 -0
  1070. /package/dist/{actions-4JYHXRFH.js.map → actions-D7OWCP36.js.map} +0 -0
  1071. /package/dist/{active-entities-3BAPHE4P.js.map → active-entities-WDPW7652.js.map} +0 -0
  1072. /package/dist/{activities-LKLPORDI.js.map → activities-WGPHYSFU.js.map} +0 -0
  1073. /package/dist/{ads-KBE5JXCH.js.map → ads-F7AUJWK7.js.map} +0 -0
  1074. /package/dist/{ads-LXWXOQHX.js.map → ads-OV3SMLKA.js.map} +0 -0
  1075. /package/dist/{adsets-YWBJFPAZ.js.map → adsets-XH2ULWPM.js.map} +0 -0
  1076. /package/dist/{asset-writes-72DEVXGO.js.map → asset-writes-4X3AJQ4Q.js.map} +0 -0
  1077. /package/dist/{audiences-QAH42HIM.js.map → audiences-MBBXWEOI.js.map} +0 -0
  1078. /package/dist/{audiences-34IQKOGS.js.map → audiences-YUG5JLL4.js.map} +0 -0
  1079. /package/dist/{audit-7ED6CUTQ.js.map → audit-WFXS5ELM.js.map} +0 -0
  1080. /package/dist/{avatars-N6W6HUPP.js.map → avatars-WZ2JDMHH.js.map} +0 -0
  1081. /package/dist/{brand-ITWQVZD2.js.map → brand-IZTTBZII.js.map} +0 -0
  1082. /package/dist/{businesses-MGP2YCEU.js.map → businesses-24JNY46Z.js.map} +0 -0
  1083. /package/dist/{campaigns-XZOQ2VTK.js.map → campaigns-KXYGSH27.js.map} +0 -0
  1084. /package/dist/{campaigns-5BIDXYSR.js.map → campaigns-U5FQ2VWL.js.map} +0 -0
  1085. /package/dist/{canvas-SL3RMOY5.js.map → canvas-IQ753Q2O.js.map} +0 -0
  1086. /package/dist/{cards-A7GQVC7B.js.map → cards-NSNAFTEB.js.map} +0 -0
  1087. /package/dist/{changes-36C754R4.js.map → changes-RDWMNSTK.js.map} +0 -0
  1088. /package/dist/{chatgpt-3WFOPURY.js.map → chatgpt-27NEJVGF.js.map} +0 -0
  1089. /package/dist/{chunk-KUY26RCF.js.map → chunk-2F4DELSV.js.map} +0 -0
  1090. /package/dist/{chunk-WF25CCLD.js.map → chunk-2GYCWRF3.js.map} +0 -0
  1091. /package/dist/{chunk-HJKYTNAZ.js.map → chunk-2L7F7KR4.js.map} +0 -0
  1092. /package/dist/{chunk-4GAEB6NK.js.map → chunk-44ZRCSR7.js.map} +0 -0
  1093. /package/dist/{chunk-2TOIY2WN.js.map → chunk-46YLDIQG.js.map} +0 -0
  1094. /package/dist/{chunk-DQ54POZN.js.map → chunk-4EDWXZ3I.js.map} +0 -0
  1095. /package/dist/{chunk-SIXU5PDF.js.map → chunk-4FFBGR5L.js.map} +0 -0
  1096. /package/dist/{chunk-JSNMKTFM.js.map → chunk-4UZUUSVL.js.map} +0 -0
  1097. /package/dist/{chunk-Q6JMMBSQ.js.map → chunk-4XHCEYHI.js.map} +0 -0
  1098. /package/dist/{chunk-ALMYGH5U.js.map → chunk-4Z6PVR3M.js.map} +0 -0
  1099. /package/dist/{chunk-K4FLWDEX.js.map → chunk-5Y5FZV2W.js.map} +0 -0
  1100. /package/dist/{chunk-INUU3752.js.map → chunk-6HJXLGDV.js.map} +0 -0
  1101. /package/dist/{chunk-XE6N4SZI.js.map → chunk-6S5CWGDA.js.map} +0 -0
  1102. /package/dist/{chunk-SXMK5AEJ.js.map → chunk-6VYROVWO.js.map} +0 -0
  1103. /package/dist/{chunk-TTLD66NI.js.map → chunk-AQRXXC6E.js.map} +0 -0
  1104. /package/dist/{chunk-W4D7C74B.js.map → chunk-ARBXT73X.js.map} +0 -0
  1105. /package/dist/{chunk-LAC6YHHX.js.map → chunk-BEZHQIEI.js.map} +0 -0
  1106. /package/dist/{chunk-J3UWMBOP.js.map → chunk-BFURWHVR.js.map} +0 -0
  1107. /package/dist/{chunk-RAQHUMKS.js.map → chunk-EZSPVWLQ.js.map} +0 -0
  1108. /package/dist/{chunk-DM3Q6F5F.js.map → chunk-FCHZ5TNG.js.map} +0 -0
  1109. /package/dist/{chunk-MI4HXE7M.js.map → chunk-FLWDFPXE.js.map} +0 -0
  1110. /package/dist/{chunk-PLBITHV6.js.map → chunk-FQMEX3GX.js.map} +0 -0
  1111. /package/dist/{chunk-FKQK22IX.js.map → chunk-GE3VT3CA.js.map} +0 -0
  1112. /package/dist/{chunk-HMIROUFV.js.map → chunk-HCQJYI6X.js.map} +0 -0
  1113. /package/dist/{chunk-FLK6QHOY.js.map → chunk-HGBJQGO5.js.map} +0 -0
  1114. /package/dist/{chunk-GU5MXV2Y.js.map → chunk-HHVWV5BJ.js.map} +0 -0
  1115. /package/dist/{chunk-HGUYC5K6.js.map → chunk-I3WGTSDY.js.map} +0 -0
  1116. /package/dist/{chunk-MGYC2IRC.js.map → chunk-I7AYMJZA.js.map} +0 -0
  1117. /package/dist/{chunk-7NF73SCB.js.map → chunk-IDSDJHRS.js.map} +0 -0
  1118. /package/dist/{chunk-OBJCNGZL.js.map → chunk-ILPHIYAL.js.map} +0 -0
  1119. /package/dist/{chunk-WR3FR3K3.js.map → chunk-IWKD56AY.js.map} +0 -0
  1120. /package/dist/{chunk-Y7XSDJEA.js.map → chunk-JLAQWMVF.js.map} +0 -0
  1121. /package/dist/{chunk-XUJZO7MZ.js.map → chunk-K6NULQN7.js.map} +0 -0
  1122. /package/dist/{chunk-JI77AKT6.js.map → chunk-L2BRAC2J.js.map} +0 -0
  1123. /package/dist/{chunk-Y67LUJBE.js.map → chunk-LGMI4LSY.js.map} +0 -0
  1124. /package/dist/{chunk-3GAR4AZK.js.map → chunk-LNODLR7W.js.map} +0 -0
  1125. /package/dist/{chunk-5XTGG4PV.js.map → chunk-LQ2BRGMX.js.map} +0 -0
  1126. /package/dist/{chunk-B2POVFR2.js.map → chunk-M7QZSEHF.js.map} +0 -0
  1127. /package/dist/{chunk-OJGYYH6K.js.map → chunk-NB2FU6EZ.js.map} +0 -0
  1128. /package/dist/{chunk-PFTYKINE.js.map → chunk-NFII3MTG.js.map} +0 -0
  1129. /package/dist/{chunk-WQPUX3BA.js.map → chunk-OG47L5GG.js.map} +0 -0
  1130. /package/dist/{chunk-4D46PS6J.js.map → chunk-QIOFOD4K.js.map} +0 -0
  1131. /package/dist/{chunk-6JCX3YLM.js.map → chunk-R2SYF5FC.js.map} +0 -0
  1132. /package/dist/{chunk-JNURZHZJ.js.map → chunk-RTH2I55B.js.map} +0 -0
  1133. /package/dist/{chunk-FFFJBNHA.js.map → chunk-S6VFDNSQ.js.map} +0 -0
  1134. /package/dist/{chunk-ZNRGH4NS.js.map → chunk-SG2TDQEE.js.map} +0 -0
  1135. /package/dist/{chunk-CKQTJ2LV.js.map → chunk-T3P6O2VU.js.map} +0 -0
  1136. /package/dist/{chunk-RCJKABOS.js.map → chunk-TU5LQUJM.js.map} +0 -0
  1137. /package/dist/{chunk-TLQOMWLQ.js.map → chunk-TU7DWSTW.js.map} +0 -0
  1138. /package/dist/{chunk-V5NHJU3M.js.map → chunk-TXDE2QJ3.js.map} +0 -0
  1139. /package/dist/{chunk-TVAIOC77.js.map → chunk-TYXZ2SRW.js.map} +0 -0
  1140. /package/dist/{chunk-C6CBBZBO.js.map → chunk-UDIEKCIR.js.map} +0 -0
  1141. /package/dist/{chunk-KBRJSPIM.js.map → chunk-UQHHGT67.js.map} +0 -0
  1142. /package/dist/{chunk-SA22KXWT.js.map → chunk-USCADMM3.js.map} +0 -0
  1143. /package/dist/{chunk-MJ7RNDD4.js.map → chunk-UUGISMNE.js.map} +0 -0
  1144. /package/dist/{chunk-IQHO2ABF.js.map → chunk-VDPOCAQ2.js.map} +0 -0
  1145. /package/dist/{chunk-AQKRSEBQ.js.map → chunk-VEJ3QX6M.js.map} +0 -0
  1146. /package/dist/{chunk-XDNJC62G.js.map → chunk-VFJB7OG6.js.map} +0 -0
  1147. /package/dist/{chunk-TVTSA4EN.js.map → chunk-VPABGAN4.js.map} +0 -0
  1148. /package/dist/{chunk-DL2UJNJ7.js.map → chunk-VRIPVLE7.js.map} +0 -0
  1149. /package/dist/{chunk-D3KLDIPQ.js.map → chunk-WLESMH4J.js.map} +0 -0
  1150. /package/dist/{chunk-OLBLXJNI.js.map → chunk-YILZR3XI.js.map} +0 -0
  1151. /package/dist/{chunk-JDR3HUEL.js.map → chunk-YJFLXOH4.js.map} +0 -0
  1152. /package/dist/{chunk-BL6RTOK3.js.map → chunk-YWHZYR6S.js.map} +0 -0
  1153. /package/dist/{chunk-XGPU2VDU.js.map → chunk-Z35KUMBW.js.map} +0 -0
  1154. /package/dist/{chunk-GACSA5A6.js.map → chunk-Z7I2ZFXS.js.map} +0 -0
  1155. /package/dist/{config-SMVIY6RW.js.map → config-55WGRLY3.js.map} +0 -0
  1156. /package/dist/{connect-HPQ32KGV.js.map → connect-3YY7MF3I.js.map} +0 -0
  1157. /package/dist/{conversion-upload-command-KTYAY7IG.js.map → conversion-upload-command-VM2P57K6.js.map} +0 -0
  1158. /package/dist/{creatives-RNOL4F4E.js.map → creatives-2DR3QHJW.js.map} +0 -0
  1159. /package/dist/{creatives-JPKA2RHU.js.map → creatives-DUR5Z5AN.js.map} +0 -0
  1160. /package/dist/{currency-R4ORE2U3.js.map → currency-X4KEACEP.js.map} +0 -0
  1161. /package/dist/{custom-conversions-5HJBB5XL.js.map → custom-conversions-OIA5Y2GX.js.map} +0 -0
  1162. /package/dist/{customers-OFZTEXST.js.map → customers-663K2OCP.js.map} +0 -0
  1163. /package/dist/{discover-GSJRZUOC.js.map → discover-2W42JB56.js.map} +0 -0
  1164. /package/dist/{draft-RIR2V6A2.js.map → draft-2ZX73IRO.js.map} +0 -0
  1165. /package/dist/{draft-WYDMLNYA.js.map → draft-CKLIIWXZ.js.map} +0 -0
  1166. /package/dist/{draft-ZCL7FVBH.js.map → draft-L5Q6KEER.js.map} +0 -0
  1167. /package/dist/{draft-DJIYEMZU.js.map → draft-MJRMZGMP.js.map} +0 -0
  1168. /package/dist/{experiment-I5CRLOVN.js.map → experiment-3VRHCQN5.js.map} +0 -0
  1169. /package/dist/{fit-53DGYRFD.js.map → fit-BEFCY2B4.js.map} +0 -0
  1170. /package/dist/{fonts-LFMBUT4R.js.map → fonts-C6XN5667.js.map} +0 -0
  1171. /package/dist/{forecast-4AG5F7YC.js.map → forecast-LYN6ZGQC.js.map} +0 -0
  1172. /package/dist/{funding-5W4LX6DU.js.map → funding-TCEPQXRQ.js.map} +0 -0
  1173. /package/dist/{ga4-BWVCDVIR.js.map → ga4-JE3HS36B.js.map} +0 -0
  1174. /package/dist/{google-NAA4BASO.js.map → google-24FDG4C4.js.map} +0 -0
  1175. /package/dist/{gsc-2MPE4N32.js.map → gsc-RMVOYIM3.js.map} +0 -0
  1176. /package/dist/{ideas-NK3KQHAK.js.map → ideas-M66FU45H.js.map} +0 -0
  1177. /package/dist/{images-2XS3JT7E.js.map → images-MM5OPUKV.js.map} +0 -0
  1178. /package/dist/{ingest-DHXWZZX4.js.map → ingest-KMLYCFF4.js.map} +0 -0
  1179. /package/dist/{intent-NSHW7EJT.js.map → intent-YCQCUCV3.js.map} +0 -0
  1180. /package/dist/{job-DRFCQ27M.js.map → job-SM2OQ2LO.js.map} +0 -0
  1181. /package/dist/{job-create-2EC25Y3J.js.map → job-create-ECZHPVKH.js.map} +0 -0
  1182. /package/dist/{job-status-UNVZRPIA.js.map → job-status-QSYDKIIV.js.map} +0 -0
  1183. /package/dist/{keyword-gap-ITTWKBWZ.js.map → keyword-gap-PUSF7EKY.js.map} +0 -0
  1184. /package/dist/{landing-QONUUP3C.js.map → landing-OZU5RRFV.js.map} +0 -0
  1185. /package/dist/{languages-MEFQQBJ2.js.map → languages-Q5SKO4AM.js.map} +0 -0
  1186. /package/dist/{line-items-OH426JGT.js.map → line-items-2V5FY33R.js.map} +0 -0
  1187. /package/dist/{locations-RLWAS6AC.js.map → locations-VQYREHYI.js.map} +0 -0
  1188. /package/dist/{lookup-ZJIP2M4X.js.map → lookup-MELV3RUL.js.map} +0 -0
  1189. /package/dist/{media-XCTZJIW4.js.map → media-BPI2VE6A.js.map} +0 -0
  1190. /package/dist/{media-ZWN7E777.js.map → media-EEWZZU3P.js.map} +0 -0
  1191. /package/dist/{media-sources-7L622UTF.js.map → media-sources-EQI3U4TC.js.map} +0 -0
  1192. /package/dist/{meta-EHKXH257.js.map → meta-SMJUQP37.js.map} +0 -0
  1193. /package/dist/{metrics-K6FDCMK7.js.map → metrics-EMAP7ESR.js.map} +0 -0
  1194. /package/dist/{output-WTEPRUPE.js.map → output-4QBQEM4C.js.map} +0 -0
  1195. /package/dist/{pages-J6AF5NDU.js.map → pages-DTQWQUKP.js.map} +0 -0
  1196. /package/dist/{performance-K4VB6L6Z.js.map → performance-NIF3CESZ.js.map} +0 -0
  1197. /package/dist/{pixels-ZZTB6NWF.js.map → pixels-2BKADWE6.js.map} +0 -0
  1198. /package/dist/{promoted-tweets-KPG4IUVD.js.map → promoted-tweets-653Q5AC6.js.map} +0 -0
  1199. /package/dist/{properties-RBLJCVSG.js.map → properties-VWKO3AAK.js.map} +0 -0
  1200. /package/dist/{query-QM7MBQD7.js.map → query-CXIOL7WI.js.map} +0 -0
  1201. /package/dist/{query-KQ675KJZ.js.map → query-OOP63DJF.js.map} +0 -0
  1202. /package/dist/{query-BJJYUGQZ.js.map → query-RBZFAIDK.js.map} +0 -0
  1203. /package/dist/{read-QME7JYVF.js.map → read-GOULD7YL.js.map} +0 -0
  1204. /package/dist/{reddit-Z7DOVIGR.js.map → reddit-JIHMAKAQ.js.map} +0 -0
  1205. /package/dist/{relevant-pages-VOICMQ7U.js.map → relevant-pages-FS7GBVXK.js.map} +0 -0
  1206. /package/dist/{research-HW4EVOZU.js.map → research-PNBACCCP.js.map} +0 -0
  1207. /package/dist/{rules-KTJ2ZZ62.js.map → rules-HY7S2YTD.js.map} +0 -0
  1208. /package/dist/{run-YRR3KOUU.js.map → run-QCNRR3CA.js.map} +0 -0
  1209. /package/dist/{scheduled-agents-DG7FTCUZ.js.map → scheduled-agents-OXYAVSIE.js.map} +0 -0
  1210. /package/dist/{shared-ZFULUOPQ.js.map → shared-CGEJI2RB.js.map} +0 -0
  1211. /package/dist/{sitemaps-F3HYH5ZP.js.map → sitemaps-5SP7PVQ6.js.map} +0 -0
  1212. /package/dist/{sites-JSMF72BY.js.map → sites-YZDPHBST.js.map} +0 -0
  1213. /package/dist/{sources-562ITR77.js.map → sources-FLUGHSVP.js.map} +0 -0
  1214. /package/dist/{stats-QP4LFQZJ.js.map → stats-EGGNFTKI.js.map} +0 -0
  1215. /package/dist/{studies-ZOEUY6YP.js.map → studies-6VUUOMZD.js.map} +0 -0
  1216. /package/dist/{sync-PHH65JFS.js.map → sync-SCM6JGJP.js.map} +0 -0
  1217. /package/dist/{sync-definition-NJPT6ABG.js.map → sync-definition-OGQ5XTQE.js.map} +0 -0
  1218. /package/dist/{tag-manager-F7PVTDBB.js.map → tag-manager-REKD4WGU.js.map} +0 -0
  1219. /package/dist/{tags-5KBOJJ5R.js.map → tags-CZTRQNXV.js.map} +0 -0
  1220. /package/dist/{targeting-constants-236ES5HE.js.map → targeting-constants-MRQB4N5I.js.map} +0 -0
  1221. /package/dist/{targeting-criteria-FJWNK53T.js.map → targeting-criteria-HSAESZIR.js.map} +0 -0
  1222. /package/dist/{terms-O6ODXEOK.js.map → terms-D2KAFHKJ.js.map} +0 -0
  1223. /package/dist/{testimonials-WAPFIGFJ.js.map → testimonials-G3OCNPBY.js.map} +0 -0
  1224. /package/dist/{themes-B4LCQUXB.js.map → themes-X56KIX3Z.js.map} +0 -0
  1225. /package/dist/{tweets-IUINLOXF.js.map → tweets-JN6ARKF6.js.map} +0 -0
  1226. /package/dist/{videos-ZJCTODEB.js.map → videos-36AXDUGZ.js.map} +0 -0
  1227. /package/dist/{viewer-check-GWZNGWCO.js.map → viewer-check-6HL4OUQY.js.map} +0 -0
  1228. /package/dist/{winning-ads-W7GTXTX7.js.map → winning-ads-GMM5W2O4.js.map} +0 -0
  1229. /package/dist/{write-commands-OTWH6BKZ.js.map → write-commands-B25W4FP5.js.map} +0 -0
  1230. /package/dist/{write-commands-5J47ZNO4.js.map → write-commands-GNNEUVDW.js.map} +0 -0
  1231. /package/dist/{x-V4NNNWRU.js.map → x-JNR5SO6F.js.map} +0 -0
@@ -1,4229 +0,0 @@
1
- import {
2
- ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN,
3
- ADVANTAGE_AUDIENCE_OPEN_AGE_MAX,
4
- AD_FORMATS,
5
- ASSET_FEED_CTA_TYPES,
6
- ATTRIBUTION_EVENT_TYPES,
7
- ATTRIBUTION_MAX_WINDOW_DAYS,
8
- BID_STRATEGIES,
9
- BID_STRATEGIES_FORBIDDING_AMOUNT,
10
- BID_STRATEGIES_REQUIRING_AMOUNT,
11
- BILLING_EVENTS,
12
- BUYING_TYPES,
13
- CREATIVE_UPDATE_STATUSES,
14
- CTA_TYPES,
15
- CURRENCY_MINIMUMS,
16
- CUSTOMER_FILE_SOURCES,
17
- CUSTOM_AUDIENCE_SUBTYPES,
18
- CUSTOM_EVENT_TYPES,
19
- DEFAULT_CURRENCY_MINIMUM,
20
- DESTINATION_TYPES,
21
- ENROLL_STATUSES,
22
- EU_DSA_COUNTRIES,
23
- FREQUENCY_CAP_EVENTS,
24
- FREQUENCY_CAP_TYPES,
25
- IMAGE_HASH_REGEX,
26
- LEAD_FORM_CTA_TYPES,
27
- MEDIA_KINDS,
28
- META_LIMITS,
29
- NUMERIC_ID_REGEX,
30
- OBJECTIVES,
31
- OPTIMIZATION_GOALS,
32
- OPTIMIZATION_GOALS_REQUIRING_APP,
33
- OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE,
34
- OPTIMIZATION_GOALS_REQUIRING_PAGE,
35
- OPTIMIZATION_GOALS_REQUIRING_PIXEL,
36
- OPTIMIZATION_GOALS_WITH_FREQUENCY_CAP,
37
- PACING_TYPES,
38
- ROAS_FLOOR_SCALE,
39
- SCHEDULE_TIMEZONE_TYPES,
40
- SPECIAL_AD_CATEGORIES,
41
- SPECIAL_CATEGORIES_REQUIRING_COUNTRY,
42
- STAGEABLE_CREATE_STATUSES,
43
- TEMP_REF_REGEX,
44
- UPDATE_STATUSES,
45
- adStudyCreateSchema,
46
- adStudyUpdateSchema
47
- } from "./chunk-GDFJOCDO.js";
48
-
49
- // ../api/src/ads-meta/customConversions.ts
50
- var RULE_OPERATORS = {
51
- eq: "is",
52
- neq: "is not",
53
- contains: "contains",
54
- i_contains: "contains",
55
- not_contains: "does not contain",
56
- i_not_contains: "does not contain",
57
- starts_with: "starts with",
58
- i_starts_with: "starts with",
59
- ends_with: "ends with",
60
- i_ends_with: "ends with",
61
- gt: "is more than",
62
- gte: "is at least",
63
- lt: "is less than",
64
- lte: "is at most",
65
- regex_match: "matches",
66
- exists: "exists"
67
- };
68
- function isRecord(value) {
69
- return typeof value === "object" && value !== null && !Array.isArray(value);
70
- }
71
- var DEFAULT_CUSTOM_CONVERSION_EVENT = "PageView";
72
- function buildCustomConversionRule(input) {
73
- return {
74
- and: [
75
- { event: { eq: input.event ?? DEFAULT_CUSTOM_CONVERSION_EVENT } },
76
- { URL: { i_contains: input.urlContains } }
77
- ]
78
- };
79
- }
80
- function customConversionRuleRefusal(rule) {
81
- const refusal = ruleNodeRefusal(rule, "rule");
82
- if (refusal) {
83
- return refusal;
84
- }
85
- if (!ruleFields(rule).some((field) => field !== "event")) {
86
- return 'rule only names the event, and Meta refuses a custom conversion with no condition beyond it \u2014 narrow it with a URL, referrer or event parameter the event carries, e.g. {"and":[{"event":{"eq":"Lead"}},{"URL":{"i_contains":"/gracias"}}]}';
87
- }
88
- return void 0;
89
- }
90
- function ruleFields(node) {
91
- if (!isRecord(node)) {
92
- return [];
93
- }
94
- return Object.entries(node).flatMap(
95
- ([key, value]) => (key === "and" || key === "or") && Array.isArray(value) ? value.flatMap(ruleFields) : [key]
96
- );
97
- }
98
- function branchRefusal(key, value, path) {
99
- if (!Array.isArray(value) || value.length === 0) {
100
- return `${path}.${key} must be a non-empty array of conditions \u2014 an empty one counts every event the pixel sends`;
101
- }
102
- for (const [index, child] of value.entries()) {
103
- const refusal = ruleNodeRefusal(child, `${path}.${key}[${index}]`);
104
- if (refusal) {
105
- return refusal;
106
- }
107
- }
108
- return void 0;
109
- }
110
- function conditionRefusal(key, value, path) {
111
- return key === "and" || key === "or" ? branchRefusal(key, value, path) : leafRefusal(key, value, path);
112
- }
113
- function ruleNodeRefusal(node, path) {
114
- if (!isRecord(node)) {
115
- return `${path} must be an object like {"URL":{"i_contains":"/thank-you"}}`;
116
- }
117
- const entries = Object.entries(node);
118
- if (entries.length === 0) {
119
- return `${path} is empty \u2014 a rule with no condition counts every event the pixel sends`;
120
- }
121
- if (entries.length > 1) {
122
- return `${path} names ${entries.length} conditions side by side (${entries.map(([key]) => key).join(", ")}) \u2014 Meta reads one branch or one field test per object, so combine them with {"and":[\u2026]}`;
123
- }
124
- for (const [key, value] of entries) {
125
- const refusal = conditionRefusal(key, value, path);
126
- if (refusal) {
127
- return refusal;
128
- }
129
- }
130
- return void 0;
131
- }
132
- function leafRefusal(field, condition, path) {
133
- if (!isRecord(condition)) {
134
- return `${path}.${field} must be a test like {"i_contains":"/thank-you"}, not a bare value`;
135
- }
136
- const tests = Object.entries(condition);
137
- if (tests.length === 0) {
138
- return `${path}.${field} names no test \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")}`;
139
- }
140
- if (tests.length > 1) {
141
- return `${path}.${field} names ${tests.length} operators at once (${tests.map(([operator]) => operator).join(", ")}) \u2014 test a field once per condition and combine them with {"and":[\u2026]}`;
142
- }
143
- for (const [operator] of tests) {
144
- if (!RULE_OPERATORS[operator]) {
145
- return `${path}.${field} uses "${operator}", which is not a Meta rule operator \u2014 use one of ${Object.keys(RULE_OPERATORS).join(", ")} (URL matching is i_contains, not contains or includes)`;
146
- }
147
- }
148
- return void 0;
149
- }
150
-
151
- // ../api/src/ads-meta/leadAds.ts
152
- var META_LEAD_ADS_NOT_ENABLED_MESSAGE = "Using Meta instant forms and their leads is not switched on for this company. Everything else on Meta keeps working. Tell the user this needs switching on by the Baker team, and carry on with the rest of the job.";
153
- var META_LEAD_ADS_RECONNECT_MESSAGE = "This Meta connection was made before lead ads were switched on for this company, so it cannot work with instant forms or read their leads. Ask the user to reconnect Meta in the dashboard \u2014 that grants the extra permissions \u2014 then ask for this again. Everything else on Meta keeps working meanwhile.";
154
- function isMetaLeadAdsRefusal(message) {
155
- return message === META_LEAD_ADS_NOT_ENABLED_MESSAGE || message === META_LEAD_ADS_RECONNECT_MESSAGE;
156
- }
157
-
158
- // ../api/src/ads-meta/placements.ts
159
- var FACEBOOK_POSITIONS_REQUIRING_FEED = ["marketplace", "search", "profile_feed", "notification"];
160
- var PLACEMENT_TARGETING_DOC = "https://developers.facebook.com/docs/marketing-api/audiences/reference/placement-targeting/";
161
- var PUBLISHER_PLATFORMS = ["facebook", "instagram", "threads", "messenger", "audience_network"];
162
- var FACEBOOK_POSITIONS = [
163
- "feed",
164
- "right_hand_column",
165
- "marketplace",
166
- "story",
167
- "search",
168
- "instream_video",
169
- "facebook_reels",
170
- "facebook_reels_overlay",
171
- "profile_feed",
172
- "notification"
173
- ];
174
- var INSTAGRAM_POSITIONS = [
175
- "stream",
176
- "story",
177
- "explore_home",
178
- "reels",
179
- "profile_feed",
180
- "ig_search",
181
- "profile_reels"
182
- ];
183
- var AUDIENCE_NETWORK_POSITIONS = ["classic", "rewarded_video"];
184
- var MESSENGER_POSITIONS = ["sponsored_messages"];
185
- var THREADS_POSITIONS = ["threads_stream"];
186
- var DEVICE_PLATFORMS = ["mobile", "desktop", "connected_tv"];
187
- var PLACEMENT_VOCABULARIES = {
188
- publisher_platforms: PUBLISHER_PLATFORMS,
189
- facebook_positions: FACEBOOK_POSITIONS,
190
- instagram_positions: INSTAGRAM_POSITIONS,
191
- audience_network_positions: AUDIENCE_NETWORK_POSITIONS,
192
- messenger_positions: MESSENGER_POSITIONS,
193
- threads_positions: THREADS_POSITIONS,
194
- device_platforms: DEVICE_PLATFORMS
195
- };
196
- var SAME_SURFACE_ON_THIS_PLATFORM = {
197
- facebook_positions: { reels: "facebook_reels", stream: "feed", stories: "story", ig_search: "search" },
198
- instagram_positions: {
199
- feed: "stream",
200
- facebook_reels: "reels",
201
- stories: "story",
202
- search: "ig_search"
203
- }
204
- };
205
- var RETIRED_PLACEMENTS = {
206
- facebook_positions: {
207
- video_feeds: 'Meta retired Facebook video feeds \u2014 use "instream_video" for in-stream video, or "facebook_reels", and drop "video_feeds"'
208
- },
209
- // v26.0, re-swept 2026-10-15: `explore` is refused (subcode 2490589, "IG
210
- // Explore placement is deprecated for this API version"); `explore_home`
211
- // validates on its own.
212
- instagram_positions: {
213
- explore: 'Meta retired Instagram Explore \u2014 drop "explore"; "explore_home" (Explore home) still runs on its own'
214
- },
215
- // v26.0 takes Messenger `story` and silently drops it from the ad set (every
216
- // version from 2026-10-27), so what was staged would never be what runs.
217
- messenger_positions: {
218
- story: 'Meta retired Messenger Stories \u2014 drop "story" from messenger_positions; Facebook and Instagram "story" still run'
219
- }
220
- };
221
- function placementFieldsAccepting(value, except) {
222
- return Object.keys(PLACEMENT_VOCABULARIES).filter(
223
- (field) => field !== except && PLACEMENT_VOCABULARIES[field].includes(value)
224
- );
225
- }
226
- function placementValueIssue(field, value) {
227
- const retired = RETIRED_PLACEMENTS[field]?.[value];
228
- if (retired) {
229
- return { field, value, kind: "retired", fix: retired };
230
- }
231
- const renamed = SAME_SURFACE_ON_THIS_PLATFORM[field]?.[value];
232
- if (renamed) {
233
- return {
234
- field,
235
- value,
236
- kind: "wrong-field",
237
- fix: `Meta calls that surface "${renamed}" in ${field} \u2014 use "${renamed}"`
238
- };
239
- }
240
- const elsewhere = placementFieldsAccepting(value, field);
241
- if (elsewhere.length > 0) {
242
- return {
243
- field,
244
- value,
245
- kind: "wrong-field",
246
- fix: `"${value}" belongs to ${elsewhere.join(" / ")}, not ${field} \u2014 move it there or drop it`
247
- };
248
- }
249
- return {
250
- field,
251
- value,
252
- kind: "unknown",
253
- fix: `"${value}" is not a placement Baker knows; ${field} accepts ${PLACEMENT_VOCABULARIES[field].join(", ")}`
254
- };
255
- }
256
- function invalidPlacementValues(targeting) {
257
- const issues = [];
258
- for (const field of Object.keys(PLACEMENT_VOCABULARIES)) {
259
- const allowed = PLACEMENT_VOCABULARIES[field];
260
- const selected = targeting?.[field] ?? [];
261
- for (const value of selected) {
262
- if (!allowed.includes(value)) {
263
- issues.push(placementValueIssue(field, value));
264
- }
265
- }
266
- }
267
- return issues;
268
- }
269
- function placementCoRequirementIssues(targeting) {
270
- const facebook = targeting?.facebook_positions ?? [];
271
- const instagram = targeting?.instagram_positions ?? [];
272
- const threads = targeting?.threads_positions ?? [];
273
- const devices = targeting?.device_platforms;
274
- const issues = [];
275
- if (facebook.includes("story")) {
276
- if (!facebook.includes("feed") && !instagram.includes("story")) {
277
- issues.push(
278
- 'Meta refuses Facebook "story" on its own \u2014 select "feed" in facebook_positions or "story" in instagram_positions alongside it'
279
- );
280
- }
281
- if (devices && !devices.includes("mobile")) {
282
- issues.push(
283
- 'Facebook "story" only runs on mobile \u2014 add "mobile" to device_platforms or drop the story placement'
284
- );
285
- }
286
- }
287
- if (threads.includes("threads_stream") && !instagram.includes("stream")) {
288
- issues.push('Threads "threads_stream" cannot be selected alone \u2014 add "stream" to instagram_positions');
289
- }
290
- return issues;
291
- }
292
- var CONSTRAINED_PLACEMENTS = [
293
- {
294
- position: "facebook_reels_overlay",
295
- reportedAs: "facebook_reels_overlay",
296
- platform: "facebook",
297
- kind: "constraint",
298
- note: "Ads on Facebook Reels take two shapes and a stock 9:16 video fits neither: overlay ads are 'a single, static image ad' (JPG/PNG, 1:1, 0% ratio tolerance, headline capped at 10 characters), and post-loop ads are 1:1 video of 4-15 seconds. Expect a long-headline 9:16 creative to look wrong here.",
299
- contested: false,
300
- source: "https://www.facebook.com/business/ads-guide/update/image/facebook-facebook-reels-overlay"
301
- },
302
- {
303
- position: "explore_home",
304
- reportedAs: "instagram_explore_grid_home",
305
- platform: "instagram",
306
- kind: "constraint",
307
- note: "Marketing API placement asset customization states 'The explore_home placement only supports the SINGLE_IMAGE format', but Meta's own Ads Guide lists Instagram Explore home under video specs. Check the account's play rate for this position before treating it as image-only.",
308
- contested: true,
309
- source: "https://developers.facebook.com/docs/marketing-api/dynamic-creative/placement-asset-customization/"
310
- },
311
- {
312
- position: "right_hand_column",
313
- reportedAs: "right_hand_column",
314
- platform: "facebook",
315
- kind: "correction",
316
- note: "Facebook right column publishes full video specs (MP4/MOV/GIF, 1:1 at 1440x1440 or mobile-only 4:5 at 1440x1800, 1 second to 241 minutes) \u2014 it is NOT image-only. Its real constraint is that it cannot be the only placement for a video, collection, or canvas ad.",
317
- contested: false,
318
- source: "https://www.facebook.com/business/ads-guide/update/video/facebook-right-hand-column"
319
- }
320
- ];
321
- var FACEBOOK_PREVIEW_FORMATS = {
322
- feed: "MOBILE_FEED_STANDARD",
323
- right_hand_column: "RIGHT_COLUMN_STANDARD",
324
- marketplace: "MARKETPLACE_MOBILE",
325
- facebook_stories: "FACEBOOK_STORY_MOBILE",
326
- facebook_reels: "FACEBOOK_REELS_MOBILE",
327
- facebook_reels_overlay: "FACEBOOK_REELS_BANNER",
328
- instream_video: "INSTREAM_VIDEO_MOBILE",
329
- // In the v25.0 ad_format enum and rendered live (2026-10-14).
330
- facebook_profile_feed: "FACEBOOK_PROFILE_FEED_MOBILE",
331
- // Retired for targeting (RETIRED_PLACEMENTS) and still reported by a breakdown
332
- // over any window that predates the retirement — an ad set created before it
333
- // keeps delivering there. Previewing what a historic row measured has to keep
334
- // working, so this stays.
335
- video_feeds: "INSTREAM_VIDEO_MOBILE"
336
- };
337
- var INSTAGRAM_PREVIEW_FORMATS = {
338
- feed: "INSTAGRAM_STANDARD",
339
- instagram_stories: "INSTAGRAM_STORY",
340
- instagram_reels: "INSTAGRAM_REELS",
341
- instagram_explore: "INSTAGRAM_EXPLORE_CONTEXTUAL",
342
- instagram_explore_grid_home: "INSTAGRAM_EXPLORE_GRID_HOME",
343
- instagram_search: "INSTAGRAM_SEARCH_CHAIN",
344
- instagram_profile_feed: "INSTAGRAM_PROFILE_FEED"
345
- };
346
- var PLATFORM_SCOPED_POSITIONS = /* @__PURE__ */ new Set(["feed"]);
347
- function previewFormatForPosition(position, platform) {
348
- if (platform === "facebook") return FACEBOOK_PREVIEW_FORMATS[position];
349
- if (platform === "instagram") return INSTAGRAM_PREVIEW_FORMATS[position];
350
- if (PLATFORM_SCOPED_POSITIONS.has(position)) return void 0;
351
- return FACEBOOK_PREVIEW_FORMATS[position] ?? INSTAGRAM_PREVIEW_FORMATS[position];
352
- }
353
- function placementFormatNote(reportedPosition) {
354
- return CONSTRAINED_PLACEMENTS.find((p) => p.reportedAs === reportedPosition);
355
- }
356
- function positionsMissingRequiredFeed(targeting) {
357
- const positions = targeting?.facebook_positions;
358
- if (!positions?.length || positions.includes("feed")) {
359
- return [];
360
- }
361
- return FACEBOOK_POSITIONS_REQUIRING_FEED.filter((required) => positions.includes(required));
362
- }
363
-
364
- // ../api/src/ads-meta/brandSafety.ts
365
- import { z } from "zod";
366
- var publisherSchema = z.string().trim().min(3).max(2048).refine((value) => !/\s/.test(value), "a site or app address has no spaces");
367
- var PUBLISHER_BLOCK_LIST_MAX_URLS = 1e4;
368
- var publisherBlockListCreateSchema = z.strictObject({
369
- name: z.string().trim().min(1).max(100),
370
- /** The sites and apps to keep ads off. */
371
- urls: z.array(publisherSchema).min(1).max(PUBLISHER_BLOCK_LIST_MAX_URLS)
372
- });
373
- var publisherBlockListUpdateSchema = z.strictObject({
374
- /** More sites and apps to keep ads off. Meta takes none off a list. */
375
- addUrls: z.array(publisherSchema).min(1).max(PUBLISHER_BLOCK_LIST_MAX_URLS).optional(),
376
- status: z.literal("DELETED").optional()
377
- }).refine((p) => p.addUrls === void 0 !== (p.status === void 0), "add urls OR delete the list");
378
- var CONTENT_FILTER_LEVELS = [
379
- "FACEBOOK_RELAXED",
380
- "FACEBOOK_STANDARD",
381
- "FACEBOOK_STRICT",
382
- "AN_RELAXED",
383
- "AN_STANDARD",
384
- "AN_STRICT",
385
- "FEED_RELAXED",
386
- "FEED_STANDARD",
387
- "FEED_STRICT"
388
- ];
389
- var EXCLUDED_PUBLISHER_CATEGORIES = [
390
- "dating",
391
- "gambling",
392
- "debated_social_issues",
393
- "mature_audiences",
394
- "tragedy_and_conflict"
395
- ];
396
- var blockListRefSchema = z.union([z.string().regex(/^\d+$/), z.string().regex(TEMP_REF_REGEX)]);
397
- var brandSafetyTargetingFields = {
398
- excluded_publisher_list_ids: z.array(blockListRefSchema).min(1).optional(),
399
- brand_safety_content_filter_levels: z.array(z.enum(CONTENT_FILTER_LEVELS)).min(1).refine(
400
- (levels) => new Set(levels.map((level) => level.split("_")[0])).size === levels.length,
401
- "one content filter level per family (FACEBOOK, AN, FEED)"
402
- ).optional(),
403
- excluded_publisher_categories: z.array(z.enum(EXCLUDED_PUBLISHER_CATEGORIES)).min(1).optional()
404
- };
405
- var BRAND_SAFETY_KEYS = new Set(Object.keys(brandSafetyTargetingFields));
406
-
407
- // ../api/src/ads-meta/catalogs.ts
408
- import { z as z2 } from "zod";
409
- var tempRefSchema = z2.string().regex(TEMP_REF_REGEX, "expected a meta_temp_* reference");
410
- var catalogRefSchema = z2.union([z2.string().regex(NUMERIC_ID_REGEX, "expected a numeric id"), tempRefSchema]);
411
- var httpsUrlSchema = z2.string().url().refine((value) => value.startsWith("https://"), "must be an https URL");
412
- var CATALOG_LIMITS = {
413
- nameMax: 100,
414
- productNameMax: 200,
415
- descriptionMax: 9999,
416
- retailerIdMax: 100,
417
- brandMax: 100,
418
- additionalImagesMax: 20,
419
- filterValuesMax: 500
420
- };
421
- var eventSourcesSchema = z2.array(z2.string().regex(NUMERIC_ID_REGEX)).min(1).max(10);
422
- var productCatalogCreateSchema = z2.strictObject({
423
- name: z2.string().trim().min(1).max(CATALOG_LIMITS.nameMax),
424
- /** The Business it is made on — filled at staging from the ad account's own Business; any other is refused. */
425
- business_id: z2.string().regex(NUMERIC_ID_REGEX).optional(),
426
- /**
427
- * Pixels to connect once it exists. Advantage+ catalog ads need one: live on
428
- * v26.0 a catalog ad set on a catalog without one was refused — "An event
429
- * source (Facebook Pixel or App) is required to run Dynamic Ads" (1885059).
430
- */
431
- event_sources: eventSourcesSchema.optional()
432
- });
433
- var productCatalogUpdateSchema = z2.strictObject({
434
- name: z2.string().trim().min(1).max(CATALOG_LIMITS.nameMax).optional(),
435
- event_sources: eventSourcesSchema.optional(),
436
- unlink_event_sources: eventSourcesSchema.optional(),
437
- status: z2.literal("DELETED").optional()
438
- }).superRefine((p, ctx) => {
439
- const changes = [p.name, p.event_sources, p.unlink_event_sources].filter((value) => value !== void 0).length;
440
- if (p.status === "DELETED" && changes > 0) {
441
- ctx.addIssue({ code: "custom", message: "a catalog delete changes nothing else" });
442
- }
443
- if (p.status === void 0 && changes === 0) {
444
- ctx.addIssue({ code: "custom", message: "rename the catalog, connect or disconnect a pixel, or delete it" });
445
- }
446
- const both = (p.event_sources ?? []).filter((id) => p.unlink_event_sources?.includes(id));
447
- if (both.length > 0) {
448
- ctx.addIssue({ code: "custom", message: `pixel ${both.join(", ")} is both connected and disconnected` });
449
- }
450
- });
451
- var PRODUCT_AVAILABILITIES = [
452
- "in stock",
453
- "out of stock",
454
- "preorder",
455
- "available for order",
456
- "discontinued"
457
- ];
458
- var PRODUCT_CONDITIONS = ["new", "refurbished", "used"];
459
- var priceSchema = z2.string().regex(/^\d{1,9}(\.\d{1,2})?$/, 'a price in major units, e.g. "19.99"');
460
- var currencySchema = z2.string().regex(/^[A-Z]{3}$/, "a three-letter currency code, e.g. EUR");
461
- var productFields = {
462
- name: z2.string().trim().min(1).max(CATALOG_LIMITS.productNameMax),
463
- description: z2.string().trim().min(1).max(CATALOG_LIMITS.descriptionMax),
464
- price: priceSchema,
465
- sale_price: priceSchema,
466
- currency: currencySchema,
467
- availability: z2.enum(PRODUCT_AVAILABILITIES),
468
- condition: z2.enum(PRODUCT_CONDITIONS),
469
- /** The product's own page — where its ad sends people. */
470
- url: httpsUrlSchema,
471
- /** A picture Meta fetches: a public https address (a library image's address works). */
472
- image_url: httpsUrlSchema,
473
- additional_image_urls: z2.array(httpsUrlSchema).min(1).max(CATALOG_LIMITS.additionalImagesMax),
474
- brand: z2.string().trim().min(1).max(CATALOG_LIMITS.brandMax)
475
- };
476
- var productCreateSchema = z2.strictObject({
477
- catalog_id: catalogRefSchema,
478
- /** The advertiser's own id for the product (Meta's `retailer_id`, the SKU) — what a product set filters on. */
479
- retailer_id: z2.string().trim().min(1).max(CATALOG_LIMITS.retailerIdMax),
480
- name: productFields.name,
481
- description: productFields.description,
482
- price: productFields.price,
483
- sale_price: productFields.sale_price.optional(),
484
- currency: productFields.currency,
485
- availability: productFields.availability.default("in stock"),
486
- condition: productFields.condition.default("new"),
487
- url: productFields.url,
488
- image_url: productFields.image_url,
489
- additional_image_urls: productFields.additional_image_urls.optional(),
490
- brand: productFields.brand.optional()
491
- });
492
- var productUpdateSchema = z2.strictObject({
493
- name: productFields.name.optional(),
494
- description: productFields.description.optional(),
495
- price: productFields.price.optional(),
496
- sale_price: productFields.sale_price.optional(),
497
- currency: productFields.currency.optional(),
498
- availability: productFields.availability.optional(),
499
- condition: productFields.condition.optional(),
500
- url: productFields.url.optional(),
501
- image_url: productFields.image_url.optional(),
502
- additional_image_urls: productFields.additional_image_urls.optional(),
503
- brand: productFields.brand.optional(),
504
- status: z2.literal("DELETED").optional()
505
- }).superRefine((p, ctx) => {
506
- const changes = Object.keys(p).filter((key) => key !== "status");
507
- if (p.status === "DELETED" && changes.length > 0) {
508
- ctx.addIssue({ code: "custom", message: "a product delete changes nothing else" });
509
- }
510
- if (p.status === void 0 && changes.length === 0) {
511
- ctx.addIssue({ code: "custom", message: "change at least one field, or delete the product" });
512
- }
513
- if ((p.price !== void 0 || p.sale_price !== void 0) && p.currency === void 0) {
514
- ctx.addIssue({ code: "custom", path: ["currency"], message: "a price names its currency" });
515
- }
516
- });
517
- var LIST_OPERATORS = ["is_any", "is_not_any"];
518
- var NUMBER_OPERATORS = ["lt", "lte", "gt", "gte"];
519
- var TEXT_OPERATORS = [
520
- "eq",
521
- "neq",
522
- "contains",
523
- "not_contains",
524
- "i_contains",
525
- "i_not_contains",
526
- "starts_with"
527
- ];
528
- var PRODUCT_SET_OPERATORS = [...LIST_OPERATORS, ...NUMBER_OPERATORS, ...TEXT_OPERATORS];
529
- var conditionSchema = z2.union([
530
- ...LIST_OPERATORS.map(
531
- (operator) => z2.strictObject({ [operator]: z2.array(z2.string().min(1)).min(1).max(CATALOG_LIMITS.filterValuesMax) })
532
- ),
533
- ...NUMBER_OPERATORS.map((operator) => z2.strictObject({ [operator]: z2.number() })),
534
- ...TEXT_OPERATORS.map((operator) => z2.strictObject({ [operator]: z2.string().min(1) }))
535
- ]);
536
- var FIELD_NAME_REGEX = /^[a-z][a-z0-9_.]*$/;
537
- function productSetFilterIssue(rule) {
538
- if (!rule || typeof rule !== "object" || Array.isArray(rule)) return "a rule is an object";
539
- const entries = Object.entries(rule);
540
- if (entries.length !== 1) return "one field per rule \u2014 combine several with and / or";
541
- const [key, value] = entries[0];
542
- if (key === "and" || key === "or") {
543
- if (!Array.isArray(value) || value.length === 0) return `${key} takes a list of rules`;
544
- for (const inner of value) {
545
- const issue = productSetFilterIssue(inner);
546
- if (issue) return issue;
547
- }
548
- return void 0;
549
- }
550
- if (!FIELD_NAME_REGEX.test(key)) {
551
- return "a rule names a product field, e.g. retailer_id, brand, product_type, price, custom_label_0";
552
- }
553
- return conditionSchema.safeParse(value).success ? void 0 : `${key}: one operator of ${PRODUCT_SET_OPERATORS.join(", ")} with its value \u2014 a list for is_any / is_not_any, a number for lt / lte / gt / gte, text for the rest`;
554
- }
555
- var productSetFilterSchema = z2.record(z2.string(), z2.unknown()).superRefine((rule, ctx) => {
556
- const issue = productSetFilterIssue(rule);
557
- if (issue) ctx.addIssue({ code: "custom", message: issue });
558
- }).transform((rule) => rule);
559
- var productSetCreateSchema = z2.strictObject({
560
- catalog_id: catalogRefSchema,
561
- name: z2.string().trim().min(1).max(CATALOG_LIMITS.nameMax),
562
- /** Which products are in it. Without one the set holds the whole catalog. */
563
- filter: productSetFilterSchema.optional()
564
- });
565
- var productSetUpdateSchema = z2.strictObject({
566
- name: z2.string().trim().min(1).max(CATALOG_LIMITS.nameMax).optional(),
567
- filter: productSetFilterSchema.optional(),
568
- status: z2.literal("DELETED").optional()
569
- }).superRefine((p, ctx) => {
570
- const changes = p.name !== void 0 || p.filter !== void 0;
571
- if (p.status === "DELETED" && changes) {
572
- ctx.addIssue({ code: "custom", message: "a product set delete changes nothing else" });
573
- }
574
- if (p.status === void 0 && !changes) {
575
- ctx.addIssue({ code: "custom", message: "rename the set, change its filter, or delete it" });
576
- }
577
- });
578
- function retailerIdFilter(retailerIds) {
579
- return { retailer_id: { is_any: [...retailerIds] } };
580
- }
581
- var FEED_INTERVALS = ["HOURLY", "DAILY", "WEEKLY"];
582
- var FEED_DAYS = ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"];
583
- var feedScheduleSchema = z2.strictObject({
584
- url: httpsUrlSchema,
585
- interval: z2.enum(FEED_INTERVALS),
586
- /** Hour of day, 0–23, in Meta's feed time zone. */
587
- hour: z2.number().int().min(0).max(23).optional(),
588
- day_of_week: z2.enum(FEED_DAYS).optional()
589
- }).superRefine((s, ctx) => {
590
- if (s.interval === "WEEKLY" && s.day_of_week === void 0) {
591
- ctx.addIssue({ code: "custom", path: ["day_of_week"], message: "a weekly schedule names its day" });
592
- }
593
- if (s.interval !== "WEEKLY" && s.day_of_week !== void 0) {
594
- ctx.addIssue({ code: "custom", path: ["day_of_week"], message: "only a weekly schedule names a day" });
595
- }
596
- });
597
- var productFeedCreateSchema = z2.strictObject({
598
- catalog_id: catalogRefSchema,
599
- name: z2.string().trim().min(1).max(CATALOG_LIMITS.nameMax),
600
- /** Without one the feed waits for files uploaded to it. */
601
- schedule: feedScheduleSchema.optional()
602
- });
603
- var productFeedUpdateSchema = z2.strictObject({
604
- name: z2.string().trim().min(1).max(CATALOG_LIMITS.nameMax).optional(),
605
- schedule: feedScheduleSchema.optional(),
606
- status: z2.literal("DELETED").optional()
607
- }).superRefine((p, ctx) => {
608
- const changes = p.name !== void 0 || p.schedule !== void 0;
609
- if (p.status === "DELETED" && changes) {
610
- ctx.addIssue({ code: "custom", message: "a feed delete changes nothing else" });
611
- }
612
- if (p.status === void 0 && !changes) {
613
- ctx.addIssue({ code: "custom", message: "rename the feed, change its schedule, or delete it" });
614
- }
615
- });
616
-
617
- // ../api/src/ads-meta/customerList.ts
618
- import { z as z3 } from "zod";
619
- var CUSTOMER_LIST_KEYS = [
620
- "EMAIL",
621
- "PHONE",
622
- "FN",
623
- "LN",
624
- "FI",
625
- "CT",
626
- "ST",
627
- "ZIP",
628
- "COUNTRY",
629
- "DOBY",
630
- "DOBM",
631
- "DOBD",
632
- "GEN",
633
- "MADID",
634
- "EXTERN_ID",
635
- "LOOKALIKE_VALUE"
636
- ];
637
- var UNHASHED_CUSTOMER_LIST_KEYS = /* @__PURE__ */ new Set([
638
- "MADID",
639
- "EXTERN_ID",
640
- "LOOKALIKE_VALUE"
641
- ]);
642
- var IDENTIFYING_CUSTOMER_LIST_KEYS = ["EMAIL", "PHONE", "MADID", "EXTERN_ID"];
643
- var CUSTOMER_LIST_BATCH_ROWS = 1e4;
644
- var CUSTOMER_LIST_MAX_BATCHES = 20;
645
- var SHA256_HEX = /^[0-9a-f]{64}$/;
646
- var MADID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
647
- function customerListCellIssue(key, value) {
648
- if (value === "") {
649
- return key === "LOOKALIKE_VALUE" ? "a value-based list carries a value for every person \u2014 give the row a value or leave it out" : void 0;
650
- }
651
- if (key === "LOOKALIKE_VALUE") {
652
- return /^\d+(\.\d+)?$/.test(value) ? void 0 : "a value-based list carries a number of 0 or more per person";
653
- }
654
- if (key === "MADID") {
655
- return MADID.test(value) ? void 0 : "a mobile advertiser id is a lowercase IDFA/AAID with hyphens";
656
- }
657
- if (key === "EXTERN_ID") {
658
- return value.length <= 256 ? void 0 : "an external id is at most 256 characters";
659
- }
660
- return SHA256_HEX.test(value) ? void 0 : `${key} must be the lowercase SHA-256 digest the CLI makes from the normalized value, never the value itself`;
661
- }
662
- var schemaColumnsSchema = z3.array(z3.enum(CUSTOMER_LIST_KEYS)).min(1).refine((keys) => new Set(keys).size === keys.length, "each column appears once").refine(
663
- (keys) => keys.some((key) => IDENTIFYING_CUSTOMER_LIST_KEYS.includes(key)),
664
- `a customer list matches people on at least one of ${IDENTIFYING_CUSTOMER_LIST_KEYS.join(", ")}`
665
- );
666
- var customerListBatchSchema = z3.strictObject({
667
- schema: schemaColumnsSchema,
668
- rows: z3.array(z3.array(z3.string())).min(1).max(CUSTOMER_LIST_BATCH_ROWS)
669
- }).superRefine((batch, ctx) => {
670
- for (const [index, row] of batch.rows.entries()) {
671
- if (row.length !== batch.schema.length) {
672
- ctx.addIssue({
673
- code: "custom",
674
- path: ["rows", index],
675
- message: `each row has one value per column (${batch.schema.length})`
676
- });
677
- return;
678
- }
679
- for (const [column, key] of batch.schema.entries()) {
680
- const issue = customerListCellIssue(key, row[column] ?? "");
681
- if (issue) {
682
- ctx.addIssue({ code: "custom", path: ["rows", index, column], message: issue });
683
- return;
684
- }
685
- }
686
- }
687
- });
688
- var customerListBatchResponseSchema = z3.object({ fileId: z3.string(), rows: z3.number().int() });
689
- var CUSTOMER_LIST_ACTIONS = ["add", "remove", "replace"];
690
- var customAudienceMembersSchema = z3.strictObject({
691
- audience_id: z3.union([z3.string().regex(NUMERIC_ID_REGEX), z3.string().regex(TEMP_REF_REGEX)]),
692
- action: z3.enum(CUSTOMER_LIST_ACTIONS),
693
- schema: schemaColumnsSchema,
694
- batches: z3.array(z3.strictObject({ fileId: z3.string().min(1), rows: z3.number().int().min(1).max(CUSTOMER_LIST_BATCH_ROWS) })).min(1).max(CUSTOMER_LIST_MAX_BATCHES)
695
- }).superRefine((p, ctx) => {
696
- if (new Set(p.batches.map((batch) => batch.fileId)).size !== p.batches.length) {
697
- ctx.addIssue({ code: "custom", path: ["batches"], message: "each batch is sent once" });
698
- }
699
- });
700
-
701
- // ../api/src/ads-meta/ops.ts
702
- import { z as z12 } from "zod";
703
-
704
- // ../api/src/ads-meta/adRules.ts
705
- import { z as z4 } from "zod";
706
- var AD_RULE_EVALUATION_TYPES = ["SCHEDULE", "TRIGGER"];
707
- var AD_RULE_OPERATORS = [
708
- "GREATER_THAN",
709
- "LESS_THAN",
710
- "EQUAL",
711
- "NOT_EQUAL",
712
- "IN_RANGE",
713
- "NOT_IN_RANGE",
714
- "IN",
715
- "NOT_IN",
716
- "CONTAIN",
717
- "NOT_CONTAIN",
718
- "ANY",
719
- "ALL",
720
- "NONE"
721
- ];
722
- var AD_RULE_TRIGGER_TYPES = [
723
- "METADATA_CREATION",
724
- "METADATA_UPDATE",
725
- "STATS_MILESTONE",
726
- "STATS_CHANGE",
727
- "DELIVERY_INSIGHTS_CHANGE"
728
- ];
729
- var AD_RULE_EXECUTION_TYPES = [
730
- "PAUSE",
731
- "UNPAUSE",
732
- "NOTIFICATION",
733
- "CHANGE_BUDGET",
734
- "CHANGE_CAMPAIGN_BUDGET",
735
- "CHANGE_BID",
736
- "ROTATE",
737
- "REBALANCE_BUDGET"
738
- ];
739
- var TRIGGER_EXECUTION_TYPES = /* @__PURE__ */ new Set(["PAUSE", "UNPAUSE", "NOTIFICATION"]);
740
- var AD_RULE_SCHEDULE_TYPES = ["DAILY", "HOURLY", "SEMI_HOURLY", "CUSTOM"];
741
- var AD_RULE_CREATE_STATUSES = ["ENABLED", "DISABLED"];
742
- var AD_RULE_UPDATE_STATUSES = ["ENABLED", "DISABLED", "DELETED"];
743
- var AD_RULE_ENTITY_TYPES = ["AD", "ADSET", "CAMPAIGN"];
744
- var TIME_PRESETS_WITH_TODAY = [
745
- "LIFETIME",
746
- "TODAY",
747
- "LAST_2_DAYS",
748
- "LAST_3_DAYS",
749
- "LAST_7_DAYS",
750
- "LAST_14_DAYS",
751
- "LAST_28_DAYS",
752
- "LAST_30_DAYS",
753
- "THIS_MONTH",
754
- "THIS_WEEK_MON_TODAY",
755
- "THIS_WEEK_SUN_TODAY"
756
- ];
757
- var AD_RULE_TIME_PRESETS = [
758
- ...TIME_PRESETS_WITH_TODAY,
759
- "YESTERDAY",
760
- "LAST_2D",
761
- "LAST_3D",
762
- "LAST_7D",
763
- "LAST_14D",
764
- "LAST_28D",
765
- "LAST_30D",
766
- "LAST_ND_14_8",
767
- "LAST_ND_30_8",
768
- "LAST_ND_60_8",
769
- "LAST_ND_120_8",
770
- "LAST_ND_180_8",
771
- "LAST_ND_LIFETIME_8",
772
- "LAST_ND_60_29",
773
- "LAST_ND_120_29",
774
- "LAST_ND_180_29",
775
- "LAST_ND_LIFETIME_29"
776
- ];
777
- var SPECIAL_FIELDS = ["entity_type", "time_preset", "attribution_window", "aggregation_id"];
778
- var METADATA_FIELDS = [
779
- "id",
780
- "name",
781
- "adlabel_ids",
782
- "objective",
783
- "start_time",
784
- "stop_time",
785
- "buying_type",
786
- "billing_event",
787
- "optimization_goal",
788
- "is_autobid",
789
- "daily_budget",
790
- "lifetime_budget",
791
- "spend_cap",
792
- "bid_amount",
793
- "created_time",
794
- "updated_time"
795
- ];
796
- var SCHEDULE_ONLY_METADATA_FIELDS = [
797
- "effective_status",
798
- "placement.page_types",
799
- "budget_reset_period",
800
- "hours_since_creation",
801
- "estimated_budget_spending_percentage",
802
- "audience_reached_percentage",
803
- "active_time",
804
- "current_time"
805
- ];
806
- var APP_EVENTS = [
807
- "achievement_unlocked",
808
- "activate_app",
809
- "add_payment_info",
810
- "add_to_cart",
811
- "add_to_wishlist",
812
- "complete_registration",
813
- "content_view",
814
- "initiated_checkout",
815
- "level_achieved",
816
- "purchase",
817
- "rate",
818
- "search",
819
- "spent_credits",
820
- "tutorial_completion"
821
- ];
822
- var OFFLINE_EVENTS = [
823
- "add_payment_info",
824
- "add_to_cart",
825
- "add_to_wishlist",
826
- "complete_registration",
827
- "initiate_checkout",
828
- "lead",
829
- "other",
830
- "purchase",
831
- "search",
832
- "view_content"
833
- ];
834
- var PIXEL_EVENTS = [
835
- "add_payment_info",
836
- "add_to_cart",
837
- "add_to_wishlist",
838
- "complete_registration",
839
- "initiate_checkout",
840
- "lead",
841
- "purchase",
842
- "search",
843
- "view_content",
844
- "other"
845
- ];
846
- var PIXEL_COST_EVENTS = [
847
- "add_payment_info",
848
- "add_to_cart",
849
- "add_to_wishlist",
850
- "complete_registration",
851
- "initiate_checkout",
852
- "lead",
853
- "purchase",
854
- "search",
855
- "view_content"
856
- ];
857
- var SCHEDULE_ONLY_INSIGHTS_FIELDS = [
858
- "mobile_app_purchase_roas",
859
- "website_purchase_roas",
860
- "offline_conversion",
861
- ...OFFLINE_EVENTS.map((event) => `offline_conversion.${event}`),
862
- "cost_per_offline_conversion",
863
- "cost_per_offline_other",
864
- "cost_per_post_engagement",
865
- "lifetime_impressions",
866
- "lifetime_spent",
867
- "today_spent",
868
- "yesterday_spent",
869
- // The same page lists both as "Yes" higher up and "No" in its last rows; the
870
- // stricter reading is kept, since a refused real-time rule fails at publish.
871
- "unique_clicks",
872
- "reach"
873
- ];
874
- var INSIGHTS_FIELDS = /* @__PURE__ */ new Set([
875
- ...SCHEDULE_ONLY_INSIGHTS_FIELDS,
876
- "impressions",
877
- "unique_impressions",
878
- "clicks",
879
- "unique_clicks",
880
- "spent",
881
- "results",
882
- "cost_per",
883
- "cpc",
884
- "cpm",
885
- "ctr",
886
- "cpa",
887
- "cpp",
888
- "reach",
889
- "frequency",
890
- "leadgen",
891
- "link_ctr",
892
- "cost_per_unique_click",
893
- "result_rate",
894
- "mobile_app_install",
895
- "cost_per_mobile_app_install",
896
- "app_custom_event",
897
- ...APP_EVENTS.map((event) => `app_custom_event.fb_mobile_${event}`),
898
- "app_custom_event.other",
899
- ...APP_EVENTS.map((event) => `cost_per_mobile_${event}`),
900
- "offsite_conversion",
901
- ...PIXEL_EVENTS.map((event) => `offsite_conversion.fb_pixel_${event}`),
902
- ...PIXEL_COST_EVENTS.map((event) => `cost_per_${event}_fb`),
903
- "link_click",
904
- "cost_per_link_click",
905
- "like",
906
- "offsite_engagement",
907
- "post",
908
- "post_comment",
909
- "post_engagement",
910
- "post_like",
911
- "post_reaction",
912
- "view_content",
913
- "video_play",
914
- "video_view",
915
- "vote"
916
- ]);
917
- var ADVANCED_FIELDS = /* @__PURE__ */ new Set(["daily_ratio_spent", "lifetime_ratio_spent"]);
918
- var OBJECT_PREFIXES = ["ad", "adset", "campaign"];
919
- var ATTRIBUTION_PREFIXES = [
920
- "account_default",
921
- "default",
922
- "inline",
923
- "1d_view",
924
- "7d_view",
925
- "28d_view",
926
- "1d_click",
927
- "7d_click",
928
- "28d_click",
929
- "1d_view_1d_click",
930
- "7d_view_1d_click",
931
- "28d_view_1d_click",
932
- "1d_view_7d_click",
933
- "7d_view_7d_click",
934
- "28d_view_7d_click",
935
- "7d_view_28d_click",
936
- "28d_view_28d_click"
937
- ];
938
- var LIVE_ATTRIBUTION_PREFIX = "account_default";
939
- var AD_RULE_ATTRIBUTION_WINDOWS = [LIVE_ATTRIBUTION_PREFIX.toUpperCase()];
940
- var RETIRED_ATTRIBUTION = `Meta retired every attribution window in rules but the account's own (#11 "This attribution window has been deprecated") \u2014 leave the window out, or use ACCOUNT_DEFAULT (account_default:)`;
941
- function retiredAttributionPrefix(field) {
942
- const colon = field.indexOf(":");
943
- const prefix = colon > 0 ? field.slice(0, colon) : void 0;
944
- return prefix !== void 0 && prefix !== LIVE_ATTRIBUTION_PREFIX && ATTRIBUTION_PREFIXES.includes(prefix);
945
- }
946
- var TIME_PREFIXES = AD_RULE_TIME_PRESETS.map((preset) => `${preset.toLowerCase()}_`).sort(
947
- (a, b) => b.length - a.length
948
- );
949
- var KNOWN_PLAIN_FIELDS = /* @__PURE__ */ new Set([
950
- ...SPECIAL_FIELDS,
951
- ...METADATA_FIELDS,
952
- ...SCHEDULE_ONLY_METADATA_FIELDS,
953
- ...INSIGHTS_FIELDS,
954
- ...ADVANCED_FIELDS
955
- ]);
956
- function plainKind(field) {
957
- if (SPECIAL_FIELDS.includes(field)) return "special";
958
- if (INSIGHTS_FIELDS.has(field)) return "insights";
959
- if (ADVANCED_FIELDS.has(field)) return "advanced";
960
- if (KNOWN_PLAIN_FIELDS.has(field)) return "metadata";
961
- return void 0;
962
- }
963
- function insightsBase(field) {
964
- let rest = field;
965
- const colon = rest.indexOf(":");
966
- if (colon > 0) {
967
- if (!ATTRIBUTION_PREFIXES.includes(rest.slice(0, colon))) return void 0;
968
- rest = rest.slice(colon + 1);
969
- }
970
- if (INSIGHTS_FIELDS.has(rest)) return rest;
971
- const prefix = TIME_PREFIXES.find((candidate) => rest.startsWith(candidate));
972
- const base = prefix ? rest.slice(prefix.length) : void 0;
973
- return base && INSIGHTS_FIELDS.has(base) ? base : void 0;
974
- }
975
- function singleField(field) {
976
- const kind = plainKind(field);
977
- if (kind) return { kind, base: field };
978
- const aggregate = /^aggregate\((.+)\)$/.exec(field);
979
- if (aggregate?.[1]) {
980
- const base2 = insightsBase(aggregate[1]);
981
- return base2 ? { kind: "aggregate", base: base2 } : void 0;
982
- }
983
- const dot = field.indexOf(".");
984
- const object = dot > 0 ? OBJECT_PREFIXES.find((prefix) => prefix === field.slice(0, dot)) : void 0;
985
- const rest = object ? field.slice(dot + 1) : field;
986
- const restKind = object ? plainKind(rest) : void 0;
987
- if (object && restKind && restKind !== "special") return { kind: restKind, base: rest, object };
988
- const base = insightsBase(rest);
989
- return base ? { kind: "insights", base, ...object ? { object } : {} } : void 0;
990
- }
991
- var FORMULA_OPERATORS = /* @__PURE__ */ new Set(["+", "-", "*", "/"]);
992
- var MAX_FORMULA_FIELDS = 6;
993
- function formulaTerms(field) {
994
- const tokens = field.trim().split(/\s+/);
995
- const fields = [];
996
- for (const [index, token] of tokens.entries()) {
997
- const isOperator = FORMULA_OPERATORS.has(token);
998
- if (index % 2 === 1 ? !isOperator : isOperator) {
999
- return { refusal: `formula "${field}" must alternate terms and + - * / operators, each separated by a space` };
1000
- }
1001
- if (!isOperator && !/^-?\d+(\.\d+)?$/.test(token)) fields.push(token);
1002
- }
1003
- if (tokens.length % 2 === 0) return { refusal: `formula "${field}" ends with an operator` };
1004
- if (fields.length > MAX_FORMULA_FIELDS) {
1005
- return { refusal: `formula "${field}" uses ${fields.length} fields; Meta allows at most ${MAX_FORMULA_FIELDS}` };
1006
- }
1007
- return { fields };
1008
- }
1009
- var FIELD_HELP = "see the field list in `baker schema ads.meta.rules.create` (Insights metrics like cost_per, spent, results, cpm, ctr, frequency, website_purchase_roas; metadata like name, daily_budget, hours_since_creation), optionally prefixed by ad./adset./campaign., the account's attribution window (account_default:) or a time range (yesterday_)";
1010
- function parseAdRuleField(field) {
1011
- const retired = field.split(/[\s()]+/).map((term) => term.replace(/^(ad|adset|campaign)\./, "")).find(retiredAttributionPrefix);
1012
- if (retired) return { refusal: `"${field}": ${RETIRED_ATTRIBUTION}` };
1013
- if (!/\s/.test(field.trim())) {
1014
- return singleField(field) ?? { refusal: `Meta does not recognise the filter field "${field}" \u2014 ${FIELD_HELP}` };
1015
- }
1016
- const terms = formulaTerms(field);
1017
- if ("refusal" in terms) return terms;
1018
- const unknown = terms.fields.find((term) => {
1019
- const parsed = singleField(term);
1020
- return !parsed || parsed.kind === "special";
1021
- });
1022
- if (unknown) {
1023
- return { refusal: `formula "${field}": Meta does not recognise the field "${unknown}" \u2014 ${FIELD_HELP}` };
1024
- }
1025
- return formulaAmountRefusal(field, terms.fields) ?? { kind: "formula", base: field };
1026
- }
1027
- function formulaAmountRefusal(field, fields) {
1028
- const amounts = fields.filter((term) => isAdRuleMoneyField(term));
1029
- if (amounts.length === 0) return void 0;
1030
- const ratioOfAmounts = fields.length === 2 && amounts.length === 2 && field.trim().split(/\s+/)[1] === "/";
1031
- return ratioOfAmounts ? void 0 : {
1032
- refusal: `formula "${field}" works out to an amount, which Meta compares in the account's minor units and Baker cannot convert inside a formula \u2014 use a plain cost field (cost_per, cpa, cpc) or a ratio of two amounts`
1033
- };
1034
- }
1035
- var COST_BASES = /* @__PURE__ */ new Set(["cpa", "cpc", "cpm", "cpp", "cost_per"]);
1036
- function isCostField(field) {
1037
- const parsed = parseAdRuleField(field);
1038
- return "kind" in parsed && parsed.kind !== "formula" && (COST_BASES.has(parsed.base) || parsed.base.startsWith("cost_per"));
1039
- }
1040
- function isInsightsField(field) {
1041
- const parsed = parseAdRuleField(field);
1042
- return "kind" in parsed && parsed.kind !== "special" && parsed.kind !== "metadata";
1043
- }
1044
- var scalarSchema = z4.union([z4.number(), z4.string(), z4.boolean()]);
1045
- var adRuleFilterSchema = z4.strictObject({
1046
- field: z4.string().min(1),
1047
- operator: z4.enum(AD_RULE_OPERATORS),
1048
- value: z4.union([scalarSchema, z4.array(scalarSchema)])
1049
- });
1050
- var triggerSchema = z4.strictObject({
1051
- type: z4.enum(AD_RULE_TRIGGER_TYPES),
1052
- field: z4.string().min(1).optional(),
1053
- operator: z4.enum(AD_RULE_OPERATORS).optional(),
1054
- value: z4.union([scalarSchema, z4.array(scalarSchema)]).optional()
1055
- });
1056
- var adRuleEvaluationSpecSchema = z4.strictObject({
1057
- evaluation_type: z4.enum(AD_RULE_EVALUATION_TYPES),
1058
- filters: z4.array(adRuleFilterSchema).min(1),
1059
- trigger: triggerSchema.optional()
1060
- });
1061
- var executionOptionSchema = z4.strictObject({
1062
- field: z4.string().min(1),
1063
- operator: z4.enum(["EQUAL", "IN"]).default("EQUAL"),
1064
- value: z4.unknown()
1065
- });
1066
- var adRuleExecutionSpecSchema = z4.strictObject({
1067
- execution_type: z4.enum(AD_RULE_EXECUTION_TYPES),
1068
- execution_options: z4.array(executionOptionSchema).optional()
1069
- });
1070
- var scheduleItemSchema = z4.strictObject({
1071
- start_minute: z4.number().int().optional(),
1072
- end_minute: z4.number().int().optional(),
1073
- days: z4.array(z4.number().int()).optional()
1074
- });
1075
- var adRuleScheduleSpecSchema = z4.strictObject({
1076
- schedule_type: z4.enum(AD_RULE_SCHEDULE_TYPES),
1077
- schedule: z4.array(scheduleItemSchema).optional()
1078
- });
1079
- var COMPARE = ["GREATER_THAN", "LESS_THAN", "EQUAL", "IN_RANGE", "NOT_IN_RANGE"];
1080
- var BOUNDED = ["GREATER_THAN", "LESS_THAN", "IN_RANGE", "NOT_IN_RANGE"];
1081
- var LISTED = ["IN", "NOT_IN"];
1082
- var TAGGED = ["ANY", "ALL", "NONE"];
1083
- var METADATA_OPERATORS = {
1084
- id: ["EQUAL", "IN", "NOT_IN"],
1085
- name: ["EQUAL", "CONTAIN", "NOT_CONTAIN"],
1086
- adlabel_ids: TAGGED,
1087
- objective: LISTED,
1088
- buying_type: LISTED,
1089
- billing_event: LISTED,
1090
- optimization_goal: LISTED,
1091
- is_autobid: LISTED,
1092
- effective_status: LISTED,
1093
- budget_reset_period: LISTED,
1094
- "placement.page_types": TAGGED,
1095
- stop_time: ["GREATER_THAN", "LESS_THAN"]
1096
- };
1097
- var SPECIAL_OPERATORS = {
1098
- entity_type: ["EQUAL"],
1099
- time_preset: ["EQUAL"],
1100
- attribution_window: ["EQUAL"],
1101
- aggregation_id: ["IN"]
1102
- };
1103
- function operatorsFor(parsed) {
1104
- if (parsed.kind === "special") return SPECIAL_OPERATORS[parsed.base] ?? ["EQUAL"];
1105
- if (parsed.kind === "metadata") return METADATA_OPERATORS[parsed.base] ?? BOUNDED;
1106
- return COMPARE;
1107
- }
1108
- function isAscendingPair(value) {
1109
- return Array.isArray(value) && value.length === 2 && value.every((bound) => typeof bound === "number") && value[0] < value[1];
1110
- }
1111
- var isNonEmptyList = (value) => Array.isArray(value) && value.length > 0;
1112
- var isText = (value) => typeof value === "string" && value.length > 0;
1113
- var VALUE_SHAPES = {
1114
- IN_RANGE: { fits: isAscendingPair, words: "a [low, high] pair of numbers, low first" },
1115
- NOT_IN_RANGE: { fits: isAscendingPair, words: "a [low, high] pair of numbers, low first" },
1116
- IN: { fits: isNonEmptyList, words: "a non-empty list" },
1117
- NOT_IN: { fits: isNonEmptyList, words: "a non-empty list" },
1118
- ANY: { fits: isNonEmptyList, words: "a non-empty list" },
1119
- ALL: { fits: isNonEmptyList, words: "a non-empty list" },
1120
- NONE: { fits: isNonEmptyList, words: "a non-empty list" },
1121
- CONTAIN: { fits: isText, words: "text" },
1122
- NOT_CONTAIN: { fits: isText, words: "text" }
1123
- };
1124
- function valueShapeIssue(operator, value, textual) {
1125
- const shape = VALUE_SHAPES[operator] ?? {
1126
- fits: (candidate) => typeof candidate === "number" || textual && typeof candidate === "string",
1127
- words: textual ? "text" : "a number"
1128
- };
1129
- return shape.fits(value) ? void 0 : `${operator} takes ${shape.words}`;
1130
- }
1131
- var TEXTUAL_FIELDS = /* @__PURE__ */ new Set(["name", "id", "entity_type", "time_preset", "attribution_window"]);
1132
- var ENUM_VALUES = {
1133
- entity_type: AD_RULE_ENTITY_TYPES,
1134
- time_preset: AD_RULE_TIME_PRESETS,
1135
- attribution_window: AD_RULE_ATTRIBUTION_WINDOWS
1136
- };
1137
- function enumIssue(parsed, value) {
1138
- const allowed = parsed.kind === "special" ? ENUM_VALUES[parsed.base] : void 0;
1139
- if (!allowed || typeof value === "string" && allowed.includes(value)) return void 0;
1140
- return `${parsed.base} must be one of ${allowed.join(", ")}`;
1141
- }
1142
- function oneFilterIssue(filter) {
1143
- const parsed = parseAdRuleField(filter.field);
1144
- if ("refusal" in parsed) return parsed.refusal;
1145
- const operators = operatorsFor(parsed);
1146
- if (!operators.includes(filter.operator)) {
1147
- return `${filter.field} takes ${operators.join(", ")} \u2014 not ${filter.operator}`;
1148
- }
1149
- return valueShapeIssue(filter.operator, filter.value, TEXTUAL_FIELDS.has(parsed.base)) ?? enumIssue(parsed, filter.value);
1150
- }
1151
- function filtersNamed(spec, field) {
1152
- return spec.filters.filter((filter) => filter.field === field);
1153
- }
1154
- function scopeIssues(spec) {
1155
- if (filtersNamed(spec, "entity_type").length > 0 || filtersNamed(spec, "id").length > 0) return [];
1156
- return [
1157
- {
1158
- path: ["evaluation_spec", "filters"],
1159
- message: "say what the rule applies to \u2014 add an entity_type filter (EQUAL AD, ADSET or CAMPAIGN) or an id filter (IN [ids])"
1160
- }
1161
- ];
1162
- }
1163
- function onceOnly(spec, field) {
1164
- return filtersNamed(spec, field).length > 1 ? [{ path: ["evaluation_spec", "filters"], message: `Meta takes one ${field} filter per rule` }] : [];
1165
- }
1166
- function measuresPerformance(spec) {
1167
- return spec.filters.some((filter) => isInsightsField(filter.field)) || spec.trigger?.type.startsWith("STATS") === true;
1168
- }
1169
- function timePresetIssues(spec) {
1170
- if (!measuresPerformance(spec) || filtersNamed(spec, "time_preset").length > 0) return [];
1171
- return [
1172
- {
1173
- path: ["evaluation_spec", "filters"],
1174
- message: "a performance condition needs a time range \u2014 add a time_preset filter (EQUAL, e.g. LAST_7D); Meta refuses the rule without one"
1175
- }
1176
- ];
1177
- }
1178
- function aggregateIssues(spec) {
1179
- const aggregates = spec.filters.some((filter) => filter.field.startsWith("aggregate("));
1180
- if (!aggregates || filtersNamed(spec, "aggregation_id").length > 0) return [];
1181
- return [
1182
- {
1183
- path: ["evaluation_spec", "filters"],
1184
- message: "an aggregate(...) filter needs an aggregation_id filter (IN [ids]) naming what to add up"
1185
- }
1186
- ];
1187
- }
1188
- var TEMP_REF = /^meta_temp_[A-Za-z0-9_-]{4,}$/;
1189
- var NUMERIC_ID = /^\d+$/;
1190
- var ENTITY_OF_PREFIX = {
1191
- "ad.id": "ad",
1192
- "adset.id": "adSet",
1193
- "campaign.id": "campaign"
1194
- };
1195
- function idFilterEntity(field) {
1196
- if (field === "id") return "level";
1197
- if (/(^|\.)adlabel_ids$/.test(field)) return "adLabel";
1198
- return ENTITY_OF_PREFIX[field];
1199
- }
1200
- function idValues(value) {
1201
- return (Array.isArray(value) ? value : [value]).map(String);
1202
- }
1203
- function idFilterIssue(filter, level) {
1204
- const named = idFilterEntity(filter.field);
1205
- const ids = filter.field === "aggregation_id" || named ? idValues(filter.value) : [];
1206
- const bad = ids.find((id) => !NUMERIC_ID.test(id) && !TEMP_REF.test(id));
1207
- if (bad) return `${filter.field} takes bare numeric ids or meta_temp_* refs \u2014 not "${bad}"`;
1208
- const temp = ids.some((id) => TEMP_REF.test(id));
1209
- if (temp && filter.field === "aggregation_id")
1210
- return "aggregation_id takes ids already on Meta, not meta_temp_* refs";
1211
- if (temp && named === "level" && !level) {
1212
- return "an id filter naming meta_temp_* refs needs an entity_type filter too, so the rule waits for the right objects";
1213
- }
1214
- return void 0;
1215
- }
1216
- function filterIssues(spec) {
1217
- const issues = [];
1218
- const level = adRuleLevel(spec);
1219
- for (const [index, filter] of spec.filters.entries()) {
1220
- const message = oneFilterIssue(filter) ?? idFilterIssue(filter, level);
1221
- if (message) issues.push({ path: ["evaluation_spec", "filters", index], message });
1222
- }
1223
- return [
1224
- ...issues,
1225
- ...scopeIssues(spec),
1226
- ...onceOnly(spec, "time_preset"),
1227
- ...onceOnly(spec, "attribution_window"),
1228
- ...timePresetIssues(spec),
1229
- ...aggregateIssues(spec)
1230
- ];
1231
- }
1232
- var SCHEDULE_ONLY_FIELDS = /* @__PURE__ */ new Set([
1233
- ...SCHEDULE_ONLY_METADATA_FIELDS,
1234
- ...SCHEDULE_ONLY_INSIGHTS_FIELDS,
1235
- "attribution_window"
1236
- ]);
1237
- function scheduleOnlyFilter(filter) {
1238
- const parsed = parseAdRuleField(filter.field);
1239
- if ("refusal" in parsed) return false;
1240
- if (parsed.kind === "advanced" || parsed.kind === "aggregate" || parsed.kind === "formula") return true;
1241
- if (parsed.kind === "insights" && parsed.base !== filter.field) return true;
1242
- return SCHEDULE_ONLY_FIELDS.has(parsed.base);
1243
- }
1244
- var STATS_CHANGE_OPERATORS = ["GREATER_THAN", "LESS_THAN", "IN_RANGE", "NOT_IN_RANGE"];
1245
- var MILESTONE_MINIMUMS = {
1246
- impressions: 1e3,
1247
- unique_impressions: 1e3,
1248
- reach: 1e3,
1249
- clicks: 10,
1250
- unique_clicks: 10,
1251
- spent: 1e3,
1252
- results: 5,
1253
- ...Object.fromEntries(
1254
- [
1255
- ...APP_EVENTS.map((event) => `app_custom_event_fb_mobile_${event}`),
1256
- "app_custom_event",
1257
- "app_custom_event_other",
1258
- "leadgen",
1259
- "like",
1260
- "link_click",
1261
- "mobile_app_install",
1262
- "offsite_conversion",
1263
- "offsite_conversion_add_to_cart",
1264
- "offsite_conversion_checkout",
1265
- ...PIXEL_EVENTS.map((event) => `offsite_conversion_fb_pixel_${event}`),
1266
- "offsite_engagement",
1267
- "post",
1268
- "post_comment",
1269
- "post_engagement",
1270
- "post_like",
1271
- "post_reaction",
1272
- "view_content",
1273
- "video_play",
1274
- "video_view",
1275
- "vote"
1276
- ].map((field) => [field, 1])
1277
- )
1278
- };
1279
- function milestoneMinimumIssue(trigger) {
1280
- if (trigger.type !== "STATS_MILESTONE" || !trigger.field) return void 0;
1281
- const minimum = MILESTONE_MINIMUMS[trigger.field];
1282
- return minimum !== void 0 && typeof trigger.value === "number" && trigger.value < minimum ? `a ${trigger.field} milestone steps by at least ${minimum}${trigger.field === "spent" ? " in the account's minor units (10.00 in a two-decimal currency)" : ""}` : void 0;
1283
- }
1284
- function milestoneIssue(trigger, spec) {
1285
- if (trigger.operator !== "EQUAL") {
1286
- return "a STATS_MILESTONE trigger takes operator EQUAL (it fires at every multiple of the value)";
1287
- }
1288
- const preset = filtersNamed(spec, "time_preset")[0]?.value;
1289
- if (preset !== void 0 && preset !== "LIFETIME") return "a STATS_MILESTONE trigger needs time_preset LIFETIME";
1290
- if (!trigger.field || MILESTONE_MINIMUMS[trigger.field] === void 0) {
1291
- return `Meta counts milestones only of ${Object.keys(MILESTONE_MINIMUMS).slice(0, 7).join(", ")} and the conversion events \u2014 not ${trigger.field}; use a STATS_CHANGE trigger for it`;
1292
- }
1293
- if (!(typeof trigger.value === "number" && trigger.value > 0))
1294
- return "a STATS_MILESTONE trigger takes a positive number";
1295
- return trigger.field === "spent" ? void 0 : milestoneMinimumIssue(trigger);
1296
- }
1297
- function statsTriggerIssue(trigger, spec) {
1298
- if (trigger.type === "STATS_MILESTONE") return milestoneIssue(trigger, spec);
1299
- if (trigger.type === "STATS_CHANGE" && !(trigger.operator && STATS_CHANGE_OPERATORS.includes(trigger.operator))) {
1300
- return `a STATS_CHANGE trigger takes ${STATS_CHANGE_OPERATORS.join(", ")}`;
1301
- }
1302
- return trigger.operator ? valueShapeIssue(trigger.operator, trigger.value, false) : "the trigger needs an operator";
1303
- }
1304
- function triggerShapeIssue(trigger, spec) {
1305
- if (trigger.type === "METADATA_CREATION") return void 0;
1306
- if (!trigger.field) return `a ${trigger.type} trigger needs a field`;
1307
- if (trigger.type === "STATS_MILESTONE") return milestoneIssue(trigger, spec);
1308
- const parsed = parseAdRuleField(trigger.field);
1309
- if ("refusal" in parsed) return parsed.refusal;
1310
- const isMetadata = parsed.kind === "metadata";
1311
- if (trigger.type === "METADATA_UPDATE") {
1312
- return isMetadata ? void 0 : `a METADATA_UPDATE trigger watches a metadata field, not ${trigger.field}`;
1313
- }
1314
- if (isMetadata || parsed.kind === "special") {
1315
- return `a ${trigger.type} trigger watches a metric, not ${trigger.field}`;
1316
- }
1317
- return statsTriggerIssue(trigger, spec);
1318
- }
1319
- function triggerIssues(spec) {
1320
- const at = (message, path = []) => ({
1321
- path: ["evaluation_spec", ...path],
1322
- message
1323
- });
1324
- if (spec.evaluation_type === "SCHEDULE") {
1325
- return spec.trigger ? [at("a SCHEDULE rule has no trigger \u2014 use evaluation_type TRIGGER, or drop the trigger", ["trigger"])] : [];
1326
- }
1327
- const issues = [];
1328
- if (!spec.trigger) {
1329
- issues.push(
1330
- at("a TRIGGER rule needs a trigger ({type, field, operator, value}) saying what change it reacts to", [
1331
- "trigger"
1332
- ])
1333
- );
1334
- } else {
1335
- const shape = triggerShapeIssue(spec.trigger, spec);
1336
- if (shape) issues.push(at(shape, ["trigger"]));
1337
- }
1338
- for (const [index, filter] of spec.filters.entries()) {
1339
- if (scheduleOnlyFilter(filter)) {
1340
- issues.push(
1341
- at(`${filter.field} works only on a schedule \u2014 use evaluation_type SCHEDULE, or drop it`, ["filters", index])
1342
- );
1343
- }
1344
- }
1345
- const preset = filtersNamed(spec, "time_preset")[0]?.value;
1346
- if (typeof preset === "string" && !TIME_PRESETS_WITH_TODAY.includes(preset)) {
1347
- issues.push(
1348
- at(
1349
- `a TRIGGER rule evaluates in real time, so its time_preset must include today (${TIME_PRESETS_WITH_TODAY.join(", ")}) \u2014 not ${preset}`,
1350
- ["filters"]
1351
- )
1352
- );
1353
- }
1354
- return issues;
1355
- }
1356
- function evaluationIssues(spec) {
1357
- return [...filterIssues(spec), ...triggerIssues(spec)];
1358
- }
1359
- function pairingIssues(rule, partial) {
1360
- const evaluationType = rule.evaluation_spec?.evaluation_type;
1361
- if (!evaluationType) return [];
1362
- const issues = [];
1363
- if (evaluationType === "TRIGGER") {
1364
- const executionType = rule.execution_spec?.execution_type;
1365
- if (executionType && !TRIGGER_EXECUTION_TYPES.has(executionType)) {
1366
- issues.push({
1367
- path: ["execution_spec", "execution_type"],
1368
- message: `a TRIGGER rule can only PAUSE, UNPAUSE or NOTIFICATION \u2014 ${executionType} needs evaluation_type SCHEDULE`
1369
- });
1370
- }
1371
- if (rule.schedule_spec) {
1372
- issues.push({
1373
- path: ["schedule_spec"],
1374
- message: "a TRIGGER rule runs the moment the metric changes, so it takes no schedule_spec \u2014 drop it"
1375
- });
1376
- }
1377
- } else if (!rule.schedule_spec && !partial) {
1378
- issues.push({
1379
- path: ["schedule_spec"],
1380
- message: "a SCHEDULE rule needs a schedule_spec (schedule_type DAILY, HOURLY, SEMI_HOURLY or CUSTOM)"
1381
- });
1382
- }
1383
- return issues;
1384
- }
1385
- var AD_RULE_CHANGE_UNITS = ["ACCOUNT_CURRENCY", "PERCENTAGE"];
1386
- var AD_RULE_REBALANCE_TYPES = [
1387
- "EVEN",
1388
- "PROPORTIONAL",
1389
- "NO_PAUSE_PROPORTIONAL",
1390
- "MATCHED_ONLY_PROPORTIONAL"
1391
- ];
1392
- var CHANGE_TYPES = /* @__PURE__ */ new Set(["CHANGE_BUDGET", "CHANGE_CAMPAIGN_BUDGET", "CHANGE_BID"]);
1393
- var ACTION_LEVEL = {
1394
- CHANGE_BUDGET: { level: "ADSET", words: "ad sets (CHANGE_CAMPAIGN_BUDGET changes a campaign's)" },
1395
- CHANGE_BID: { level: "ADSET", words: "ad sets" },
1396
- REBALANCE_BUDGET: { level: "ADSET", words: "ad sets" },
1397
- CHANGE_CAMPAIGN_BUDGET: { level: "CAMPAIGN", words: "campaigns (CHANGE_BUDGET changes an ad set's)" },
1398
- ROTATE: { level: "AD", words: "ads, rotating within the ad sets an adset.id filter names" }
1399
- };
1400
- function optionAllowed(field, executionType) {
1401
- switch (field) {
1402
- case "user_ids":
1403
- case "alert_preferences":
1404
- return true;
1405
- case "change_spec":
1406
- case "execution_count_limit":
1407
- case "action_frequency":
1408
- return CHANGE_TYPES.has(executionType);
1409
- case "rebalance_spec":
1410
- return executionType === "REBALANCE_BUDGET";
1411
- default:
1412
- return false;
1413
- }
1414
- }
1415
- function isPositiveInt(value) {
1416
- return typeof value === "number" && Number.isInteger(value) && value > 0;
1417
- }
1418
- function isRecord2(value) {
1419
- return typeof value === "object" && value !== null && !Array.isArray(value);
1420
- }
1421
- function isNumberPair(value) {
1422
- return Array.isArray(value) && value.length === 2 && value.every((bound) => typeof bound === "number") && value[0] <= value[1];
1423
- }
1424
- function changeSpecIssue(value) {
1425
- if (!isRecord2(value)) return "change_spec takes {amount, unit, limit?, target_field?}";
1426
- if (typeof value.amount !== "number" || value.amount === 0) return "change_spec.amount takes a non-zero number";
1427
- const target = value.target_field;
1428
- if (target !== void 0) {
1429
- if (typeof target !== "string" || !isInsightsField(target)) {
1430
- return "change_spec.target_field takes an Insights metric (e.g. cost_per, website_purchase_roas)";
1431
- }
1432
- return value.limit === void 0 || isNumberPair(value.limit) ? void 0 : "with target_field, change_spec.limit takes a [lowest, highest] pair";
1433
- }
1434
- if (!AD_RULE_CHANGE_UNITS.includes(value.unit)) {
1435
- return `change_spec.unit takes ${AD_RULE_CHANGE_UNITS.join(" or ")} (required unless target_field is set)`;
1436
- }
1437
- return value.limit === void 0 || typeof value.limit === "number" && value.limit > 0 ? void 0 : "change_spec.limit takes a positive amount \u2014 the most (or least) the budget or bid may reach";
1438
- }
1439
- function rebalanceSpecIssue(value) {
1440
- if (!isRecord2(value) || !AD_RULE_REBALANCE_TYPES.includes(value.type)) {
1441
- return `rebalance_spec.type takes ${AD_RULE_REBALANCE_TYPES.join(", ")}`;
1442
- }
1443
- const needsTarget = value.type !== "EVEN" || value.target_count !== void 0;
1444
- if (needsTarget && (typeof value.target_field !== "string" || !isInsightsField(value.target_field))) {
1445
- return "rebalance_spec needs a target_field (an Insights metric to rank by) unless type is EVEN with no target_count";
1446
- }
1447
- if (value.target_count !== void 0 && !isPositiveInt(value.target_count)) {
1448
- return "rebalance_spec.target_count takes a positive whole number";
1449
- }
1450
- if (typeof value.target_field === "string" && isCostField(value.target_field) && value.is_inverse !== true) {
1451
- return `rebalance_spec ranks by ${value.target_field}, a cost, so Meta would give the most budget to the most expensive ad sets \u2014 add is_inverse: true to favour the cheapest`;
1452
- }
1453
- return void 0;
1454
- }
1455
- function optionValueIssue(option) {
1456
- switch (option.field) {
1457
- case "change_spec":
1458
- return changeSpecIssue(option.value);
1459
- case "rebalance_spec":
1460
- return rebalanceSpecIssue(option.value);
1461
- case "execution_count_limit":
1462
- case "action_frequency":
1463
- return isPositiveInt(option.value) ? void 0 : `${option.field} takes a positive whole number`;
1464
- case "user_ids":
1465
- return Array.isArray(option.value) && option.value.length > 0 ? void 0 : "user_ids takes a list of Facebook user ids to notify";
1466
- default:
1467
- return void 0;
1468
- }
1469
- }
1470
- var REQUIRED_OPTION = {
1471
- CHANGE_BUDGET: "change_spec",
1472
- CHANGE_CAMPAIGN_BUDGET: "change_spec",
1473
- CHANGE_BID: "change_spec",
1474
- REBALANCE_BUDGET: "rebalance_spec"
1475
- };
1476
- function executionIssues(spec) {
1477
- const issues = [];
1478
- const options = spec.execution_options ?? [];
1479
- const seen = /* @__PURE__ */ new Set();
1480
- for (const [index, option] of options.entries()) {
1481
- const path = ["execution_spec", "execution_options", index];
1482
- if (seen.has(option.field)) issues.push({ path, message: `${option.field} is given twice` });
1483
- seen.add(option.field);
1484
- if (!optionAllowed(option.field, spec.execution_type)) {
1485
- issues.push({ path, message: `${spec.execution_type} does not take the ${option.field} option` });
1486
- continue;
1487
- }
1488
- const message = optionValueIssue(option);
1489
- if (message) issues.push({ path, message });
1490
- }
1491
- const required = REQUIRED_OPTION[spec.execution_type];
1492
- if (required && !seen.has(required)) {
1493
- issues.push({
1494
- path: ["execution_spec", "execution_options"],
1495
- message: `${spec.execution_type} needs a ${required} option saying how much to change`
1496
- });
1497
- }
1498
- return issues;
1499
- }
1500
- function adRuleLevel(spec) {
1501
- const value = spec ? filtersNamed(spec, "entity_type")[0]?.value : void 0;
1502
- return AD_RULE_ENTITY_TYPES.includes(value) ? value : void 0;
1503
- }
1504
- function rotateIssues(rule) {
1505
- if (rule.execution_spec?.execution_type !== "ROTATE" || !rule.evaluation_spec) return [];
1506
- return filtersNamed(rule.evaluation_spec, "id").length > 0 ? [
1507
- {
1508
- path: ["evaluation_spec", "filters"],
1509
- message: "a ROTATE rule names the ad sets whose ads it rotates with an adset.id filter (entity_type AD) \u2014 Meta refuses a bare id filter of ad sets"
1510
- }
1511
- ] : [];
1512
- }
1513
- function levelIssues(rule) {
1514
- const executionType = rule.execution_spec?.execution_type;
1515
- const wanted = executionType ? ACTION_LEVEL[executionType] : void 0;
1516
- const level = adRuleLevel(rule.evaluation_spec);
1517
- if (!wanted || !level || level === wanted.level) return [];
1518
- return [
1519
- {
1520
- path: ["execution_spec", "execution_type"],
1521
- message: `${executionType} acts on ${wanted.words} \u2014 set entity_type ${wanted.level}, not ${level}`
1522
- }
1523
- ];
1524
- }
1525
- var MINUTES_PER_DAY = 24 * 60;
1526
- function minuteIssue(name, value) {
1527
- if (value === void 0) return void 0;
1528
- return value % 30 === 0 && value >= 0 && value <= MINUTES_PER_DAY ? void 0 : `${name} is minutes after midnight, a multiple of 30 between 0 and ${MINUTES_PER_DAY}`;
1529
- }
1530
- function scheduleItemIssue(item) {
1531
- if (item.days === void 0 && item.start_minute === void 0 && item.end_minute === void 0) {
1532
- return "a custom schedule entry names its days (0\u20136) and/or start_minute/end_minute \u2014 an empty one says nothing about when to run";
1533
- }
1534
- const minute = minuteIssue("start_minute", item.start_minute) ?? minuteIssue("end_minute", item.end_minute);
1535
- if (minute) return minute;
1536
- if (item.start_minute !== void 0 && item.end_minute !== void 0 && item.end_minute < item.start_minute) {
1537
- return "end_minute must be at or after start_minute";
1538
- }
1539
- const days = item.days ?? [];
1540
- if (days.some((day) => day < 0 || day > 6) || new Set(days).size !== days.length) {
1541
- return "days are distinct numbers from 0 (Sunday) to 6 (Saturday)";
1542
- }
1543
- return void 0;
1544
- }
1545
- function scheduleIssues(spec, executionType) {
1546
- const issues = [];
1547
- const items = spec.schedule ?? [];
1548
- if (spec.schedule_type === "CUSTOM" && items.length === 0) {
1549
- issues.push({
1550
- path: ["schedule_spec", "schedule"],
1551
- message: "a CUSTOM schedule needs at least one {start_minute, end_minute, days} entry"
1552
- });
1553
- }
1554
- if (spec.schedule_type !== "CUSTOM" && items.length > 0) {
1555
- issues.push({
1556
- path: ["schedule_spec", "schedule"],
1557
- message: `schedule entries need schedule_type CUSTOM, not ${spec.schedule_type}`
1558
- });
1559
- }
1560
- for (const [index, item] of items.entries()) {
1561
- const message = scheduleItemIssue(item);
1562
- if (message) issues.push({ path: ["schedule_spec", "schedule", index], message });
1563
- }
1564
- if (executionType === "REBALANCE_BUDGET" && spec.schedule_type !== "DAILY" && spec.schedule_type !== "CUSTOM") {
1565
- issues.push({
1566
- path: ["schedule_spec", "schedule_type"],
1567
- message: "a REBALANCE_BUDGET rule runs DAILY or on a CUSTOM schedule"
1568
- });
1569
- }
1570
- return issues;
1571
- }
1572
- function adRuleIssues(rule, { partial = false } = {}) {
1573
- return [
1574
- ...rule.evaluation_spec ? evaluationIssues(rule.evaluation_spec) : [],
1575
- ...rule.execution_spec ? executionIssues(rule.execution_spec) : [],
1576
- ...rule.schedule_spec ? scheduleIssues(rule.schedule_spec, rule.execution_spec?.execution_type) : [],
1577
- ...pairingIssues(rule, partial),
1578
- ...levelIssues(rule),
1579
- ...rotateIssues(rule)
1580
- ];
1581
- }
1582
- function addIssues(rule, ctx, partial = false) {
1583
- for (const issue of adRuleIssues(rule, { partial })) {
1584
- ctx.addIssue({ code: "custom", path: issue.path, message: issue.message });
1585
- }
1586
- }
1587
- var currencyCodeSchema = z4.string().regex(/^[A-Z]{3}$/).optional();
1588
- var adRuleCreateSchema = z4.strictObject({
1589
- name: z4.string().min(1).max(255),
1590
- status: z4.enum(AD_RULE_CREATE_STATUSES).default("ENABLED"),
1591
- evaluation_spec: adRuleEvaluationSpecSchema,
1592
- execution_spec: adRuleExecutionSpecSchema,
1593
- schedule_spec: adRuleScheduleSpecSchema.optional(),
1594
- /** The account currency the money values are in — filled by the backend. */
1595
- currencyCode: currencyCodeSchema
1596
- }).superRefine((rule, ctx) => addIssues(rule, ctx));
1597
- var MONEY_METADATA = /* @__PURE__ */ new Set(["daily_budget", "lifetime_budget", "spend_cap", "bid_amount"]);
1598
- var MONEY_INSIGHTS = /* @__PURE__ */ new Set([
1599
- "spent",
1600
- "today_spent",
1601
- "yesterday_spent",
1602
- "lifetime_spent",
1603
- "cpc",
1604
- "cpm",
1605
- "cpa",
1606
- "cpp"
1607
- ]);
1608
- function unitsField(field) {
1609
- return field.split(/(\s+|[()])/).map((term) => {
1610
- const object = /^(ad|adset|campaign)\./.exec(term)?.[0] ?? "";
1611
- const bare = term.slice(object.length);
1612
- return retiredAttributionPrefix(bare) ? `${object}${LIVE_ATTRIBUTION_PREFIX}${bare.slice(bare.indexOf(":"))}` : term;
1613
- }).join("");
1614
- }
1615
- function isAdRuleMoneyField(field) {
1616
- const parsed = parseAdRuleField(unitsField(field));
1617
- if ("refusal" in parsed || parsed.kind === "formula" || parsed.kind === "special") return false;
1618
- if (parsed.kind === "metadata") return MONEY_METADATA.has(parsed.base);
1619
- return MONEY_INSIGHTS.has(parsed.base) || parsed.base.startsWith("cost_per");
1620
- }
1621
- var adRuleUpdateSchema = z4.strictObject({
1622
- name: z4.string().min(1).max(255).optional(),
1623
- status: z4.enum(AD_RULE_UPDATE_STATUSES).optional(),
1624
- /** Each spec is replaced whole — Meta takes no partial spec on update. */
1625
- evaluation_spec: adRuleEvaluationSpecSchema.optional(),
1626
- execution_spec: adRuleExecutionSpecSchema.optional(),
1627
- schedule_spec: adRuleScheduleSpecSchema.optional(),
1628
- /**
1629
- * Run the rule once, now (`POST /{rule}/execute`), after any change staged
1630
- * beside it — the rule acts on what matches it at that moment, whatever its
1631
- * schedule and even while it is off. Meta ignores `validate_only` there (a
1632
- * validate-only execute ran the rule, its history shows it; live on v26.0,
1633
- * 2026-10-15), so it is never dry-run.
1634
- */
1635
- run_now: z4.literal(true).optional(),
1636
- currencyCode: currencyCodeSchema
1637
- }).refine(
1638
- (p) => Object.entries(p).some(([key, value]) => key !== "currencyCode" && value !== void 0),
1639
- "update needs at least one field"
1640
- ).refine((p) => !(p.run_now && p.status === "DELETED"), "a rule being deleted cannot also run now \u2014 pick one").superRefine((rule, ctx) => addIssues(rule, ctx, true));
1641
- var metaAdRuleHistoryQuerySchema = z4.strictObject({
1642
- accountId: z4.string().min(1),
1643
- ruleId: z4.string().regex(/^\d+$/).optional(),
1644
- objectId: z4.string().regex(/^\d+$/).optional(),
1645
- /** Meta's action names, e.g. PAUSED, UNPAUSED, CHANGED_BUDGET, CHANGED_BID, NOTIFICATION. */
1646
- action: z4.string().min(1).optional(),
1647
- hideNoChanges: z4.boolean().optional(),
1648
- limit: z4.number().int().min(1).max(500).optional()
1649
- });
1650
-
1651
- // ../api/src/ads-meta/adSetCompliance.ts
1652
- import { z as z5 } from "zod";
1653
- var placementSoftOptOutSchema = z5.strictObject({
1654
- facebook_positions: z5.array(z5.enum(FACEBOOK_POSITIONS)).min(1).optional(),
1655
- instagram_positions: z5.array(z5.enum(INSTAGRAM_POSITIONS)).min(1).optional(),
1656
- audience_network_positions: z5.array(z5.enum(AUDIENCE_NETWORK_POSITIONS)).min(1).optional(),
1657
- messenger_positions: z5.array(z5.enum(MESSENGER_POSITIONS)).min(1).optional(),
1658
- threads_positions: z5.array(z5.enum(THREADS_POSITIONS)).min(1).optional()
1659
- }).refine(
1660
- (spec) => Object.values(spec).some((positions) => positions !== void 0),
1661
- "name at least one position Meta may spend on (e.g. audience_network_positions: [classic])"
1662
- );
1663
- var REGIONAL_REGULATED_CATEGORIES = [
1664
- "TAIWAN_FINSERV",
1665
- "AUSTRALIA_FINSERV",
1666
- "INDIA_FINSERV",
1667
- "TAIWAN_UNIVERSAL",
1668
- "SINGAPORE_UNIVERSAL",
1669
- "THAILAND_UNIVERSAL",
1670
- "BRAZIL_REGULATION"
1671
- ];
1672
- var IDENTITY_PREFIX = {
1673
- TAIWAN_FINSERV: "taiwan_finserv",
1674
- AUSTRALIA_FINSERV: "australia_finserv",
1675
- INDIA_FINSERV: "india_finserv",
1676
- TAIWAN_UNIVERSAL: "taiwan_universal",
1677
- SINGAPORE_UNIVERSAL: "singapore_universal",
1678
- THAILAND_UNIVERSAL: "universal",
1679
- BRAZIL_REGULATION: "universal"
1680
- };
1681
- var identityId = z5.string().regex(/^\d+$/, "a verified advertiser id (digits)");
1682
- var IDENTITY_KEYS = [...new Set(Object.values(IDENTITY_PREFIX))].flatMap((prefix) => [
1683
- `${prefix}_beneficiary`,
1684
- `${prefix}_payer`
1685
- ]);
1686
- var regionalRegulationIdentitiesSchema = z5.strictObject(
1687
- Object.fromEntries(IDENTITY_KEYS.map((key) => [key, identityId.optional()]))
1688
- );
1689
- var regionalRegulationFields = {
1690
- regional_regulated_categories: z5.array(z5.enum(REGIONAL_REGULATED_CATEGORIES)).min(1).optional(),
1691
- regional_regulation_identities: regionalRegulationIdentitiesSchema.optional()
1692
- };
1693
- function validateRegionalRegulation(p, ctx) {
1694
- const categories = p.regional_regulated_categories ?? [];
1695
- const identities = p.regional_regulation_identities ?? {};
1696
- for (const category of categories) {
1697
- const prefix = IDENTITY_PREFIX[category];
1698
- const missing = [`${prefix}_beneficiary`, `${prefix}_payer`].filter((key) => !identities[key]);
1699
- if (missing.length > 0) {
1700
- ctx.addIssue({
1701
- code: "custom",
1702
- path: ["regional_regulation_identities"],
1703
- message: `${category} needs ${missing.join(" and ")} in regional_regulation_identities \u2014 the verified advertiser ids from Meta's advertiser verification (Meta refuses it without them, 3858548)`
1704
- });
1705
- }
1706
- }
1707
- if (categories.includes("TAIWAN_FINSERV") && !categories.includes("TAIWAN_UNIVERSAL")) {
1708
- ctx.addIssue({
1709
- code: "custom",
1710
- path: ["regional_regulated_categories"],
1711
- message: "a Taiwan financial-services ad set declares TAIWAN_UNIVERSAL beside TAIWAN_FINSERV"
1712
- });
1713
- }
1714
- }
1715
- var SOFT_PLATFORM = {
1716
- facebook_positions: "facebook",
1717
- instagram_positions: "instagram",
1718
- audience_network_positions: "audience_network",
1719
- messenger_positions: "messenger",
1720
- threads_positions: "threads"
1721
- };
1722
- function softOptOutPlacementIssue(soft, targeting, isCreate) {
1723
- if (!soft || !isCreate && targeting === void 0) return void 0;
1724
- const platforms = Array.isArray(targeting?.publisher_platforms) ? targeting.publisher_platforms : [];
1725
- if (platforms.length === 0) {
1726
- return "limited spend reaches placements the ad set leaves out, so it needs manual placements (targeting.publisher_platforms and positions) \u2014 with automatic placements Meta drops it";
1727
- }
1728
- for (const [key, positions] of Object.entries(soft)) {
1729
- const platform = SOFT_PLATFORM[key];
1730
- const running = targeting?.[key];
1731
- if (!platform || !positions || !platforms.includes(platform)) continue;
1732
- const runs = Array.isArray(running) ? running : void 0;
1733
- const overlap = positions.filter((position) => runs === void 0 || runs.includes(position));
1734
- if (overlap.length > 0) {
1735
- return `the ad set already runs on ${overlap.map((position) => `${platform} ${position}`).join(", ")} \u2014 limited spend names only positions it leaves out`;
1736
- }
1737
- }
1738
- return void 0;
1739
- }
1740
-
1741
- // ../api/src/ads-meta/copies.ts
1742
- import { z as z6 } from "zod";
1743
- var COPY_STATUS_OPTIONS = ["PAUSED", "ACTIVE", "INHERITED_FROM_SOURCE"];
1744
- var COPY_RENAME_STRATEGIES = ["DEEP_RENAME", "ONLY_TOP_LEVEL_RENAME", "NO_RENAME"];
1745
- var DEEP_COPY_MAX_ADS = 51;
1746
- var sourceIdSchema = z6.string().regex(
1747
- NUMERIC_ID_REGEX,
1748
- "the source must be a published Meta id \u2014 to repeat something staged in this chat, stage it again"
1749
- );
1750
- var destinationSchema = z6.union([
1751
- z6.string().regex(NUMERIC_ID_REGEX, "expected a numeric id"),
1752
- z6.string().regex(TEMP_REF_REGEX, "expected a meta_temp_* reference")
1753
- ]);
1754
- var copiedTreeSchema = z6.strictObject({
1755
- adSets: z6.number().int().nonnegative().optional(),
1756
- ads: z6.number().int().nonnegative()
1757
- });
1758
- var naming = {
1759
- status_option: z6.enum(COPY_STATUS_OPTIONS).optional(),
1760
- rename_strategy: z6.enum(COPY_RENAME_STRATEGIES).optional(),
1761
- rename_prefix: z6.string().min(1).max(100).optional(),
1762
- rename_suffix: z6.string().min(1).max(100).optional()
1763
- };
1764
- var schedule = {
1765
- start_time: z6.number().int().positive().optional(),
1766
- end_time: z6.number().int().positive().optional()
1767
- };
1768
- function copyIssues(p, ctx) {
1769
- if (p.rename_strategy === "NO_RENAME" && (p.rename_prefix || p.rename_suffix)) {
1770
- ctx.addIssue({
1771
- code: "custom",
1772
- path: ["rename_strategy"],
1773
- message: "NO_RENAME keeps every name as it is, so a prefix or suffix would be ignored \u2014 drop one of them"
1774
- });
1775
- }
1776
- if (p.start_time !== void 0 && p.end_time !== void 0 && p.end_time <= p.start_time) {
1777
- ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
1778
- }
1779
- if (p.deep_copy && p.sourceTree && p.sourceTree.ads > DEEP_COPY_MAX_ADS) {
1780
- ctx.addIssue({
1781
- code: "custom",
1782
- path: ["deep_copy"],
1783
- message: `Meta copies at most ${DEEP_COPY_MAX_ADS} ads in one go and this holds ${p.sourceTree.ads} \u2014 copy its ad sets one by one (\`adsets copy <id> --deep --to-campaign <copy>\`)`
1784
- });
1785
- }
1786
- }
1787
- var campaignCopySchema = z6.strictObject({
1788
- source_id: sourceIdSchema,
1789
- /** Copy the ad sets and ads too. Without it Meta copies the campaign alone. */
1790
- deep_copy: z6.boolean().optional(),
1791
- ...naming,
1792
- /** For a deep copy only: when the copied ad sets start and end (else they keep the originals'). */
1793
- ...schedule,
1794
- sourceTree: copiedTreeSchema.optional()
1795
- }).superRefine((p, ctx) => {
1796
- if (!p.deep_copy && (p.start_time !== void 0 || p.end_time !== void 0)) {
1797
- ctx.addIssue({
1798
- code: "custom",
1799
- path: ["start_time"],
1800
- message: "start and end apply to the copied ad sets, so they need a deep copy (--deep)"
1801
- });
1802
- }
1803
- copyIssues(p, ctx);
1804
- });
1805
- var adSetCopySchema = z6.strictObject({
1806
- source_id: sourceIdSchema,
1807
- /** The campaign the copy goes into; omitted, it stays beside the original. */
1808
- campaign_id: destinationSchema.optional(),
1809
- /** Copy the ads too. */
1810
- deep_copy: z6.boolean().optional(),
1811
- ...naming,
1812
- ...schedule,
1813
- sourceTree: copiedTreeSchema.optional()
1814
- }).superRefine(copyIssues);
1815
- var adCopySchema = z6.strictObject({
1816
- source_id: sourceIdSchema,
1817
- /** The ad set the copy goes into; omitted, it stays beside the original. */
1818
- adset_id: destinationSchema.optional(),
1819
- ...naming
1820
- }).superRefine(copyIssues);
1821
-
1822
- // ../api/src/ads-meta/instantExperiences.ts
1823
- import { z as z7 } from "zod";
1824
- var tempRefSchema2 = z7.string().regex(TEMP_REF_REGEX, "expected a meta_temp_* reference");
1825
- var httpsUrlSchema2 = z7.string().url().refine((value) => value.startsWith("https://"), "must be an https URL");
1826
- var CANVAS_LIMITS = { nameMax: 100, elementsMax: 20, textMax: 1e3, buttonTextMax: 30 };
1827
- var textElement = z7.strictObject({
1828
- type: z7.literal("text"),
1829
- text: z7.string().trim().min(1).max(CANVAS_LIMITS.textMax)
1830
- });
1831
- var buttonFields = {
1832
- text: z7.string().trim().min(1).max(CANVAS_LIMITS.buttonTextMax),
1833
- url: httpsUrlSchema2
1834
- };
1835
- var buttonElement = z7.strictObject({
1836
- type: z7.literal("button"),
1837
- ...buttonFields,
1838
- /** Meta's `button_style`: BUTTON_FILLED or BUTTON_OUTLINE (the two it took, live). */
1839
- style: z7.enum(["filled", "outline"]).default("filled")
1840
- });
1841
- var idOrRefSchema = z7.union([z7.string().regex(NUMERIC_ID_REGEX), tempRefSchema2]);
1842
- var photoElement = z7.strictObject({
1843
- type: z7.literal("photo"),
1844
- /**
1845
- * A photo on the Page — the only picture Meta takes in an experience: its id,
1846
- * or the ref of a Page photo this chat uploads (`pages photos upload`).
1847
- */
1848
- photo_id: idOrRefSchema
1849
- });
1850
- var videoElement = z7.strictObject({
1851
- type: z7.literal("video"),
1852
- /** A video of the ad account (`baker ads meta media`), by id. */
1853
- video_id: z7.string().regex(NUMERIC_ID_REGEX).optional(),
1854
- /** A library video this chat uploads (`media upload --kind video`). */
1855
- videoRef: tempRefSchema2.optional()
1856
- }).refine(
1857
- (p) => p.video_id === void 0 !== (p.videoRef === void 0),
1858
- "a video element names video_id OR videoRef"
1859
- );
1860
- var productSetElement = z7.strictObject({
1861
- type: z7.literal("product_set"),
1862
- /** A product set's id, or the ref of one this chat creates. */
1863
- product_set_id: idOrRefSchema,
1864
- /** Meta's `show_in_feed`: the products also show under the ad itself — what makes a collection ad. */
1865
- show_in_feed: z7.boolean().default(true),
1866
- /** Catalog tokens allowed, e.g. "{{product.name}}". */
1867
- item_headline: z7.string().trim().min(1).max(200).optional(),
1868
- item_description: z7.string().trim().min(1).max(200).optional()
1869
- });
1870
- var footerElement = z7.strictObject({ type: z7.literal("footer"), ...buttonFields });
1871
- var canvasElementSchema = z7.discriminatedUnion("type", [
1872
- textElement,
1873
- buttonElement,
1874
- photoElement,
1875
- videoElement,
1876
- productSetElement,
1877
- footerElement
1878
- ]);
1879
- var canvasCreateSchema = z7.strictObject({
1880
- page_id: z7.string().regex(NUMERIC_ID_REGEX),
1881
- name: z7.string().trim().min(1).max(CANVAS_LIMITS.nameMax),
1882
- /** Six hex digits, no `#` — e.g. FFFFFF. */
1883
- background_color: z7.string().regex(/^[0-9A-Fa-f]{6}$/, "a colour is six hex digits, e.g. FFFFFF").optional(),
1884
- elements: z7.array(canvasElementSchema).min(1).max(CANVAS_LIMITS.elementsMax),
1885
- /** Publish it with the Session: an ad can only open a published experience, and a published one is fixed. */
1886
- publish: z7.boolean().default(true)
1887
- }).superRefine((p, ctx) => {
1888
- const footers = p.elements.flatMap((element, index) => element.type === "footer" ? [index] : []);
1889
- if (footers.length > 1 || footers.length === 1 && footers[0] !== p.elements.length - 1) {
1890
- ctx.addIssue({
1891
- code: "custom",
1892
- path: ["elements"],
1893
- message: "an experience has at most one footer, and it is the last element"
1894
- });
1895
- }
1896
- });
1897
- var canvasUpdateSchema = z7.strictObject({
1898
- name: z7.string().trim().min(1).max(CANVAS_LIMITS.nameMax).optional(),
1899
- publish: z7.literal(true).optional()
1900
- }).refine((p) => p.name !== void 0 || p.publish !== void 0, "rename the experience or publish it");
1901
-
1902
- // ../api/src/ads-meta/leadForms.ts
1903
- import { z as z8 } from "zod";
1904
- var httpsUrlSchema3 = z8.string().url().refine((value) => value.startsWith("https://"), "must be an https URL");
1905
- var LEAD_FORM_LOCALES = [
1906
- "AR_AR",
1907
- "CS_CZ",
1908
- "DA_DK",
1909
- "DE_DE",
1910
- "EL_GR",
1911
- "EN_GB",
1912
- "EN_US",
1913
- "ES_ES",
1914
- "ES_LA",
1915
- "FI_FI",
1916
- "FR_FR",
1917
- "HE_IL",
1918
- "HI_IN",
1919
- "HU_HU",
1920
- "ID_ID",
1921
- "IT_IT",
1922
- "JA_JP",
1923
- "KO_KR",
1924
- "NB_NO",
1925
- "NL_NL",
1926
- "PL_PL",
1927
- "PT_BR",
1928
- "PT_PT",
1929
- "RO_RO",
1930
- "RU_RU",
1931
- "SV_SE",
1932
- "TH_TH",
1933
- "TR_TR",
1934
- "VI_VN",
1935
- "ZH_CN",
1936
- "ZH_HK",
1937
- "ZH_TW"
1938
- ];
1939
- var LEAD_FORM_QUESTION_TYPES = [
1940
- "CUSTOM",
1941
- "FULL_NAME",
1942
- "FIRST_NAME",
1943
- "LAST_NAME",
1944
- "EMAIL",
1945
- "PHONE",
1946
- "PHONE_OTP",
1947
- "WORK_EMAIL",
1948
- "WORK_PHONE_NUMBER",
1949
- "WHATSAPP_NUMBER",
1950
- "COMPANY_NAME",
1951
- "JOB_TITLE",
1952
- "WEBSITE",
1953
- "STREET_ADDRESS",
1954
- "ADDRESS_LINE_TWO",
1955
- "CITY",
1956
- "STATE",
1957
- "PROVINCE",
1958
- "COUNTRY",
1959
- "ZIP",
1960
- "POST_CODE",
1961
- "DOB",
1962
- "GENDER",
1963
- "MARITIAL_STATUS",
1964
- "RELATIONSHIP_STATUS",
1965
- "MILITARY_STATUS",
1966
- "EDUCATION_LEVEL",
1967
- "VIN",
1968
- "LICENSE_PLATE",
1969
- "EMAIL_ALIAS",
1970
- "DATE_TIME",
1971
- "SLIDER",
1972
- "ID_CPF",
1973
- "ID_AR_DNI",
1974
- "ID_CL_RUT",
1975
- "ID_CO_CC",
1976
- "ID_EC_CI",
1977
- "ID_PE_DNI",
1978
- "ID_MX_RFC",
1979
- "USER_PROVIDED_PHONE_NUMBER",
1980
- "STORE_LOOKUP",
1981
- "STORE_LOOKUP_WITH_TYPEAHEAD",
1982
- "LOCAL_DEALER",
1983
- "JOIN_CODE",
1984
- "FACEBOOK_LEAD_ID",
1985
- "MESSENGER",
1986
- "THREAD_LINK"
1987
- ];
1988
- var WORDED_QUESTION_TYPES = /* @__PURE__ */ new Set(["CUSTOM", "DATE_TIME", "SLIDER"]);
1989
- var NATIONAL_ID_COUNTRY = {
1990
- ID_AR_DNI: "AR",
1991
- ID_CPF: "BR",
1992
- ID_CL_RUT: "CL",
1993
- ID_CO_CC: "CO",
1994
- ID_EC_CI: "EC",
1995
- ID_PE_DNI: "PE",
1996
- ID_MX_RFC: "MX"
1997
- };
1998
- var REFUSED_QUESTION_TYPES = {
1999
- USER_PROVIDED_PHONE_NUMBER: "Meta refuses it on a form made through its API \u2014 ask for PHONE instead",
2000
- LOCAL_DEALER: "Meta refuses it on a form made through its API (it needs a dealer setup in Ads Manager)",
2001
- JOIN_CODE: "Meta refuses it on a form made through its API",
2002
- FACEBOOK_LEAD_ID: "Meta refuses it on a form made through its API",
2003
- MESSENGER: "Meta refuses it on a form made through its API",
2004
- THREAD_LINK: "Meta refuses it on a form made through its API",
2005
- STORE_LOOKUP: "a store locator needs a store-locations setup Meta does not open to Baker (#3, no capability) \u2014 build that form in Ads Manager",
2006
- STORE_LOOKUP_WITH_TYPEAHEAD: "a store locator needs a store-locations setup Meta does not open to Baker (#3, no capability) \u2014 build that form in Ads Manager"
2007
- };
2008
- var LEAD_FORM_LIMITS = {
2009
- nameMax: 255,
2010
- labelMax: 255,
2011
- questionsMax: 50,
2012
- wordedQuestionsMax: 15,
2013
- optionsMin: 2,
2014
- optionsMax: 100,
2015
- optionMax: 255,
2016
- privacyLinkTextMax: 70,
2017
- textMax: 1e3,
2018
- introItemsMax: 5,
2019
- buttonTextMax: 60,
2020
- checkboxesMax: 10,
2021
- trackingParametersMax: 20
2022
- };
2023
- var keySchema = z8.string().trim().min(1).max(100).regex(/^[A-Za-z0-9_]+$/, "a key is letters, digits and underscores");
2024
- var optionSchema = z8.strictObject({
2025
- value: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.optionMax),
2026
- /** What the answer is stored as on a lead; Baker numbers them when left out (Meta needs one). */
2027
- key: keySchema.optional()
2028
- });
2029
- var questionTypeSchema = z8.preprocess(
2030
- (value) => value === "ZIP_CODE" ? "ZIP" : value,
2031
- z8.enum(LEAD_FORM_QUESTION_TYPES)
2032
- );
2033
- var leadFormQuestionSchema = z8.strictObject({
2034
- type: questionTypeSchema,
2035
- /** The question's wording — CUSTOM, DATE_TIME and SLIDER only; Meta words the rest in the form's language. */
2036
- label: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.labelMax).optional(),
2037
- /** The field name the answer is stored under on a lead (Meta picks one when left out). */
2038
- key: keySchema.optional(),
2039
- /** A short note under the question, e.g. "We'll call to confirm the time." */
2040
- inlineContext: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax).optional(),
2041
- /** Multiple choice answers (CUSTOM only). */
2042
- options: z8.array(optionSchema).max(LEAD_FORM_LIMITS.optionsMax).optional()
2043
- });
2044
- var THANK_YOU_BUTTON_TYPES = [
2045
- "VIEW_WEBSITE",
2046
- "DOWNLOAD",
2047
- "BOOK_ON_WEBSITE",
2048
- "CALL_BUSINESS",
2049
- "WHATSAPP",
2050
- "P2B_MESSENGER",
2051
- "PROMO_CODE",
2052
- "NONE",
2053
- "MESSAGE_BUSINESS",
2054
- "SCHEDULE_APPOINTMENT",
2055
- "VIEW_ON_FACEBOOK"
2056
- ];
2057
- var REFUSED_THANK_YOU_BUTTONS = {
2058
- MESSAGE_BUSINESS: 'Meta answers "This button type is not yet supported" \u2014 use P2B_MESSENGER to open Messenger',
2059
- SCHEDULE_APPOINTMENT: 'Meta answers "Appointment integration is missing" \u2014 it needs a booking integration set up in Meta Business Suite',
2060
- VIEW_ON_FACEBOOK: "it opens a downloadable file Meta takes only as an upload Baker cannot send \u2014 use DOWNLOAD with a link"
2061
- };
2062
- var WEBSITE_BUTTONS = /* @__PURE__ */ new Set(["VIEW_WEBSITE", "DOWNLOAD", "BOOK_ON_WEBSITE"]);
2063
- var thankYouSchema = z8.strictObject({
2064
- title: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax),
2065
- body: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax).optional(),
2066
- buttonType: z8.enum(THANK_YOU_BUTTON_TYPES).default("VIEW_WEBSITE"),
2067
- buttonText: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.buttonTextMax).optional(),
2068
- /** Where VIEW_WEBSITE, DOWNLOAD and BOOK_ON_WEBSITE go; defaults to the form's follow-up link. */
2069
- websiteUrl: httpsUrlSchema3.optional(),
2070
- /** CALL_BUSINESS: the number, with its country. */
2071
- businessPhoneNumber: z8.string().trim().min(5).max(30).optional(),
2072
- countryCode: z8.string().regex(/^[A-Z]{2}$/, "a two-letter country code, e.g. US").optional(),
2073
- /** Also offer to continue the conversation in Messenger. */
2074
- enableMessenger: z8.boolean().optional()
2075
- });
2076
- var introSchema = z8.strictObject({
2077
- title: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax),
2078
- /** PARAGRAPH_STYLE: one paragraph. LIST_STYLE: up to five bullet points. */
2079
- style: z8.enum(["PARAGRAPH_STYLE", "LIST_STYLE"]).default("PARAGRAPH_STYLE"),
2080
- content: z8.array(z8.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax)).min(1).max(LEAD_FORM_LIMITS.introItemsMax),
2081
- buttonText: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.buttonTextMax).optional(),
2082
- /** A photo already on the Page, by id — the only cover Meta takes from Baker. */
2083
- coverPhotoId: z8.string().regex(NUMERIC_ID_REGEX).optional()
2084
- });
2085
- var disclaimerSchema = z8.strictObject({
2086
- title: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax).optional(),
2087
- body: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax),
2088
- /** Words of the body that link somewhere — each `text` must appear in the body. */
2089
- links: z8.array(z8.strictObject({ text: z8.string().trim().min(1), url: httpsUrlSchema3 })).max(5).optional(),
2090
- checkboxes: z8.array(
2091
- z8.strictObject({
2092
- text: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.textMax),
2093
- key: keySchema.optional(),
2094
- /** Whether the box must be ticked to submit (Meta's default: required). */
2095
- required: z8.boolean().default(true),
2096
- checkedByDefault: z8.boolean().default(false)
2097
- })
2098
- ).max(LEAD_FORM_LIMITS.checkboxesMax).optional()
2099
- });
2100
- function refuseQuestion(question, index, ctx) {
2101
- const path = ["questions", index];
2102
- const refused = REFUSED_QUESTION_TYPES[question.type];
2103
- if (refused) {
2104
- ctx.addIssue({ code: "custom", path: [...path, "type"], message: `${question.type}: ${refused}` });
2105
- }
2106
- const worded = WORDED_QUESTION_TYPES.has(question.type);
2107
- if (worded && !question.label) {
2108
- ctx.addIssue({ code: "custom", path: [...path, "label"], message: `${question.type} questions need a label` });
2109
- }
2110
- if (!worded && question.label) {
2111
- ctx.addIssue({
2112
- code: "custom",
2113
- path: [...path, "label"],
2114
- message: `Meta words ${question.type} itself, in the form's language \u2014 drop the label, or ask a CUSTOM question`
2115
- });
2116
- }
2117
- if (question.options && question.type !== "CUSTOM") {
2118
- ctx.addIssue({ code: "custom", path: [...path, "options"], message: "only a CUSTOM question takes answers" });
2119
- }
2120
- if (question.options && question.options.length < LEAD_FORM_LIMITS.optionsMin) {
2121
- ctx.addIssue({
2122
- code: "custom",
2123
- path: [...path, "options"],
2124
- message: "a multiple-choice question needs at least 2 answers"
2125
- });
2126
- }
2127
- if (question.inlineContext && !worded) {
2128
- ctx.addIssue({
2129
- code: "custom",
2130
- path: [...path, "inlineContext"],
2131
- message: "a note under the question goes on a CUSTOM, DATE_TIME or SLIDER question"
2132
- });
2133
- }
2134
- }
2135
- function storedKey(question) {
2136
- return question.key ?? (WORDED_QUESTION_TYPES.has(question.type) ? void 0 : question.type.toLowerCase());
2137
- }
2138
- function refuseQuestions(questions, ctx) {
2139
- questions.forEach((question, index) => {
2140
- refuseQuestion(question, index, ctx);
2141
- });
2142
- const worded = questions.filter((question) => WORDED_QUESTION_TYPES.has(question.type)).length;
2143
- if (worded > LEAD_FORM_LIMITS.wordedQuestionsMax) {
2144
- ctx.addIssue({
2145
- code: "custom",
2146
- path: ["questions"],
2147
- message: `Meta allows at most ${LEAD_FORM_LIMITS.wordedQuestionsMax} custom questions (CUSTOM, DATE_TIME, SLIDER) on a form`
2148
- });
2149
- }
2150
- const ids = questions.filter((question) => question.type in NATIONAL_ID_COUNTRY);
2151
- if (ids.length > 1) {
2152
- ctx.addIssue({
2153
- code: "custom",
2154
- path: ["questions"],
2155
- message: "a form asks for one national ID at most, and its ads must target only that ID's country"
2156
- });
2157
- }
2158
- const seen = /* @__PURE__ */ new Map();
2159
- questions.forEach((question, index) => {
2160
- const key = storedKey(question);
2161
- const typeKey = `${question.type}:${question.label ?? ""}`;
2162
- for (const id of [key && `key:${key}`, `q:${typeKey}`]) {
2163
- if (!id) continue;
2164
- if (seen.has(id)) {
2165
- ctx.addIssue({
2166
- code: "custom",
2167
- path: ["questions", index],
2168
- message: id.startsWith("key:") ? `two questions share the key "${key}"` : "duplicate question"
2169
- });
2170
- }
2171
- seen.set(id, index);
2172
- }
2173
- });
2174
- }
2175
- function refuseThankYou(thankYou, followUpActionUrl, ctx) {
2176
- const path = ["thankYou"];
2177
- const refused = REFUSED_THANK_YOU_BUTTONS[thankYou.buttonType];
2178
- if (refused) {
2179
- ctx.addIssue({ code: "custom", path: [...path, "buttonType"], message: `${thankYou.buttonType}: ${refused}` });
2180
- }
2181
- if (thankYou.buttonType !== "NONE" && thankYou.buttonType !== "VIEW_WEBSITE" && !thankYou.buttonText) {
2182
- ctx.addIssue({ code: "custom", path: [...path, "buttonText"], message: "the thank-you button needs its text" });
2183
- }
2184
- if (WEBSITE_BUTTONS.has(thankYou.buttonType) && !thankYou.websiteUrl && !followUpActionUrl) {
2185
- ctx.addIssue({
2186
- code: "custom",
2187
- path: [...path, "websiteUrl"],
2188
- message: `a ${thankYou.buttonType} button needs the website it opens (websiteUrl or followUpActionUrl)`
2189
- });
2190
- }
2191
- if (thankYou.buttonType === "CALL_BUSINESS" && (!thankYou.businessPhoneNumber || !thankYou.countryCode)) {
2192
- ctx.addIssue({
2193
- code: "custom",
2194
- path: [...path, "businessPhoneNumber"],
2195
- message: "a CALL_BUSINESS button needs businessPhoneNumber and its countryCode"
2196
- });
2197
- }
2198
- }
2199
- function refuseIntro(intro, ctx) {
2200
- if (intro.style === "PARAGRAPH_STYLE" && intro.content.length !== 1) {
2201
- ctx.addIssue({
2202
- code: "custom",
2203
- path: ["intro", "content"],
2204
- message: "a PARAGRAPH_STYLE intro holds exactly one paragraph \u2014 use LIST_STYLE for bullet points"
2205
- });
2206
- }
2207
- }
2208
- function refuseDisclaimer(disclaimer, ctx) {
2209
- for (const [index, link] of (disclaimer.links ?? []).entries()) {
2210
- if (!disclaimer.body.includes(link.text)) {
2211
- ctx.addIssue({
2212
- code: "custom",
2213
- path: ["disclaimer", "links", index, "text"],
2214
- message: `"${link.text}" is not in the disclaimer's text \u2014 a link is words of the text`
2215
- });
2216
- }
2217
- }
2218
- }
2219
- var leadFormCreateSchema = z8.strictObject({
2220
- page_id: z8.string().regex(NUMERIC_ID_REGEX),
2221
- /** Unique among the Page's forms — Meta refuses a name the Page already has. */
2222
- name: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax),
2223
- locale: z8.enum(LEAD_FORM_LOCALES).default("EN_US"),
2224
- /** The headline above the questions. */
2225
- questionPageHeadline: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.nameMax).optional(),
2226
- questions: z8.array(leadFormQuestionSchema).min(1).max(LEAD_FORM_LIMITS.questionsMax),
2227
- privacyPolicyUrl: httpsUrlSchema3,
2228
- privacyPolicyLinkText: z8.string().trim().min(1).max(LEAD_FORM_LIMITS.privacyLinkTextMax).default("Privacy Policy"),
2229
- /** Where "View website" goes after submitting. Required without a thank-you screen. */
2230
- followUpActionUrl: httpsUrlSchema3.optional(),
2231
- /** Higher intent: people review and confirm their answers before submitting. Off = more volume. */
2232
- optimizedForQuality: z8.boolean().default(false),
2233
- /** The intro screen before the questions (Meta's context card). */
2234
- intro: introSchema.optional(),
2235
- /** Extra terms and consent checkboxes shown with the privacy policy. */
2236
- disclaimer: disclaimerSchema.optional(),
2237
- thankYou: thankYouSchema.optional(),
2238
- /**
2239
- * "restricted": only people the ad was shown to can open the form (Meta's
2240
- * default when unset). "open": anyone the ad is shared with can.
2241
- */
2242
- sharing: z8.enum(["restricted", "open"]).optional(),
2243
- /** Confirm the phone number with a code sent by text message. Needs a PHONE question. */
2244
- smsVerification: z8.boolean().optional(),
2245
- /** Name/value pairs Meta adds to every lead's answers, e.g. { "campaign": "spring" }. */
2246
- trackingParameters: z8.record(keySchema, z8.string().trim().min(1).max(LEAD_FORM_LIMITS.optionMax)).refine(
2247
- (value) => Object.keys(value).length <= LEAD_FORM_LIMITS.trackingParametersMax,
2248
- `at most ${LEAD_FORM_LIMITS.trackingParametersMax} tracking parameters`
2249
- ).optional()
2250
- }).superRefine((form, ctx) => {
2251
- refuseQuestions(form.questions, ctx);
2252
- if (form.thankYou) {
2253
- refuseThankYou(form.thankYou, form.followUpActionUrl, ctx);
2254
- } else if (!form.followUpActionUrl) {
2255
- ctx.addIssue({
2256
- code: "custom",
2257
- path: ["followUpActionUrl"],
2258
- message: "a form without a thank-you screen needs followUpActionUrl (Meta's View website button)"
2259
- });
2260
- }
2261
- if (form.intro) refuseIntro(form.intro, ctx);
2262
- if (form.disclaimer) refuseDisclaimer(form.disclaimer, ctx);
2263
- if (form.smsVerification && !form.questions.some((question) => question.type === "PHONE")) {
2264
- ctx.addIssue({
2265
- code: "custom",
2266
- path: ["smsVerification"],
2267
- message: "text-message verification needs a PHONE question"
2268
- });
2269
- }
2270
- });
2271
- var leadFormUpdateSchema = z8.looseObject({ status: z8.enum(["ARCHIVED", "ACTIVE"]).optional() }).superRefine((p, ctx) => {
2272
- const others = Object.keys(p).filter((key) => key !== "status");
2273
- if (others.length > 0) {
2274
- ctx.addIssue({
2275
- code: "custom",
2276
- path: [others[0] ?? "status"],
2277
- message: `Meta keeps an Instant Form's ${others.join(", ")} as they were once the form exists (it answers success and changes nothing). Make a changed copy instead: \`baker ads meta lead-forms duplicate <formId> --name "\u2026" --file changes.json\`, point the ads at the copy, then \`lead-forms archive <formId>\`.`
2278
- });
2279
- }
2280
- if (p.status === void 0 && others.length === 0) {
2281
- ctx.addIssue({ code: "custom", path: ["status"], message: "archive the form or unarchive it (status)" });
2282
- }
2283
- });
2284
-
2285
- // ../api/src/ads-meta/mediaSpecs.ts
2286
- var RATIO_4_5 = 4 / 5;
2287
- var RATIO_9_16 = 9 / 16;
2288
- var VIDEO_MAX_SECONDS = [
2289
- ["Facebook Stories", 3 * 60],
2290
- ["Reels", 15 * 60],
2291
- ["Instagram feed and Stories", 60 * 60],
2292
- ["Facebook feed", 241 * 60]
2293
- ];
2294
- var POSITION_MAX_SECONDS = {
2295
- facebook: {
2296
- feed: ["Facebook feed", 241 * 60],
2297
- story: ["Facebook Stories", 3 * 60],
2298
- facebook_reels: ["Facebook Reels", 15 * 60],
2299
- instream_video: ["Facebook in-stream", 10 * 60]
2300
- },
2301
- instagram: {
2302
- stream: ["Instagram feed", 60 * 60],
2303
- story: ["Instagram Stories", 60 * 60],
2304
- explore: ["Instagram Explore", 60 * 60],
2305
- reels: ["Instagram Reels", 15 * 60],
2306
- profile_reels: ["Instagram profile Reels", 15 * 60]
2307
- },
2308
- messenger: { story: ["Messenger Stories", 60] }
2309
- };
2310
- var PLACEMENT_SLOTS = ["feed", "stories", "reels", "right_column", "default"];
2311
-
2312
- // ../api/src/ads-meta/messaging.ts
2313
- import { z as z9 } from "zod";
2314
- var APP_DESTINATIONS = ["MESSENGER", "WHATSAPP", "INSTAGRAM_DIRECT"];
2315
- var MESSAGING_CTA_DESTINATION = {
2316
- MESSAGE_PAGE: "MESSENGER",
2317
- WHATSAPP_MESSAGE: "WHATSAPP",
2318
- INSTAGRAM_MESSAGE: "INSTAGRAM_DIRECT"
2319
- };
2320
- var MESSAGING_DESTINATION_TYPES = [
2321
- "MESSENGER",
2322
- "WHATSAPP",
2323
- "INSTAGRAM_DIRECT",
2324
- "MESSAGING_MESSENGER_WHATSAPP",
2325
- "MESSAGING_INSTAGRAM_DIRECT_MESSENGER",
2326
- "MESSAGING_INSTAGRAM_DIRECT_WHATSAPP",
2327
- "MESSAGING_INSTAGRAM_DIRECT_MESSENGER_WHATSAPP"
2328
- ];
2329
- var WELCOME_LIMITS = { textMax: 300, iceBreakerTitleMax: 80, iceBreakerResponseMax: 300, iceBreakersMax: 4 };
2330
- var welcomeMessageSchema = z9.strictObject({
2331
- greeting: z9.string().trim().min(1).max(WELCOME_LIMITS.textMax),
2332
- iceBreakers: z9.array(
2333
- z9.strictObject({
2334
- question: z9.string().trim().min(1).max(WELCOME_LIMITS.iceBreakerTitleMax),
2335
- answer: z9.string().trim().min(1).max(WELCOME_LIMITS.iceBreakerResponseMax)
2336
- })
2337
- ).min(1).max(WELCOME_LIMITS.iceBreakersMax).optional(),
2338
- autofill: z9.string().trim().min(1).max(WELCOME_LIMITS.textMax).optional()
2339
- }).refine((p) => !(p.iceBreakers && p.autofill), {
2340
- message: "a greeting offers questions to tap OR a message to send, not both",
2341
- path: ["autofill"]
2342
- });
2343
-
2344
- // ../api/src/ads-meta/pagePhotos.ts
2345
- import { z as z10 } from "zod";
2346
- var httpsUrlSchema4 = z10.string().url().refine((value) => value.startsWith("https://"), "must be an https URL");
2347
- var pagePhotoCreateSchema = z10.strictObject({
2348
- page_id: z10.string().regex(NUMERIC_ID_REGEX),
2349
- /** A Baker library image — staging fills `url` with its Baker address. */
2350
- bakerImageId: z10.string().min(1).max(64).optional(),
2351
- /** A public https picture address Meta can fetch. */
2352
- url: httpsUrlSchema4.optional(),
2353
- /** Shown with the photo in the Page's library only; it is never posted. */
2354
- caption: z10.string().trim().min(1).max(2e3).optional()
2355
- }).refine((p) => p.bakerImageId !== void 0 || p.url !== void 0, "a Page photo names bakerImageId or url");
2356
- var pagePhotoUpdateSchema = z10.strictObject({ status: z10.literal("DELETED") });
2357
-
2358
- // ../api/src/ads-meta/reachFrequency.ts
2359
- import { z as z11 } from "zod";
2360
- var unixSeconds = z11.number().int().positive();
2361
- var INSTREAM_PACKAGES = [
2362
- "NORMAL",
2363
- "PREMIUM",
2364
- "SPORTS",
2365
- "ENTERTAINMENT",
2366
- "BEAUTY",
2367
- "FOOD",
2368
- "SPANISH",
2369
- "REGULAR_ANIMALS_PETS",
2370
- "REGULAR_FOOD",
2371
- "REGULAR_GAMES",
2372
- "REGULAR_POLITICS",
2373
- "REGULAR_SPORTS",
2374
- "REGULAR_STYLE",
2375
- "REGULAR_TV_MOVIES"
2376
- ];
2377
- var reachFrequencyPredictionRequestSchema = z11.strictObject({
2378
- accountId: z11.string().regex(NUMERIC_ID_REGEX),
2379
- /** `reach`: how many people a budget reaches. `budget`: what a reach costs. */
2380
- solveFor: z11.enum(["reach", "budget"]),
2381
- /** Lifetime budget, major units — with solveFor reach. */
2382
- budget: z11.string().regex(/^\d+(\.\d{1,2})?$/).optional(),
2383
- /** People to reach — with solveFor budget. Meta's floor is usually 200,000 per country. */
2384
- reach: z11.number().int().positive().optional(),
2385
- start_time: unixSeconds,
2386
- end_time: unixSeconds,
2387
- /** Most times one person sees the ad in each `frequencyCapDays`. */
2388
- frequencyCap: z11.number().int().min(1).max(90).optional(),
2389
- frequencyCapDays: z11.number().int().min(1).max(90).optional(),
2390
- objective: z11.enum([
2391
- "REACH",
2392
- "BRAND_AWARENESS",
2393
- "VIDEO_VIEWS",
2394
- "POST_ENGAGEMENT",
2395
- "LINK_CLICKS",
2396
- "OUTCOME_AWARENESS",
2397
- "OUTCOME_ENGAGEMENT"
2398
- ]).default("REACH"),
2399
- /**
2400
- * Balanced frequency (`is_balanced_frequency` + `target_frequency`): Meta
2401
- * aims each person at this many views per `targetFrequencyDays` rather than
2402
- * capping. Live on v26.0 (2026-10-15) it quoted only under
2403
- * OUTCOME_AWARENESS / OUTCOME_ENGAGEMENT with a REACH or THRUPLAY goal
2404
- * ("Target frequency can only be used when…"), and a plain quote without it
2405
- * needs a frequency cap.
2406
- */
2407
- targetFrequency: z11.number().int().min(1).max(90).optional(),
2408
- targetFrequencyDays: z11.number().int().min(1).max(90).optional(),
2409
- optimization_goal: z11.string().min(1).max(64).optional(),
2410
- /** The Page (and Instagram account) the ads run as. */
2411
- page_id: z11.string().regex(NUMERIC_ID_REGEX),
2412
- instagram_user_id: z11.string().regex(NUMERIC_ID_REGEX).optional(),
2413
- /** Meta targeting: ONE country, no website custom audiences. */
2414
- targeting: z11.record(z11.string(), z11.unknown()),
2415
- /**
2416
- * Run only in these hours (`day_parting_schedule`): minutes from midnight
2417
- * and days (0 = Sunday). Live on v26.0 (2026-10-15) a weekday 09–18 quote
2418
- * came back with its own reach.
2419
- */
2420
- day_parting_schedule: z11.array(
2421
- z11.strictObject({
2422
- start_minute: z11.number().int().min(0).max(1440),
2423
- end_minute: z11.number().int().min(0).max(1440),
2424
- days: z11.array(z11.number().int().min(0).max(6)).min(1)
2425
- })
2426
- ).min(1).optional(),
2427
- /** In-stream video content packages the ads may run in (`instream_packages`). */
2428
- instream_packages: z11.array(z11.enum(INSTREAM_PACKAGES)).min(1).optional()
2429
- }).superRefine((p, ctx) => {
2430
- if (p.solveFor === "reach" && p.budget === void 0) {
2431
- ctx.addIssue({ code: "custom", path: ["budget"], message: "solving for reach needs --budget" });
2432
- }
2433
- if (p.solveFor === "budget" && p.reach === void 0) {
2434
- ctx.addIssue({ code: "custom", path: ["reach"], message: "solving for budget needs --reach" });
2435
- }
2436
- if (p.end_time <= p.start_time) {
2437
- ctx.addIssue({ code: "custom", path: ["end_time"], message: "the end comes after the start" });
2438
- }
2439
- if (p.targetFrequency !== void 0) {
2440
- const objectiveOk = p.objective === "OUTCOME_AWARENESS" || p.objective === "OUTCOME_ENGAGEMENT";
2441
- const goalOk = p.optimization_goal === "REACH" || p.optimization_goal === "THRUPLAY";
2442
- if (!objectiveOk || !goalOk) {
2443
- ctx.addIssue({
2444
- code: "custom",
2445
- path: ["targetFrequency"],
2446
- message: "balanced frequency needs --objective OUTCOME_AWARENESS (or OUTCOME_ENGAGEMENT) and --optimization-goal REACH (or THRUPLAY)"
2447
- });
2448
- }
2449
- }
2450
- if (p.end_time - p.start_time > 90 * 86400) {
2451
- ctx.addIssue({ code: "custom", path: ["end_time"], message: "Meta reserves at most 90 days" });
2452
- }
2453
- });
2454
- var reachFrequencyReservationCreateSchema = z11.strictObject({
2455
- prediction_id: z11.string().regex(NUMERIC_ID_REGEX)
2456
- });
2457
- var reachFrequencyReservationUpdateSchema = z11.strictObject({ status: z11.literal("CANCELLED") });
2458
-
2459
- // ../api/src/ads-meta/ops.ts
2460
- var tempRefSchema3 = z12.string().regex(TEMP_REF_REGEX, "expected a meta_temp_* reference");
2461
- var parentRefSchema = z12.union([z12.string().regex(NUMERIC_ID_REGEX, "expected a numeric id"), tempRefSchema3]);
2462
- var moneySchema = z12.strictObject({
2463
- amount: z12.string().regex(/^\d+(\.\d{1,2})?$/, "expected a decimal amount like 50 or 50.00").refine((val) => Number(val) > 0, "amount must be greater than zero"),
2464
- currencyCode: z12.string().length(3).optional()
2465
- });
2466
- var httpsUrlSchema5 = z12.string().url().refine((u) => u.startsWith("https://"), "destination URLs must be https");
2467
- var bakerMediaIdSchema = z12.string().min(1);
2468
- var stageableStatusSchema = z12.enum(STAGEABLE_CREATE_STATUSES);
2469
- var updateStatusSchema = z12.enum(UPDATE_STATUSES);
2470
- var labelFields = {
2471
- adlabels: z12.array(parentRefSchema).max(META_LIMITS.adLabel.perObjectMax).optional(),
2472
- addLabels: z12.array(parentRefSchema).min(1).optional(),
2473
- removeLabels: z12.array(parentRefSchema).min(1).optional()
2474
- };
2475
- var createLabelFields = { adlabels: labelFields.adlabels };
2476
- function currencyMinimums(currencyCode) {
2477
- return CURRENCY_MINIMUMS[currencyCode] ?? DEFAULT_CURRENCY_MINIMUM;
2478
- }
2479
- function validateDailyBudgetFloor(money, ctx, path) {
2480
- if (money?.currencyCode) {
2481
- const min = currencyMinimums(money.currencyCode).dailyBudgetMin;
2482
- if (Number(money.amount) < min) {
2483
- ctx.addIssue({ code: "custom", path, message: `below the ${min} ${money.currencyCode} daily minimum` });
2484
- }
2485
- }
2486
- }
2487
- var geoLocationsSchema = z12.object({
2488
- countries: z12.array(z12.string().length(2)).optional(),
2489
- regions: z12.array(z12.object({ key: z12.string() })).optional(),
2490
- cities: z12.array(z12.object({ key: z12.string(), radius: z12.number().optional(), distance_unit: z12.string().optional() })).optional(),
2491
- zips: z12.array(z12.object({ key: z12.string() })).optional(),
2492
- location_types: z12.array(z12.string()).optional()
2493
- }).catchall(z12.unknown());
2494
- var idNameSchema = z12.object({ id: z12.string(), name: z12.string().optional() });
2495
- var productAudienceEventSchema = z12.strictObject({
2496
- retention_seconds: z12.number().int().min(3600).max(180 * 86400),
2497
- rule: z12.record(z12.string(), z12.unknown()).refine((rule) => JSON.stringify(rule).includes('"event"'), {
2498
- message: 'a product audience rule names the event it counts, e.g. {"event":{"eq":"ViewContent"}}'
2499
- })
2500
- });
2501
- var productAudienceSpecSchema = z12.strictObject({
2502
- /** A product set's id, or the meta_temp_* ref of one this chat creates. */
2503
- product_set_id: parentRefSchema,
2504
- inclusions: z12.array(productAudienceEventSchema).min(1),
2505
- exclusions: z12.array(productAudienceEventSchema).min(1).optional()
2506
- });
2507
- var metaTargetingSchema = z12.object({
2508
- geo_locations: geoLocationsSchema.optional(),
2509
- excluded_geo_locations: geoLocationsSchema.optional(),
2510
- age_min: z12.number().int().min(13).max(65).optional(),
2511
- age_max: z12.number().int().min(13).max(65).optional(),
2512
- genders: z12.array(z12.union([z12.literal(1), z12.literal(2)])).optional(),
2513
- locales: z12.array(z12.number().int()).optional(),
2514
- interests: z12.array(idNameSchema).optional(),
2515
- behaviors: z12.array(idNameSchema).optional(),
2516
- custom_audiences: z12.array(z12.object({ id: parentRefSchema })).optional(),
2517
- excluded_custom_audiences: z12.array(z12.object({ id: parentRefSchema })).optional(),
2518
- flexible_spec: z12.array(z12.record(z12.string(), z12.unknown())).optional(),
2519
- product_audience_specs: z12.array(productAudienceSpecSchema).min(1).optional(),
2520
- excluded_product_audience_specs: z12.array(productAudienceSpecSchema).min(1).optional(),
2521
- /**
2522
- * Retired by Meta: live on v25.0 (2026-10-14) a create excluding one
2523
- * interest was refused — "Detailed targeting exclusions are no longer
2524
- * available for ad sets" (subcode 3858492). Excluding people goes through
2525
- * `excluded_custom_audiences`.
2526
- */
2527
- exclusions: z12.record(z12.string(), z12.unknown()).refine((value) => Object.keys(value).length === 0, {
2528
- message: "Meta no longer lets an ad set exclude detailed targeting (interests, behaviors, demographics) \u2014 take targeting.exclusions out; to keep people out, exclude a custom audience (excluded_custom_audiences)"
2529
- }).optional(),
2530
- publisher_platforms: z12.array(z12.string()).optional(),
2531
- facebook_positions: z12.array(z12.string()).optional(),
2532
- instagram_positions: z12.array(z12.string()).optional(),
2533
- audience_network_positions: z12.array(z12.string()).optional(),
2534
- messenger_positions: z12.array(z12.string()).optional(),
2535
- threads_positions: z12.array(z12.string()).optional(),
2536
- device_platforms: z12.array(z12.string()).optional(),
2537
- targeting_automation: z12.object({ advantage_audience: z12.union([z12.literal(0), z12.literal(1)]) }).partial().optional(),
2538
- ...brandSafetyTargetingFields
2539
- }).catchall(z12.unknown());
2540
- var GEO_INCLUSION_KEYS = [
2541
- "countries",
2542
- "country_groups",
2543
- "regions",
2544
- "cities",
2545
- "zips",
2546
- "geo_markets",
2547
- "places",
2548
- "custom_locations",
2549
- "electoral_districts",
2550
- "subcities",
2551
- "neighborhoods",
2552
- "subneighborhoods",
2553
- "metro_areas",
2554
- "large_geo_areas",
2555
- "medium_geo_areas",
2556
- "small_geo_areas"
2557
- ];
2558
- function targetingHasGeo(t) {
2559
- const geo = t?.geo_locations;
2560
- return Boolean(
2561
- geo && GEO_INCLUSION_KEYS.some((key) => Array.isArray(geo[key]) && geo[key].length > 0)
2562
- );
2563
- }
2564
- function targetingHasGeoOrAudience(t) {
2565
- if (!t) {
2566
- return false;
2567
- }
2568
- return targetingHasGeo(t) || Boolean(t.custom_audiences?.length);
2569
- }
2570
- function advantageAudienceSetting(t) {
2571
- const value = t.targeting_automation?.advantage_audience;
2572
- return value === 0 || value === 1 ? value : void 0;
2573
- }
2574
- function targetingHardLimitsDemographics(t) {
2575
- if (!t) {
2576
- return false;
2577
- }
2578
- const narrowsAgeMax = typeof t.age_max === "number" && t.age_max < ADVANTAGE_AUDIENCE_OPEN_AGE_MAX;
2579
- const narrowsAgeMin = typeof t.age_min === "number" && t.age_min > ADVANTAGE_AUDIENCE_MAX_HARD_AGE_MIN;
2580
- const narrowsGender = Array.isArray(t.genders) && t.genders.length === 1;
2581
- return narrowsAgeMax || narrowsAgeMin || narrowsGender;
2582
- }
2583
- var QUARTER_HOUR_MS = 15 * 6e4;
2584
- var MIN_HIGH_DEMAND_PERIOD_MS = 3 * 36e5;
2585
- var budgetScheduleSchema = z12.strictObject({
2586
- time_start: z12.number().int().positive(),
2587
- time_end: z12.number().int().positive(),
2588
- increase: moneySchema.optional(),
2589
- increasePercent: z12.number().int().min(1).max(800).optional()
2590
- }).superRefine((period, ctx) => {
2591
- if (period.increase === void 0 === (period.increasePercent === void 0)) {
2592
- ctx.addIssue({
2593
- code: "custom",
2594
- path: ["increase"],
2595
- message: "a budget schedule raises the budget by an amount (increase) or a percentage (increasePercent) \u2014 one of them"
2596
- });
2597
- }
2598
- if (period.time_end - period.time_start < MIN_HIGH_DEMAND_PERIOD_MS) {
2599
- ctx.addIssue({ code: "custom", path: ["time_end"], message: "a high-demand period lasts at least 3 hours" });
2600
- }
2601
- if (period.time_start % QUARTER_HOUR_MS !== 0 || period.time_end % QUARTER_HOUR_MS !== 0) {
2602
- ctx.addIssue({
2603
- code: "custom",
2604
- path: ["time_start"],
2605
- message: "Meta starts and ends a high-demand period on a quarter hour (:00, :15, :30 or :45)"
2606
- });
2607
- }
2608
- });
2609
- var budgetSchedulesSchema = z12.array(budgetScheduleSchema).min(1).max(META_LIMITS.adSet.budgetSchedulesMax).refine(
2610
- (periods) => new Set(periods.map((period) => period.increase === void 0)).size <= 1,
2611
- "Meta raises a budget by amounts or by percentages, not both \u2014 use one kind for every period"
2612
- );
2613
- function validateBudgetSchedules(p, ctx) {
2614
- if (p.budgetSchedules && !p.dailyBudget) {
2615
- ctx.addIssue({
2616
- code: "custom",
2617
- path: ["budgetSchedules"],
2618
- message: "a budget schedule raises a daily budget, and Meta needs that daily budget in the same change \u2014 pass dailyBudget (the current one, on an update)"
2619
- });
2620
- }
2621
- }
2622
- var boostMoveSchema = z12.strictObject({
2623
- id: z12.string().regex(NUMERIC_ID_REGEX, "a boost is named by its id from `baker ads meta high-demand-periods`"),
2624
- time_start: z12.number().int().positive(),
2625
- time_end: z12.number().int().positive(),
2626
- increase: moneySchema.optional(),
2627
- increasePercent: z12.number().int().min(1).max(800).optional()
2628
- }).superRefine((move, ctx) => {
2629
- if (move.increase !== void 0 && move.increasePercent !== void 0) {
2630
- ctx.addIssue({
2631
- code: "custom",
2632
- path: ["increase"],
2633
- message: "a boost raises the budget by an amount or by a percentage, not both \u2014 a move keeps the live boost's own"
2634
- });
2635
- }
2636
- if (move.time_end - move.time_start < MIN_HIGH_DEMAND_PERIOD_MS) {
2637
- ctx.addIssue({ code: "custom", path: ["time_end"], message: "a high-demand period lasts at least 3 hours" });
2638
- }
2639
- if (move.time_start % QUARTER_HOUR_MS !== 0 || move.time_end % QUARTER_HOUR_MS !== 0) {
2640
- ctx.addIssue({
2641
- code: "custom",
2642
- path: ["time_start"],
2643
- message: "Meta starts and ends a high-demand period on a quarter hour (:00, :15, :30 or :45)"
2644
- });
2645
- }
2646
- });
2647
- var boostEditFields = {
2648
- removeBoosts: z12.array(z12.string().regex(NUMERIC_ID_REGEX, "a boost is named by its id from `baker ads meta high-demand-periods`")).min(1).max(META_LIMITS.adSet.budgetSchedulesMax).optional(),
2649
- moveBoosts: z12.array(boostMoveSchema).min(1).max(META_LIMITS.adSet.budgetSchedulesMax).optional()
2650
- };
2651
- function validateBoostEdits(p, ctx) {
2652
- const removed = new Set(p.removeBoosts ?? []);
2653
- for (const move of p.moveBoosts ?? []) {
2654
- if (removed.has(move.id)) {
2655
- ctx.addIssue({
2656
- code: "custom",
2657
- path: ["moveBoosts"],
2658
- message: `boost ${move.id} is both moved and removed \u2014 pick one`
2659
- });
2660
- }
2661
- }
2662
- if (p.clear?.includes("budgetSchedules") && (p.removeBoosts || p.moveBoosts)) {
2663
- ctx.addIssue({
2664
- code: "custom",
2665
- path: ["clear"],
2666
- message: "clearing every boost already removes the ones named \u2014 drop removeBoosts/moveBoosts or the clear"
2667
- });
2668
- }
2669
- }
2670
- var specialAdCategoriesSchema = z12.array(z12.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
2671
- var campaignCreateSchema = z12.strictObject({
2672
- name: z12.string().min(1).max(META_LIMITS.campaign.nameMax),
2673
- objective: z12.enum(OBJECTIVES),
2674
- status: stageableStatusSchema.default("PAUSED"),
2675
- special_ad_categories: specialAdCategoriesSchema,
2676
- special_ad_category_country: z12.array(z12.string().length(2)).optional(),
2677
- buying_type: z12.enum(BUYING_TYPES).default("AUCTION"),
2678
- bid_strategy: z12.enum(BID_STRATEGIES).optional(),
2679
- /** Campaign Budget Optimization (Advantage campaign budget) — mutually exclusive with ad-set budgets. */
2680
- dailyBudget: moneySchema.optional(),
2681
- lifetimeBudget: moneySchema.optional(),
2682
- spendCap: moneySchema.optional(),
2683
- /**
2684
- * Ad-set budget sharing: lets ad sets lend up to 20% of their budget to each
2685
- * other. Meta requires an explicit true/false on any campaign that carries no
2686
- * campaign budget (subcode 4834011); Baker sends false unless asked, because
2687
- * turning it on moves real spend between ad sets nobody asked to move.
2688
- */
2689
- adSetBudgetSharing: z12.boolean().optional(),
2690
- budgetSchedules: budgetSchedulesSchema.optional(),
2691
- start_time: z12.number().int().positive().optional(),
2692
- stop_time: z12.number().int().positive().optional(),
2693
- /**
2694
- * Advantage+ catalog ads: the catalog the campaign sells from. Meta fixes it
2695
- * at creation; each ad set then names one of its product sets.
2696
- */
2697
- promoted_object: z12.strictObject({ product_catalog_id: parentRefSchema }).optional(),
2698
- ...createLabelFields
2699
- }).superRefine((p, ctx) => {
2700
- if (p.dailyBudget && p.lifetimeBudget) {
2701
- ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
2702
- }
2703
- validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
2704
- validateBudgetSchedules(p, ctx);
2705
- if (p.stop_time && p.start_time && p.stop_time <= p.start_time) {
2706
- ctx.addIssue({ code: "custom", path: ["stop_time"], message: "stop_time must be after start_time" });
2707
- }
2708
- const needsCountry = p.special_ad_categories.some((c) => SPECIAL_CATEGORIES_REQUIRING_COUNTRY.includes(c));
2709
- if (needsCountry && !p.special_ad_category_country?.length) {
2710
- ctx.addIssue({
2711
- code: "custom",
2712
- path: ["special_ad_category_country"],
2713
- message: "ISSUES_ELECTIONS_POLITICS campaigns need special_ad_category_country \u2014 pass the 2-letter country code(s) the ads run in"
2714
- });
2715
- }
2716
- const euCountries = (p.special_ad_category_country ?? []).filter((c) => EU_DSA_COUNTRIES.has(c.toUpperCase()));
2717
- if (needsCountry && euCountries.length > 0) {
2718
- ctx.addIssue({
2719
- code: "custom",
2720
- path: ["special_ad_category_country"],
2721
- message: `Meta no longer runs ads about social issues, elections or politics in the EU (since 6 October 2025), so it refuses this campaign for ${euCountries.join(", ")} \u2014 drop the EU countries, or run these ads outside Meta`
2722
- });
2723
- }
2724
- });
2725
- var AD_SET_CLEARABLE_CONTROLS = [
2726
- "dailyMinSpendTarget",
2727
- "dailySpendCap",
2728
- "lifetimeMinSpendTarget",
2729
- "lifetimeSpendCap",
2730
- "adset_schedule",
2731
- "budgetSchedules"
2732
- ];
2733
- var CAMPAIGN_CLEARABLE_CONTROLS = ["budgetSchedules"];
2734
- function validateClear(p, ctx) {
2735
- for (const field of p.clear ?? []) {
2736
- if (p[field] !== void 0) {
2737
- ctx.addIssue({ code: "custom", path: ["clear"], message: `${field} is both set and cleared \u2014 pick one` });
2738
- }
2739
- }
2740
- }
2741
- var campaignUpdateSchema = z12.strictObject({
2742
- name: z12.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
2743
- status: updateStatusSchema.optional(),
2744
- bid_strategy: z12.enum(BID_STRATEGIES).optional(),
2745
- dailyBudget: moneySchema.optional(),
2746
- lifetimeBudget: moneySchema.optional(),
2747
- spendCap: moneySchema.optional(),
2748
- budgetSchedules: budgetSchedulesSchema.optional(),
2749
- start_time: z12.number().int().positive().optional(),
2750
- stop_time: z12.number().int().positive().optional(),
2751
- /** Budget boosts to take away — every one the campaign had when this was staged. */
2752
- clear: z12.array(z12.enum(CAMPAIGN_CLEARABLE_CONTROLS)).min(1).optional(),
2753
- ...boostEditFields,
2754
- ...labelFields
2755
- }).superRefine((p, ctx) => {
2756
- if (!Object.values(p).some((val) => val !== void 0)) {
2757
- ctx.addIssue({ code: "custom", message: "update needs at least one field" });
2758
- }
2759
- if (p.dailyBudget && p.lifetimeBudget) {
2760
- ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
2761
- }
2762
- validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
2763
- validateBudgetSchedules(p, ctx);
2764
- validateClear(p, ctx);
2765
- validateBoostEdits(p, ctx);
2766
- });
2767
- var promotedObjectFields = {
2768
- page_id: parentRefSchema.optional(),
2769
- pixel_id: z12.string().regex(NUMERIC_ID_REGEX).optional(),
2770
- custom_event_type: z12.enum(CUSTOM_EVENT_TYPES).optional(),
2771
- /**
2772
- * A Custom Conversion to optimize toward, instead of a raw pixel event.
2773
- * Named alone by the caller: the stage reads the conversion off Meta and
2774
- * fills `pixel_id`, `custom_event_type` and `pixel_rule` from it, so the
2775
- * staged payload matches what Ads Manager stores and the review shows the
2776
- * event the ad set will actually chase.
2777
- */
2778
- custom_conversion_id: z12.union([z12.string().regex(NUMERIC_ID_REGEX), tempRefSchema3]).optional(),
2779
- /** The custom conversion's own filter, filled by the stage. Never written by hand. */
2780
- pixel_rule: z12.string().optional(),
2781
- application_id: z12.string().regex(NUMERIC_ID_REGEX).optional(),
2782
- object_store_url: z12.string().url().optional(),
2783
- product_catalog_id: parentRefSchema.optional(),
2784
- /** A product set's id, or the meta_temp_* ref of one this chat creates. */
2785
- product_set_id: parentRefSchema.optional(),
2786
- whatsapp_phone_number: z12.string().optional(),
2787
- offline_conversion_data_set_id: z12.string().regex(NUMERIC_ID_REGEX).optional()
2788
- };
2789
- var promotedObjectSchema = z12.strictObject(promotedObjectFields, {
2790
- error: (issue) => issue.code === "unrecognized_keys" ? `promoted_object does not take ${issue.keys.map((key) => `"${key}"`).join(", ")} \u2014 it takes ${Object.keys(promotedObjectFields).join(", ")}` : void 0
2791
- });
2792
- var attributionSpecSchema = z12.array(
2793
- z12.strictObject({
2794
- event_type: z12.enum(ATTRIBUTION_EVENT_TYPES),
2795
- window_days: z12.union([z12.literal(1), z12.literal(7)])
2796
- }).refine((w) => w.window_days <= ATTRIBUTION_MAX_WINDOW_DAYS[w.event_type], {
2797
- error: "Meta counts a view or an engaged video view for 1 day only \u2014 window_days 1",
2798
- path: ["window_days"]
2799
- })
2800
- );
2801
- var minRoasSchema = z12.number().min(META_LIMITS.adSet.minRoasMin, `minRoas must be at least ${META_LIMITS.adSet.minRoasMin} (Meta's floor)`).max(META_LIMITS.adSet.minRoasMax, `minRoas must be at most ${META_LIMITS.adSet.minRoasMax} (Meta's ceiling)`).refine(
2802
- (roas) => Math.round(roas * ROAS_FLOOR_SCALE) / ROAS_FLOOR_SCALE === roas,
2803
- "Meta keeps a minimum ROAS to 4 decimals (2.3333, not 2.33333)"
2804
- );
2805
- var frequencyCapSchema = z12.strictObject({
2806
- event: z12.enum(FREQUENCY_CAP_EVENTS).default("IMPRESSIONS"),
2807
- interval_days: z12.number().int().min(1).max(META_LIMITS.adSet.frequencyIntervalDaysMax),
2808
- max_frequency: z12.number().int().min(1).max(META_LIMITS.adSet.frequencyMaxImpressionsMax),
2809
- type: z12.enum(FREQUENCY_CAP_TYPES).optional()
2810
- });
2811
- var spendLimitFields = {
2812
- dailyMinSpendTarget: moneySchema.optional(),
2813
- dailySpendCap: moneySchema.optional(),
2814
- lifetimeMinSpendTarget: moneySchema.optional(),
2815
- lifetimeSpendCap: moneySchema.optional()
2816
- };
2817
- function minAboveCap(min, cap) {
2818
- return min !== void 0 && cap !== void 0 && Number(min.amount) > Number(cap.amount);
2819
- }
2820
- function validateSpendLimits(p, ctx) {
2821
- const daily = p.dailyMinSpendTarget !== void 0 || p.dailySpendCap !== void 0;
2822
- const lifetime = p.lifetimeMinSpendTarget !== void 0 || p.lifetimeSpendCap !== void 0;
2823
- if ((daily || lifetime) && (p.dailyBudget || p.lifetimeBudget)) {
2824
- ctx.addIssue({
2825
- code: "custom",
2826
- path: [daily ? "dailySpendCap" : "lifetimeSpendCap"],
2827
- message: "spend limits share out a campaign budget \u2014 an ad set with its own budget takes none; drop the budget or the limits"
2828
- });
2829
- }
2830
- if (daily && lifetime) {
2831
- ctx.addIssue({
2832
- code: "custom",
2833
- path: ["lifetimeSpendCap"],
2834
- message: "use daily limits under a daily campaign budget and lifetime limits under a lifetime one, never both"
2835
- });
2836
- }
2837
- if (minAboveCap(p.dailyMinSpendTarget, p.dailySpendCap) || minAboveCap(p.lifetimeMinSpendTarget, p.lifetimeSpendCap)) {
2838
- ctx.addIssue({
2839
- code: "custom",
2840
- path: [daily ? "dailyMinSpendTarget" : "lifetimeMinSpendTarget"],
2841
- message: "the minimum spend can't be higher than the spend cap"
2842
- });
2843
- }
2844
- }
2845
- var MINUTES_PER_DAY2 = 24 * 60;
2846
- var scheduleBlockSchema = z12.strictObject({
2847
- start_minute: z12.number().int().min(0).max(MINUTES_PER_DAY2),
2848
- end_minute: z12.number().int().min(0).max(MINUTES_PER_DAY2),
2849
- days: z12.array(z12.number().int().min(0).max(6)).min(1),
2850
- timezone_type: z12.enum(SCHEDULE_TIMEZONE_TYPES).optional()
2851
- }).superRefine((block, ctx) => {
2852
- if (block.start_minute % 60 !== 0 || block.end_minute % 60 !== 0) {
2853
- ctx.addIssue({
2854
- code: "custom",
2855
- path: ["start_minute"],
2856
- message: "Meta schedules whole hours \u2014 start_minute and end_minute must be multiples of 60 (540 = 9:00)"
2857
- });
2858
- }
2859
- if (block.end_minute - block.start_minute < 60) {
2860
- ctx.addIssue({
2861
- code: "custom",
2862
- path: ["end_minute"],
2863
- message: "a schedule block must end at least one hour after it starts"
2864
- });
2865
- }
2866
- });
2867
- var adSetFields = {
2868
- name: z12.string().min(1).max(META_LIMITS.adSet.nameMax),
2869
- campaign_id: parentRefSchema,
2870
- status: stageableStatusSchema.default("PAUSED"),
2871
- dailyBudget: moneySchema.optional(),
2872
- lifetimeBudget: moneySchema.optional(),
2873
- bidAmount: moneySchema.optional(),
2874
- bid_strategy: z12.enum(BID_STRATEGIES).optional(),
2875
- minRoas: minRoasSchema.optional(),
2876
- frequency_control_specs: z12.array(frequencyCapSchema).min(1).optional(),
2877
- adset_schedule: z12.array(scheduleBlockSchema).min(1).optional(),
2878
- pacing: z12.enum(PACING_TYPES).optional(),
2879
- ...spendLimitFields,
2880
- /**
2881
- * Create-only on an ad set. Meta refuses `budget_schedule_specs` on an ad set
2882
- * update even beside its daily budget ("Ad set must have daily budget to
2883
- * support budget schedule", subcode 3858199 — live on v25.0, 2026-10-14);
2884
- * only the `/budget_schedules` edge adds one later, and that edge ignores
2885
- * `validate_only` (a dry run created a real period), so Baker does not use it.
2886
- */
2887
- budgetSchedules: budgetSchedulesSchema.optional(),
2888
- /**
2889
- * A Dynamic Creative ad set: its one ad mixes the images, videos and texts of
2890
- * an asset-feed (`dynamic`) creative. Create-only — Meta fixes it for the ad
2891
- * set's life — and such an ad set holds exactly one ad (subcode 1885553).
2892
- */
2893
- is_dynamic_creative: z12.boolean().optional(),
2894
- /**
2895
- * Reach and frequency: the reservation this ad set is bought on (its id, or
2896
- * the meta_temp_* ref of a `reachFrequencyReservation.create` in this chat).
2897
- * Its campaign is `buying_type: RESERVED` (`reachFrequency.ts`).
2898
- */
2899
- rf_prediction_id: parentRefSchema.optional(),
2900
- billing_event: z12.enum(BILLING_EVENTS),
2901
- optimization_goal: z12.enum(OPTIMIZATION_GOALS),
2902
- destination_type: z12.enum(DESTINATION_TYPES).optional(),
2903
- promoted_object: promotedObjectSchema.optional(),
2904
- attribution_spec: attributionSpecSchema.optional(),
2905
- start_time: z12.number().int().positive().optional(),
2906
- end_time: z12.number().int().positive().optional(),
2907
- targeting: metaTargetingSchema,
2908
- /**
2909
- * The live ad set this one was copied from, verbatim, by `duplicate`. Baker
2910
- * only — `adSetCommonBody` never sends it to Meta. Set exclusively when the
2911
- * targeting IS the source's targeting, because that is what it licenses:
2912
- * placement validation is skipped for it (see `validateAdSetPlacements`).
2913
- */
2914
- clonedFrom: z12.string().regex(NUMERIC_ID_REGEX).optional(),
2915
- /** EU Digital Services Act: who benefits from / pays for the ad. Auto-filled from the account for EU geo when omitted. */
2916
- dsa_beneficiary: z12.string().min(1).max(100).optional(),
2917
- dsa_payor: z12.string().min(1).max(100).optional(),
2918
- /** Advantage+ placements with limited spend — Sales and Leads campaigns only (`adSetCompliance.ts`). */
2919
- placement_soft_opt_out: placementSoftOptOutSchema.optional(),
2920
- ...regionalRegulationFields,
2921
- ...createLabelFields
2922
- };
2923
- var MIN_ROAS = "LOWEST_COST_WITH_MIN_ROAS";
2924
- function validateMinRoas(p, ctx, requireFloor) {
2925
- if (p.minRoas !== void 0 && p.bid_strategy !== void 0 && p.bid_strategy !== MIN_ROAS) {
2926
- ctx.addIssue({
2927
- code: "custom",
2928
- path: ["minRoas"],
2929
- message: `minRoas only works with bid_strategy ${MIN_ROAS} \u2014 Meta refuses a ROAS floor beside ${p.bid_strategy}`
2930
- });
2931
- }
2932
- if (requireFloor && p.bid_strategy === MIN_ROAS && p.minRoas === void 0) {
2933
- ctx.addIssue({
2934
- code: "custom",
2935
- path: ["minRoas"],
2936
- message: `${MIN_ROAS} needs minRoas \u2014 the return every euro spent must average, e.g. 2.5 for 250% (--min-roas 2.5)`
2937
- });
2938
- }
2939
- }
2940
- var ONE_DAY_CLICK_GOALS = /* @__PURE__ */ new Set(["LINK_CLICKS", "LANDING_PAGE_VIEWS", "REACH"]);
2941
- function validateAttribution(p, ctx) {
2942
- const goal = p.optimization_goal;
2943
- if (!p.attribution_spec || !goal || !ONE_DAY_CLICK_GOALS.has(goal)) return;
2944
- const oneDayClick = p.attribution_spec.every((w) => w.event_type === "CLICK_THROUGH" && w.window_days === 1);
2945
- if (!oneDayClick) {
2946
- ctx.addIssue({
2947
- code: "custom",
2948
- path: ["attribution_spec"],
2949
- message: `Meta attributes a ${goal} ad set on a 1-day click only \u2014 use --attribution 1d_click, or leave it out`
2950
- });
2951
- }
2952
- }
2953
- function validateFrequencyCap(p, ctx) {
2954
- const goal = p.optimization_goal;
2955
- if (p.frequency_control_specs && goal && !OPTIMIZATION_GOALS_WITH_FREQUENCY_CAP.includes(goal)) {
2956
- ctx.addIssue({
2957
- code: "custom",
2958
- path: ["frequency_control_specs"],
2959
- message: `Meta caps frequency only on ${OPTIMIZATION_GOALS_WITH_FREQUENCY_CAP.join(" or ")} ad sets, not ${goal}`
2960
- });
2961
- }
2962
- if (!p.rf_prediction_id && (p.frequency_control_specs ?? []).some((cap) => cap.type === "TARGET")) {
2963
- ctx.addIssue({
2964
- code: "custom",
2965
- path: ["frequency_control_specs"],
2966
- message: "Meta takes a TARGET frequency only on a reach-and-frequency ad set with a prediction attached (subcode 3858652) \u2014 use a CAP (leave type out)"
2967
- });
2968
- }
2969
- const events = (p.frequency_control_specs ?? []).map((cap) => cap.event);
2970
- if (events.includes("VIDEO_VIEWS")) {
2971
- ctx.addIssue({
2972
- code: "custom",
2973
- path: ["frequency_control_specs"],
2974
- message: "Meta fails a VIDEO_VIEWS frequency cap with an unknown error \u2014 count VIDEO_VIEWS_2S or VIDEO_VIEWS_15S, or IMPRESSIONS"
2975
- });
2976
- }
2977
- if (events.includes("VIDEO_VIEWS_6S") && goal && goal !== "REACH") {
2978
- ctx.addIssue({
2979
- code: "custom",
2980
- path: ["frequency_control_specs"],
2981
- message: `Meta counts VIDEO_VIEWS_6S caps on REACH ad sets only, not ${goal} \u2014 use VIDEO_VIEWS_2S or VIDEO_VIEWS_15S`
2982
- });
2983
- }
2984
- }
2985
- function validatePacing(p, ctx) {
2986
- if (p.adset_schedule && p.pacing !== void 0 && p.pacing !== "day_parting") {
2987
- ctx.addIssue({
2988
- code: "custom",
2989
- path: ["pacing"],
2990
- message: `an ad schedule runs only with day_parting pacing, not ${p.pacing} \u2014 drop pacing and Baker sends day_parting`
2991
- });
2992
- }
2993
- if (p.adset_schedule && p.dailyBudget) {
2994
- ctx.addIssue({
2995
- code: "custom",
2996
- path: ["adset_schedule"],
2997
- message: "Meta runs an ad schedule only on a lifetime budget \u2014 use lifetimeBudget with an end_time"
2998
- });
2999
- }
3000
- if (p.pacing === "day_parting" && !p.adset_schedule) {
3001
- ctx.addIssue({
3002
- code: "custom",
3003
- path: ["pacing"],
3004
- message: "day_parting pacing needs adset_schedule \u2014 the hours the ads may run"
3005
- });
3006
- }
3007
- if (p.pacing === "no_pacing" && p.bid_strategy !== void 0 && p.bid_strategy !== "LOWEST_COST_WITH_BID_CAP") {
3008
- ctx.addIssue({
3009
- code: "custom",
3010
- path: ["pacing"],
3011
- message: `accelerated delivery (no_pacing) works only with LOWEST_COST_WITH_BID_CAP, not ${p.bid_strategy}`
3012
- });
3013
- }
3014
- }
3015
- function validateBidStrategy(p, ctx) {
3016
- const strategy = p.bid_strategy;
3017
- if (!strategy) {
3018
- return;
3019
- }
3020
- if (BID_STRATEGIES_REQUIRING_AMOUNT.includes(strategy) && !p.bidAmount) {
3021
- ctx.addIssue({ code: "custom", path: ["bidAmount"], message: `${strategy} requires a bidAmount` });
3022
- }
3023
- if (BID_STRATEGIES_FORBIDDING_AMOUNT.includes(strategy) && p.bidAmount) {
3024
- ctx.addIssue({
3025
- code: "custom",
3026
- path: ["bidAmount"],
3027
- message: `${strategy} must not set a bidAmount \u2014 Meta rejects one (it bids automatically)`
3028
- });
3029
- }
3030
- if (strategy === "COST_CAP" && p.billing_event && p.billing_event !== "IMPRESSIONS") {
3031
- ctx.addIssue({
3032
- code: "custom",
3033
- path: ["billing_event"],
3034
- message: "COST_CAP requires billing_event IMPRESSIONS"
3035
- });
3036
- }
3037
- if (strategy === "LOWEST_COST_WITH_MIN_ROAS" && p.optimization_goal && p.optimization_goal !== "VALUE") {
3038
- ctx.addIssue({
3039
- code: "custom",
3040
- path: ["bid_strategy"],
3041
- message: "LOWEST_COST_WITH_MIN_ROAS requires optimization_goal VALUE"
3042
- });
3043
- }
3044
- }
3045
- function validateAdSetBudgetAndBid(p, ctx) {
3046
- if (p.dailyBudget && p.lifetimeBudget) {
3047
- ctx.addIssue({ code: "custom", path: ["dailyBudget"], message: "set only one of dailyBudget or lifetimeBudget" });
3048
- }
3049
- validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
3050
- if (p.lifetimeBudget && !p.end_time) {
3051
- ctx.addIssue({ code: "custom", path: ["end_time"], message: "lifetimeBudget ad sets need an end_time" });
3052
- }
3053
- validateBidStrategy(p, ctx);
3054
- if (p.end_time && p.start_time && p.end_time <= p.start_time) {
3055
- ctx.addIssue({ code: "custom", path: ["end_time"], message: "end_time must be after start_time" });
3056
- }
3057
- }
3058
- function validateAdSetPromotedObject(p, ctx) {
3059
- const goal = p.optimization_goal;
3060
- if (!goal) {
3061
- return;
3062
- }
3063
- const po = p.promoted_object;
3064
- const namesConversion = Boolean(po?.custom_conversion_id);
3065
- const hasPixel = Boolean(po?.pixel_id) || namesConversion || Boolean(po?.product_set_id);
3066
- const hasEventType = Boolean(po?.custom_event_type) || namesConversion;
3067
- if (OPTIMIZATION_GOALS_REQUIRING_PAGE.includes(goal) && !po?.page_id) {
3068
- ctx.addIssue({
3069
- code: "custom",
3070
- path: ["promoted_object", "page_id"],
3071
- message: `optimization_goal ${goal} needs promoted_object.page_id \u2014 pass --page-id with the Facebook Page the leads/likes belong to`
3072
- });
3073
- }
3074
- if (OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) && !hasPixel) {
3075
- ctx.addIssue({
3076
- code: "custom",
3077
- path: ["promoted_object", "pixel_id"],
3078
- message: `optimization_goal ${goal} needs promoted_object.pixel_id \u2014 pass --pixel-id with the conversion pixel, or --custom-conversion-id to optimize toward a custom conversion`
3079
- });
3080
- }
3081
- if (OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal) && !hasPixel && !po?.application_id) {
3082
- ctx.addIssue({
3083
- code: "custom",
3084
- path: ["promoted_object", "pixel_id"],
3085
- message: `optimization_goal ${goal} needs a conversion source \u2014 pass promoted_object.pixel_id (web value optimization) or promoted_object.application_id (app value optimization)`
3086
- });
3087
- }
3088
- if ((OPTIMIZATION_GOALS_REQUIRING_PIXEL.includes(goal) || OPTIMIZATION_GOALS_REQUIRING_CONVERSION_SOURCE.includes(goal)) && !hasEventType) {
3089
- ctx.addIssue({
3090
- code: "custom",
3091
- path: ["promoted_object", "custom_event_type"],
3092
- message: `optimization_goal ${goal} needs promoted_object.custom_event_type \u2014 pass --custom-event-type (e.g. PURCHASE, LEAD), or --custom-conversion-id to optimize toward a custom conversion`
3093
- });
3094
- }
3095
- if (OPTIMIZATION_GOALS_REQUIRING_APP.includes(goal) && !po?.application_id) {
3096
- ctx.addIssue({
3097
- code: "custom",
3098
- path: ["promoted_object", "application_id"],
3099
- message: `optimization_goal ${goal} needs promoted_object.application_id`
3100
- });
3101
- }
3102
- }
3103
- function validateMessagingAdSet(p, ctx) {
3104
- const opensConversation = MESSAGING_DESTINATION_TYPES.some((type) => type === p.destination_type);
3105
- if (opensConversation && !p.promoted_object?.page_id) {
3106
- ctx.addIssue({
3107
- code: "custom",
3108
- path: ["promoted_object", "page_id"],
3109
- message: `destination_type ${p.destination_type} opens a conversation with a Page \u2014 pass promoted_object.page_id (--page-id) with that Page`
3110
- });
3111
- }
3112
- if (p.optimization_goal === "CONVERSATIONS" && p.destination_type !== void 0 && !opensConversation) {
3113
- ctx.addIssue({
3114
- code: "custom",
3115
- path: ["destination_type"],
3116
- message: `optimization_goal CONVERSATIONS needs destination_type MESSENGER, WHATSAPP, INSTAGRAM_DIRECT or a MESSAGING_* mix \u2014 ${p.destination_type} opens no conversation`
3117
- });
3118
- }
3119
- if (p.optimization_goal === "CONVERSATIONS" && p.destination_type === void 0) {
3120
- ctx.addIssue({
3121
- code: "custom",
3122
- path: ["destination_type"],
3123
- message: "optimization_goal CONVERSATIONS needs destination_type MESSENGER, WHATSAPP, INSTAGRAM_DIRECT or a MESSAGING_* mix \u2014 where the conversation opens"
3124
- });
3125
- }
3126
- }
3127
- function validateAdvantageAudience(p, ctx) {
3128
- const t = p.targeting;
3129
- if (t && targetingHardLimitsDemographics(t) && advantageAudienceSetting(t) === 1) {
3130
- ctx.addIssue({
3131
- code: "custom",
3132
- path: ["targeting", "targeting_automation", "advantage_audience"],
3133
- message: "Advantage+ Audience (advantage_audience: 1) treats age and gender as suggestions, so a hard age/gender limit is rejected \u2014 set advantage_audience: 0 to enforce the limit, or drop the age_max/age_min/gender restriction"
3134
- });
3135
- }
3136
- }
3137
- function validateAdSetPlacements(p, ctx) {
3138
- if (p.clonedFrom) {
3139
- for (const issue of invalidPlacementValues(p.targeting)) {
3140
- if (issue.kind === "retired") {
3141
- ctx.addIssue({
3142
- code: "custom",
3143
- path: ["targeting", issue.field],
3144
- message: `${issue.field} no longer accepts "${issue.value}". ${issue.fix} (${PLACEMENT_TARGETING_DOC})`
3145
- });
3146
- }
3147
- }
3148
- return;
3149
- }
3150
- const missingFeed = positionsMissingRequiredFeed(p.targeting);
3151
- if (missingFeed.length > 0) {
3152
- ctx.addIssue({
3153
- code: "custom",
3154
- path: ["targeting", "facebook_positions"],
3155
- message: `Meta requires "feed" alongside ${missingFeed.join(", ")} \u2014 add "feed" to facebook_positions or drop those positions (${PLACEMENT_TARGETING_DOC})`
3156
- });
3157
- }
3158
- for (const issue of invalidPlacementValues(p.targeting)) {
3159
- if (issue.kind === "unknown") {
3160
- continue;
3161
- }
3162
- ctx.addIssue({
3163
- code: "custom",
3164
- path: ["targeting", issue.field],
3165
- message: issue.kind === "retired" ? `${issue.field} no longer accepts "${issue.value}". ${issue.fix} (${PLACEMENT_TARGETING_DOC})` : `${issue.field} does not accept "${issue.value}". ${issue.fix} (${PLACEMENT_TARGETING_DOC})`
3166
- });
3167
- }
3168
- for (const message of placementCoRequirementIssues(p.targeting)) {
3169
- ctx.addIssue({ code: "custom", path: ["targeting"], message: `${message} (${PLACEMENT_TARGETING_DOC})` });
3170
- }
3171
- }
3172
- function validateSoftOptOut(p, ctx, isCreate) {
3173
- const issue = softOptOutPlacementIssue(
3174
- p.placement_soft_opt_out,
3175
- p.targeting,
3176
- isCreate
3177
- );
3178
- if (issue) ctx.addIssue({ code: "custom", path: ["placement_soft_opt_out"], message: issue });
3179
- }
3180
- var adSetCreateSchema = z12.strictObject(adSetFields).superRefine((p, ctx) => {
3181
- validateAdSetBudgetAndBid(p, ctx);
3182
- validateMinRoas(p, ctx, true);
3183
- validateFrequencyCap(p, ctx);
3184
- validateAttribution(p, ctx);
3185
- validatePacing(p, ctx);
3186
- validateSpendLimits(p, ctx);
3187
- validateBudgetSchedules(p, ctx);
3188
- validateAdSetPromotedObject(p, ctx);
3189
- validateMessagingAdSet(p, ctx);
3190
- validateAdvantageAudience(p, ctx);
3191
- validateAdSetPlacements(p, ctx);
3192
- validateRegionalRegulation(p, ctx);
3193
- validateSoftOptOut(p, ctx, true);
3194
- if (!targetingHasGeoOrAudience(p.targeting)) {
3195
- ctx.addIssue({
3196
- code: "custom",
3197
- path: ["targeting", "geo_locations"],
3198
- message: 'targeting needs a location \u2014 set targeting.geo_locations (e.g. countries: ["US"]) or include a custom audience; Meta rejects an ad set with no geo'
3199
- });
3200
- }
3201
- });
3202
- var adSetUpdateSchema = z12.strictObject({
3203
- name: adSetFields.name.optional(),
3204
- status: updateStatusSchema.optional(),
3205
- dailyBudget: moneySchema.optional(),
3206
- lifetimeBudget: moneySchema.optional(),
3207
- bidAmount: moneySchema.optional(),
3208
- bid_strategy: z12.enum(BID_STRATEGIES).optional(),
3209
- minRoas: minRoasSchema.optional(),
3210
- frequency_control_specs: z12.array(frequencyCapSchema).min(1).optional(),
3211
- adset_schedule: z12.array(scheduleBlockSchema).min(1).optional(),
3212
- pacing: z12.enum(PACING_TYPES).optional(),
3213
- ...spendLimitFields,
3214
- optimization_goal: z12.enum(OPTIMIZATION_GOALS).optional(),
3215
- destination_type: z12.enum(DESTINATION_TYPES).optional(),
3216
- promoted_object: promotedObjectSchema.optional(),
3217
- attribution_spec: attributionSpecSchema.optional(),
3218
- start_time: z12.number().int().positive().optional(),
3219
- end_time: z12.number().int().positive().optional(),
3220
- targeting: metaTargetingSchema.optional(),
3221
- dsa_beneficiary: z12.string().min(1).max(100).optional(),
3222
- dsa_payor: z12.string().min(1).max(100).optional(),
3223
- placement_soft_opt_out: placementSoftOptOutSchema.optional(),
3224
- ...regionalRegulationFields,
3225
- /**
3226
- * Boosts ADDED to a live ad set. Meta refuses `budget_schedule_specs` in an
3227
- * ad set update (subcode 3858199) but takes each period on the
3228
- * `/{adset}/budget_schedules` edge without the budget restated (live on
3229
- * v26.0, 2026-10-15), so the executor sends them there.
3230
- */
3231
- budgetSchedules: budgetSchedulesSchema.optional(),
3232
- /** Delivery controls to take away (`AD_SET_CLEARABLE_CONTROLS`). */
3233
- clear: z12.array(z12.enum(AD_SET_CLEARABLE_CONTROLS)).min(1).optional(),
3234
- ...boostEditFields,
3235
- ...labelFields
3236
- }).superRefine((p, ctx) => {
3237
- if (!Object.values(p).some((val) => val !== void 0)) {
3238
- ctx.addIssue({ code: "custom", message: "update needs at least one field" });
3239
- }
3240
- validateClear(p, ctx);
3241
- validateBoostEdits(p, ctx);
3242
- validateAdSetBudgetAndBid(p, ctx);
3243
- validateMinRoas(p, ctx, false);
3244
- validateFrequencyCap(p, ctx);
3245
- validateAttribution(p, ctx);
3246
- validatePacing(p, ctx);
3247
- validateSpendLimits(p, ctx);
3248
- if (p.optimization_goal) {
3249
- validateAdSetPromotedObject(p, ctx);
3250
- }
3251
- if (p.destination_type) {
3252
- validateMessagingAdSet(p, ctx);
3253
- }
3254
- validateAdvantageAudience(p, ctx);
3255
- validateAdSetPlacements(p, ctx);
3256
- validateRegionalRegulation(p, ctx);
3257
- validateSoftOptOut(p, ctx, false);
3258
- });
3259
- var messageSchema = z12.string().min(1).max(META_LIMITS.creative.messageHardMax);
3260
- var headlineSchema = z12.string().min(1).max(META_LIMITS.creative.headlineMax);
3261
- var descriptionSchema = z12.string().min(1).max(META_LIMITS.creative.descriptionMax);
3262
- var callToActionSchema = z12.strictObject({
3263
- type: z12.enum(CTA_TYPES),
3264
- /** Overrides the base link for the CTA button; defaults to the ad's link. */
3265
- link: httpsUrlSchema5.optional(),
3266
- /**
3267
- * The instant form the button opens — Meta's `call_to_action.value.lead_gen_form_id`.
3268
- * This is the ONLY place an instant form is named: the ad set says leads open
3269
- * on the ad (`destination_type: ON_AD`), and the creative says which form.
3270
- * Without it Meta refuses every ad in that ad set with subcode 3390001,
3271
- * "Choose or create an instant form for your leads campaign".
3272
- */
3273
- lead_gen_form_id: parentRefSchema.optional(),
3274
- /** The app a click-to-message button opens a conversation in — `value.app_destination`. */
3275
- app_destination: z12.enum(APP_DESTINATIONS).optional(),
3276
- /**
3277
- * App ads: the deep link the button opens in an installed app (`value.app_link`,
3278
- * e.g. `myapp://product/12`). Meta refuses one without an app-store `link`
3279
- * beside it (subcode 1885949, live on v25.0, 2026-10-15).
3280
- */
3281
- app_link: z12.string().min(3).max(1e3).optional(),
3282
- /**
3283
- * App ads: the Meta app the button installs or opens (`value.application`).
3284
- * Meta refuses one whose store does not match the button's link (subcode
3285
- * 1885270, live on v25.0, 2026-10-15).
3286
- */
3287
- application: z12.string().regex(NUMERIC_ID_REGEX).optional()
3288
- }).superRefine((p, ctx) => {
3289
- validateMessagingButton(p, ctx);
3290
- if (p.lead_gen_form_id && !LEAD_FORM_CTA_TYPES.some((allowed) => allowed === p.type)) {
3291
- ctx.addIssue({
3292
- code: "custom",
3293
- path: ["type"],
3294
- message: `${p.type} cannot open an instant form \u2014 Meta refuses it (subcode 1856030). Use one of ${LEAD_FORM_CTA_TYPES.join(", ")}, or drop lead_gen_form_id if this ad should go to the website.`
3295
- });
3296
- }
3297
- });
3298
- function validateMessagingButton(p, ctx) {
3299
- const opens = MESSAGING_CTA_DESTINATION[p.type];
3300
- if (opens && p.app_destination && p.app_destination !== opens) {
3301
- ctx.addIssue({
3302
- code: "custom",
3303
- path: ["app_destination"],
3304
- message: `${p.type} opens ${opens} \u2014 set app_destination ${opens}, or pick the button of ${p.app_destination}`
3305
- });
3306
- }
3307
- if (p.app_destination && p.lead_gen_form_id) {
3308
- ctx.addIssue({
3309
- code: "custom",
3310
- path: ["app_destination"],
3311
- message: "a button opens a conversation or an instant form, not both \u2014 drop app_destination or lead_gen_form_id"
3312
- });
3313
- }
3314
- }
3315
- var creativeEnhancementsSchema = z12.strictObject({
3316
- standardEnhancements: z12.enum(ENROLL_STATUSES).optional(),
3317
- features: z12.record(z12.string(), z12.enum(ENROLL_STATUSES)).optional()
3318
- });
3319
- var multiAdvertiserSchema = z12.enum(["opt_in", "opt_out"]);
3320
- var partnerSchema = z12.strictObject({
3321
- facebook_page_id: z12.string().regex(NUMERIC_ID_REGEX).optional(),
3322
- instagram_user_id: z12.string().regex(NUMERIC_ID_REGEX).optional(),
3323
- ad_format: z12.enum(["both", "first_only", "auto"]).optional()
3324
- }).refine(
3325
- (p) => p.facebook_page_id !== void 0 || p.instagram_user_id !== void 0,
3326
- "name the partner's Page or Instagram account"
3327
- );
3328
- var creativeSharedFields = {
3329
- name: z12.string().max(META_LIMITS.creative.nameMax).optional(),
3330
- /** Facebook Page id backing the ad's identity. */
3331
- page_id: parentRefSchema,
3332
- /** Instagram account id for IG placements (aka instagram_actor_id on read). */
3333
- instagram_user_id: z12.string().regex(NUMERIC_ID_REGEX).optional(),
3334
- /** URL tracking parameters appended to the destination, e.g. "utm_source=fb&utm_campaign=x". */
3335
- url_tags: z12.string().max(1e3).optional(),
3336
- enhancements: creativeEnhancementsSchema.optional(),
3337
- /**
3338
- * v26: on an advertiser with a shop, Meta sends eligible new ads to the shop
3339
- * as well as the website (`destination_spec` WEBSITE_AND_SHOP) unless told
3340
- * not to. `website_only` opts out (WEBSITE_AND_SHOP_OPT_OUT); unset leaves
3341
- * Meta's default. Live on v26.0: both values validate, any other is refused.
3342
- */
3343
- shop_destination: z12.enum(["website_and_shop", "website_only"]).optional(),
3344
- multi_advertiser: multiAdvertiserSchema.optional(),
3345
- partner: partnerSchema.optional()
3346
- };
3347
- var conversationAndAppFields = {
3348
- welcome_message: welcomeMessageSchema.optional(),
3349
- /**
3350
- * How a deep link opens: `deeplink_with_web_fallback` (the app, else the
3351
- * website), `deeplink_with_appstore_fallback` (the app, else its store page),
3352
- * `web_only`, or `automatic` (Meta decides).
3353
- */
3354
- applink_treatment: z12.enum(["automatic", "deeplink_with_web_fallback", "deeplink_with_appstore_fallback", "web_only"]).optional()
3355
- };
3356
- var imageMediaFields = {
3357
- imageHash: z12.string().regex(IMAGE_HASH_REGEX).optional(),
3358
- imageRef: tempRefSchema3.optional()
3359
- };
3360
- var videoMediaFields = {
3361
- videoId: z12.string().regex(NUMERIC_ID_REGEX).optional(),
3362
- videoRef: tempRefSchema3.optional(),
3363
- /** The video's cover: a picture already in the ad account, by hash. */
3364
- thumbnailHash: z12.string().regex(IMAGE_HASH_REGEX).optional(),
3365
- /** The video's cover: a library picture staged as a `media upload --kind image` in this chat. */
3366
- thumbnailRef: tempRefSchema3.optional(),
3367
- /** The video's cover: a public picture URL Meta fetches. */
3368
- imageUrl: z12.string().url().optional()
3369
- };
3370
- function validateDeepLink(cta, creativeLink, ctx, path) {
3371
- if (!cta?.app_link) return;
3372
- const link = cta.link ?? creativeLink;
3373
- if (!link || !isAppStoreUrl(link)) {
3374
- ctx.addIssue({
3375
- code: "custom",
3376
- path,
3377
- message: `a deep link (app_link) needs the button to lead to the app's store page \u2014 Meta refuses it beside ${link ?? "no link"} (subcode 1885949); set the link to the App Store or Google Play URL`
3378
- });
3379
- }
3380
- }
3381
- function isAppStoreUrl(url) {
3382
- try {
3383
- const host = new URL(url).hostname.toLowerCase();
3384
- return ["apps.apple.com", "itunes.apple.com", "play.google.com"].includes(host);
3385
- } catch {
3386
- return false;
3387
- }
3388
- }
3389
- function validateWelcomeOpensConversation(p, ctx) {
3390
- if (p.welcome_message && !p.call_to_action?.app_destination) {
3391
- ctx.addIssue({
3392
- code: "custom",
3393
- path: ["welcome_message"],
3394
- message: "a greeting needs a button that opens a conversation \u2014 set call_to_action.app_destination (MESSENGER, WHATSAPP or INSTAGRAM_DIRECT)"
3395
- });
3396
- }
3397
- }
3398
- function countImageRefs(p) {
3399
- return [p.imageHash, p.imageRef].filter(Boolean).length;
3400
- }
3401
- function countVideoRefs(p) {
3402
- return [p.videoId, p.videoRef].filter(Boolean).length;
3403
- }
3404
- var singleCreativeSchema = z12.strictObject({
3405
- creativeType: z12.literal("single"),
3406
- ...creativeSharedFields,
3407
- /** Primary text. */
3408
- message: messageSchema,
3409
- link: httpsUrlSchema5,
3410
- /** Headline. */
3411
- headline: headlineSchema.optional(),
3412
- description: descriptionSchema.optional(),
3413
- /** Display URL / caption shown under the headline. */
3414
- caption: z12.string().max(255).optional(),
3415
- call_to_action: callToActionSchema.optional(),
3416
- ...imageMediaFields,
3417
- ...videoMediaFields,
3418
- ...conversationAndAppFields
3419
- }).superRefine((p, ctx) => {
3420
- validateWelcomeOpensConversation(p, ctx);
3421
- validateDeepLink(p.call_to_action, p.link, ctx, ["call_to_action", "app_link"]);
3422
- const images = countImageRefs(p);
3423
- const videos = countVideoRefs(p);
3424
- if (images + videos === 0) {
3425
- ctx.addIssue({ code: "custom", path: ["imageHash"], message: "a single ad needs one image or one video" });
3426
- }
3427
- if (images > 1) {
3428
- ctx.addIssue({ code: "custom", path: ["imageHash"], message: "provide exactly one image reference" });
3429
- }
3430
- if (videos > 1) {
3431
- ctx.addIssue({ code: "custom", path: ["videoId"], message: "provide exactly one video reference" });
3432
- }
3433
- if (images > 0 && videos > 0) {
3434
- ctx.addIssue({
3435
- code: "custom",
3436
- path: ["videoId"],
3437
- message: "a single ad is either an image OR a video, not both"
3438
- });
3439
- }
3440
- });
3441
- var carouselCardSchema = z12.strictObject({
3442
- link: httpsUrlSchema5,
3443
- headline: z12.string().max(META_LIMITS.creative.headlineMax).optional(),
3444
- description: z12.string().max(META_LIMITS.creative.descriptionMax).optional(),
3445
- call_to_action: callToActionSchema.optional(),
3446
- ...imageMediaFields,
3447
- ...videoMediaFields
3448
- }).superRefine((p, ctx) => {
3449
- const images = countImageRefs(p);
3450
- const videos = countVideoRefs(p);
3451
- if (images + videos === 0) {
3452
- ctx.addIssue({ code: "custom", path: ["imageHash"], message: "each card needs an image or a video" });
3453
- }
3454
- if (images > 1) {
3455
- ctx.addIssue({ code: "custom", path: ["imageHash"], message: "each card needs exactly one image reference" });
3456
- }
3457
- if (videos > 1) {
3458
- ctx.addIssue({ code: "custom", path: ["videoId"], message: "each card needs exactly one video reference" });
3459
- }
3460
- if (images > 0 && videos > 0) {
3461
- ctx.addIssue({ code: "custom", path: ["videoId"], message: "each card is an image OR a video, not both" });
3462
- }
3463
- });
3464
- var carouselCreativeSchema = z12.strictObject({
3465
- creativeType: z12.literal("carousel"),
3466
- ...creativeSharedFields,
3467
- message: messageSchema,
3468
- /** Optional "see more" card destination applied when a card has no own link. */
3469
- link: httpsUrlSchema5.optional(),
3470
- call_to_action: callToActionSchema.optional(),
3471
- cards: z12.array(carouselCardSchema).min(META_LIMITS.creative.carouselCardsMin).max(META_LIMITS.creative.carouselCardsMax),
3472
- /**
3473
- * `multi_share_optimized`. Meta's default (`optimized`) reorders the cards
3474
- * by performance and may show only the top five; `fixed` — Baker's default —
3475
- * shows every card in the order it was built.
3476
- */
3477
- card_order: z12.enum(["fixed", "optimized"]).default("fixed"),
3478
- /** `multi_share_end_card`: Meta adds a card linking to the Page after the last one. Off unless asked. */
3479
- end_card: z12.boolean().default(false),
3480
- ...conversationAndAppFields
3481
- }).superRefine((p, ctx) => {
3482
- validateWelcomeOpensConversation(p, ctx);
3483
- validateDeepLink(p.call_to_action, p.link ?? p.cards[0]?.link, ctx, ["call_to_action", "app_link"]);
3484
- p.cards.forEach((card, index) => {
3485
- validateDeepLink(card.call_to_action, card.link, ctx, ["cards", index, "call_to_action", "app_link"]);
3486
- });
3487
- const forms = new Set(
3488
- [p.call_to_action?.lead_gen_form_id, ...p.cards.map((card) => card.call_to_action?.lead_gen_form_id)].filter(
3489
- Boolean
3490
- )
3491
- );
3492
- if (forms.size > 1) {
3493
- ctx.addIssue({
3494
- code: "custom",
3495
- path: ["cards"],
3496
- message: `every card of a carousel must open the SAME instant form \u2014 this one names ${[...forms].join(" and ")}`
3497
- });
3498
- }
3499
- });
3500
- var dynamicImageSchema = z12.strictObject({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
3501
- var dynamicVideoSchema = z12.strictObject({
3502
- videoId: videoMediaFields.videoId,
3503
- videoRef: videoMediaFields.videoRef,
3504
- thumbnailHash: videoMediaFields.thumbnailHash,
3505
- thumbnailRef: videoMediaFields.thumbnailRef
3506
- }).refine((p) => countVideoRefs(p) === 1, "each dynamic video needs exactly one reference");
3507
- var DYN = META_LIMITS.creative;
3508
- function assetFeedCount(p) {
3509
- return p.bodies.length + p.titles.length + (p.descriptions?.length ?? 0) + (p.images?.length ?? 0) + (p.videos?.length ?? 0) + p.link_urls.length + (p.call_to_action_types?.length ?? 0) + 1;
3510
- }
3511
- var dynamicCreativeSchema = z12.strictObject({
3512
- creativeType: z12.literal("dynamic"),
3513
- ...creativeSharedFields,
3514
- bodies: z12.array(z12.strictObject({ text: z12.string().min(1).max(DYN.assetFeedBodyMax) })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
3515
- titles: z12.array(z12.strictObject({ text: z12.string().min(1).max(DYN.assetFeedTitleMax) })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
3516
- descriptions: z12.array(z12.strictObject({ text: z12.string().min(1).max(DYN.assetFeedTitleMax) })).max(DYN.dynamicTextsMax).optional(),
3517
- images: z12.array(dynamicImageSchema).max(DYN.assetFeedImagesMax).optional(),
3518
- videos: z12.array(dynamicVideoSchema).max(DYN.assetFeedVideosMax).optional(),
3519
- /**
3520
- * Exactly one format ("Only one ad_format is allowed per asset feed").
3521
- * Meta's doc calls it required; when it is left out the builder fills it
3522
- * from the media (`AUTOMATIC_FORMAT` for pictures and videos together) —
3523
- * except on a flexible (`DEGREES_OF_FREEDOM`) creative, every one of which
3524
- * read back off a live account omits it.
3525
- */
3526
- ad_formats: z12.array(z12.enum(AD_FORMATS)).length(1).optional(),
3527
- call_to_action_types: z12.array(z12.string()).max(DYN.dynamicTextsMax).optional(),
3528
- /**
3529
- * The button on the creative's own `link_data` — a flexible ad carries both
3530
- * envelopes, and this is the one that takes `SEE_DETAILS`. Kept separate
3531
- * from `call_to_action_types` because Meta validates the two against
3532
- * different enums.
3533
- */
3534
- call_to_action: callToActionSchema.optional(),
3535
- link_urls: z12.array(z12.strictObject({ website_url: httpsUrlSchema5, display_url: z12.string().optional() })).min(1).max(DYN.dynamicTextsMax),
3536
- /**
3537
- * `asset_feed_spec.optimization_type` — passed through as a free string on
3538
- * purpose. Meta's own 400 enumerates ten values and then accepts
3539
- * `DEGREES_OF_FREEDOM`, which is not among them and is what every
3540
- * Advantage+ flexible creative on a live account reports. An enum here
3541
- * would refuse the value Meta itself hands back.
3542
- */
3543
- optimization_type: z12.string().optional(),
3544
- /** Multi-language / placement customization — structural passthrough for v1. */
3545
- asset_customization_rules: z12.array(z12.record(z12.string(), z12.unknown())).optional()
3546
- }).superRefine((p, ctx) => {
3547
- if (!(p.images?.length || p.videos?.length)) {
3548
- ctx.addIssue({
3549
- code: "custom",
3550
- path: ["images"],
3551
- message: "a dynamic creative needs at least one image or video"
3552
- });
3553
- }
3554
- const assets = assetFeedCount(p);
3555
- if (assets > DYN.assetFeedAssetsMax) {
3556
- ctx.addIssue({
3557
- code: "custom",
3558
- path: ["images"],
3559
- message: `a dynamic creative carries at most ${DYN.assetFeedAssetsMax} assets in all (pictures, videos, texts, links, buttons and the format each count) \u2014 this has ${assets}`
3560
- });
3561
- }
3562
- p.call_to_action_types?.forEach((type, index) => {
3563
- if (ASSET_FEED_CTA_TYPES.some((allowed) => allowed === type)) {
3564
- return;
3565
- }
3566
- const isLinkButton = CTA_TYPES.some((allowed) => allowed === type);
3567
- ctx.addIssue({
3568
- code: "custom",
3569
- path: ["call_to_action_types", index],
3570
- message: isLinkButton ? `${type} is not one of the buttons Meta accepts in asset_feed_spec.call_to_action_types \u2014 it is a link_data button. Pass it as call_to_action: { type: "${type}" } instead.` : `${type} is not a Meta call-to-action button.`
3571
- });
3572
- });
3573
- });
3574
- var placementAssetSchema = z12.strictObject({
3575
- ...imageMediaFields,
3576
- ...videoMediaFields,
3577
- placements: z12.array(z12.enum(PLACEMENT_SLOTS)).min(1)
3578
- }).superRefine((p, ctx) => {
3579
- const images = countImageRefs(p);
3580
- const videos = countVideoRefs(p);
3581
- if (images + videos !== 1) {
3582
- ctx.addIssue({ code: "custom", path: ["imageRef"], message: "each asset is exactly one picture or one video" });
3583
- }
3584
- if (p.placements.includes("default") && p.placements.length > 1) {
3585
- ctx.addIssue({
3586
- code: "custom",
3587
- path: ["placements"],
3588
- message: '"default" already means every placement no other asset names \u2014 give it alone'
3589
- });
3590
- }
3591
- });
3592
- var placementCreativeSchema = z12.strictObject({
3593
- creativeType: z12.literal("placement"),
3594
- ...creativeSharedFields,
3595
- message: z12.string().min(1).max(META_LIMITS.creative.assetFeedBodyMax),
3596
- link: httpsUrlSchema5,
3597
- headline: z12.string().min(1).max(META_LIMITS.creative.assetFeedTitleMax).optional(),
3598
- description: z12.string().min(1).max(META_LIMITS.creative.assetFeedTitleMax).optional(),
3599
- call_to_action: callToActionSchema.optional(),
3600
- assets: z12.array(placementAssetSchema).min(2).max(META_LIMITS.creative.assetFeedImagesMax)
3601
- }).superRefine((p, ctx) => {
3602
- const carried = ["lead_gen_form_id", "link", "app_destination", "app_link", "application"].filter(
3603
- (key) => p.call_to_action?.[key] !== void 0
3604
- );
3605
- if (carried.length > 0) {
3606
- ctx.addIssue({
3607
- code: "custom",
3608
- path: ["call_to_action"],
3609
- message: `a placement creative's button is its type only \u2014 Meta keeps no ${carried.join(", ")} on it. For an Instant Form, a different button link or a messaging app, use a single or carousel creative`
3610
- });
3611
- }
3612
- const defaults = p.assets.filter((asset) => asset.placements.includes("default")).length;
3613
- if (defaults !== 1) {
3614
- ctx.addIssue({
3615
- code: "custom",
3616
- path: ["assets"],
3617
- message: `exactly one asset must be "default" \u2014 the one every other placement shows (this has ${defaults})`
3618
- });
3619
- }
3620
- const claimed = /* @__PURE__ */ new Map();
3621
- p.assets.forEach((asset, index) => {
3622
- for (const slot of asset.placements) {
3623
- if (slot !== "default" && claimed.has(slot)) {
3624
- ctx.addIssue({
3625
- code: "custom",
3626
- path: ["assets", index, "placements"],
3627
- message: `${slot} is already given to asset ${claimed.get(slot)} \u2014 one asset per placement`
3628
- });
3629
- }
3630
- claimed.set(slot, index);
3631
- }
3632
- });
3633
- const kinds = new Set(p.assets.map((asset) => countVideoRefs(asset) > 0 ? "video" : "image"));
3634
- if (kinds.size > 1) {
3635
- ctx.addIssue({
3636
- code: "custom",
3637
- path: ["assets"],
3638
- message: "every asset of a placement creative is a picture, or every one is a video \u2014 Meta takes one format per ad"
3639
- });
3640
- }
3641
- });
3642
- var existingPostCreativeSchema = z12.strictObject({
3643
- creativeType: z12.literal("existing_post"),
3644
- name: creativeSharedFields.name,
3645
- /** "<page_id>_<post_id>" object story id of the Facebook post to promote. */
3646
- object_story_id: z12.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"').optional(),
3647
- /** An Instagram post's media id — from `baker ads meta instagram-media`. */
3648
- source_instagram_media_id: z12.string().regex(NUMERIC_ID_REGEX).optional(),
3649
- /** A creator's partnership ad code for their Instagram post. */
3650
- instagram_ad_code: z12.string().trim().min(8).max(500).optional(),
3651
- /** The brand's Page the ad runs as — needed with an Instagram post or an ad code. */
3652
- page_id: z12.string().regex(NUMERIC_ID_REGEX).optional(),
3653
- instagram_user_id: creativeSharedFields.instagram_user_id,
3654
- url_tags: creativeSharedFields.url_tags,
3655
- enhancements: creativeSharedFields.enhancements,
3656
- multi_advertiser: creativeSharedFields.multi_advertiser,
3657
- partner: creativeSharedFields.partner
3658
- }).superRefine((p, ctx) => {
3659
- const sources = [p.object_story_id, p.source_instagram_media_id, p.instagram_ad_code].filter(Boolean).length;
3660
- if (sources !== 1) {
3661
- ctx.addIssue({
3662
- code: "custom",
3663
- path: ["object_story_id"],
3664
- message: "boost ONE post: object_story_id (Facebook), source_instagram_media_id (Instagram) or instagram_ad_code"
3665
- });
3666
- }
3667
- if ((p.source_instagram_media_id || p.instagram_ad_code) && !p.page_id) {
3668
- ctx.addIssue({
3669
- code: "custom",
3670
- path: ["page_id"],
3671
- message: "an Instagram post runs as the brand's Facebook Page \u2014 add page_id"
3672
- });
3673
- }
3674
- });
3675
- var specCreativeSchema = z12.strictObject({
3676
- creativeType: z12.literal("spec"),
3677
- name: creativeSharedFields.name,
3678
- url_tags: creativeSharedFields.url_tags,
3679
- /** Promote the existing post — keeps the ad's likes, comments and shares. */
3680
- object_story_id: z12.string().regex(/^\d+_\d+$/, 'expected "<page_id>_<post_id>"').optional(),
3681
- object_story_spec: z12.record(z12.string(), z12.unknown()).optional(),
3682
- asset_feed_spec: z12.record(z12.string(), z12.unknown()).optional(),
3683
- degrees_of_freedom_spec: z12.record(z12.string(), z12.unknown()).optional(),
3684
- instagram_user_id: creativeSharedFields.instagram_user_id,
3685
- /** The creative this spec was cloned from, for the review diff. */
3686
- clonedFrom: z12.string().regex(NUMERIC_ID_REGEX).optional()
3687
- }).superRefine((p, ctx) => {
3688
- if (!(p.object_story_id || p.object_story_spec || p.asset_feed_spec)) {
3689
- ctx.addIssue({
3690
- code: "custom",
3691
- path: ["object_story_spec"],
3692
- message: "a spec creative needs object_story_id, object_story_spec or asset_feed_spec"
3693
- });
3694
- }
3695
- });
3696
- var CATALOG_TOKEN_NAMESPACES = [
3697
- "product",
3698
- "category",
3699
- "hotel",
3700
- "flight",
3701
- "destination",
3702
- "home_listing",
3703
- "vehicle",
3704
- "vehicle_offer",
3705
- "trip"
3706
- ];
3707
- function unknownCatalogTokens(text) {
3708
- return [...(text ?? "").matchAll(/\{\{\s*([^}|\s]+)[^}]*\}\}/g)].filter((match) => !CATALOG_TOKEN_NAMESPACES.some((ns) => match[1]?.startsWith(`${ns}.`))).map((match) => match[0]);
3709
- }
3710
- var templateText = (max) => z12.string().trim().min(1).max(max);
3711
- var catalogCreativeSchema = z12.strictObject({
3712
- creativeType: z12.literal("catalog"),
3713
- name: creativeSharedFields.name,
3714
- page_id: creativeSharedFields.page_id,
3715
- instagram_user_id: creativeSharedFields.instagram_user_id,
3716
- url_tags: creativeSharedFields.url_tags,
3717
- /** A product set's id, or the meta_temp_* ref of one this chat creates. */
3718
- product_set_id: parentRefSchema,
3719
- message: templateText(META_LIMITS.creative.messageHardMax),
3720
- link: httpsUrlSchema5,
3721
- headline: templateText(255).optional(),
3722
- description: templateText(255).optional(),
3723
- call_to_action: z12.strictObject({ type: z12.enum(CTA_TYPES) }).optional(),
3724
- /**
3725
- * `carousel` (Meta picks the products, one card each — the default),
3726
- * `single` (one product per ad: `force_single_link`), or `slideshow` (each
3727
- * card cycles a product's pictures: `format_option: carousel_slideshows`).
3728
- */
3729
- format: z12.enum(["carousel", "single", "slideshow"]).default("carousel"),
3730
- /** `multi_share_end_card`: a last card linking to the Page. Off unless asked. */
3731
- end_card: z12.boolean().default(false)
3732
- }).superRefine((p, ctx) => {
3733
- for (const key of ["message", "headline", "description"]) {
3734
- const unknown = unknownCatalogTokens(p[key]);
3735
- if (unknown.length > 0) {
3736
- ctx.addIssue({
3737
- code: "custom",
3738
- path: [key],
3739
- message: `${unknown.join(", ")} reads no catalog field \u2014 a token names its catalog type, e.g. {{product.name}}, {{product.price}}`
3740
- });
3741
- }
3742
- }
3743
- });
3744
- var instantExperienceCreativeSchema = z12.strictObject({
3745
- creativeType: z12.literal("instant_experience"),
3746
- name: creativeSharedFields.name,
3747
- page_id: creativeSharedFields.page_id,
3748
- instagram_user_id: creativeSharedFields.instagram_user_id,
3749
- url_tags: creativeSharedFields.url_tags,
3750
- /** The experience: its id, or the meta_temp_* ref of one this chat creates. */
3751
- canvas_id: parentRefSchema,
3752
- message: messageSchema,
3753
- headline: headlineSchema.optional(),
3754
- description: descriptionSchema.optional(),
3755
- call_to_action: z12.strictObject({ type: z12.enum(CTA_TYPES) }).optional(),
3756
- format: z12.enum(["standard", "collection"]).default("standard"),
3757
- /**
3758
- * A collection over a photo experience (more than header → product set →
3759
- * footer) shows four pictures under its hero, named by the experience's
3760
- * elements: a photo element, or one product of a product-set element
3761
- * (`element_child_index`). Meta refuses such a collection without four
3762
- * (2131023). Only a live experience has element ids — read them with
3763
- * `instant-experiences --page-id`.
3764
- */
3765
- collection_thumbnails: z12.array(
3766
- z12.strictObject({
3767
- element_id: z12.string().regex(NUMERIC_ID_REGEX),
3768
- element_child_index: z12.number().int().min(0).optional(),
3769
- /**
3770
- * The square of a photo element shown, in the photo's pixels:
3771
- * `{"100x100": [[left, top], [right, bottom]]}` — Meta's only key.
3772
- * Required on a photo element (live); staging fills a centered
3773
- * square from the photo when it is left out.
3774
- */
3775
- element_crops: z12.strictObject({
3776
- "100x100": z12.tuple([
3777
- z12.tuple([z12.number().int().min(0), z12.number().int().min(0)]),
3778
- z12.tuple([z12.number().int().positive(), z12.number().int().positive()])
3779
- ])
3780
- }).optional()
3781
- })
3782
- ).length(4, "a collection shows exactly four pictures under its hero").optional(),
3783
- ...imageMediaFields,
3784
- ...videoMediaFields
3785
- }).superRefine((p, ctx) => {
3786
- if (p.collection_thumbnails && (p.format !== "collection" || !NUMERIC_ID_REGEX.test(p.canvas_id))) {
3787
- ctx.addIssue({
3788
- code: "custom",
3789
- path: ["collection_thumbnails"],
3790
- message: "collection thumbnails go on a --format collection ad over a live Instant Experience (its elements have ids only once it exists)"
3791
- });
3792
- }
3793
- const images = countImageRefs(p);
3794
- const videos = countVideoRefs(p);
3795
- if (images + videos !== 1) {
3796
- ctx.addIssue({
3797
- code: "custom",
3798
- path: ["imageHash"],
3799
- message: "the ad shows one picture or one video before it opens the experience"
3800
- });
3801
- }
3802
- });
3803
- var creativeContentSchema = z12.discriminatedUnion("creativeType", [
3804
- singleCreativeSchema,
3805
- carouselCreativeSchema,
3806
- dynamicCreativeSchema,
3807
- placementCreativeSchema,
3808
- existingPostCreativeSchema,
3809
- specCreativeSchema,
3810
- catalogCreativeSchema,
3811
- instantExperienceCreativeSchema
3812
- ]);
3813
- var adCreativeCreateSchema = creativeContentSchema;
3814
- var adCreativeUpdateSchema = z12.strictObject({
3815
- name: z12.string().max(META_LIMITS.creative.nameMax).optional(),
3816
- status: z12.enum(CREATIVE_UPDATE_STATUSES).optional(),
3817
- /** Content patch — only honored when the target is a staged meta_temp_* creative. */
3818
- content: z12.record(z12.string(), z12.unknown()).optional(),
3819
- ...labelFields
3820
- }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
3821
- var adCreateSchema = z12.strictObject({
3822
- name: z12.string().min(1).max(META_LIMITS.ad.nameMax),
3823
- adset_id: parentRefSchema,
3824
- status: stageableStatusSchema.default("PAUSED"),
3825
- creative: z12.strictObject({ creative_id: parentRefSchema }),
3826
- /** Conversion pixel / offline event set / view tags — structural passthrough. */
3827
- tracking_specs: z12.array(z12.record(z12.string(), z12.unknown())).optional(),
3828
- /**
3829
- * The website domain the ad's conversions are counted on — the registrable
3830
- * domain only (`example.com`, never `www.example.com` or a URL). Meta fills
3831
- * it from the destination when left out; set it when the site and the
3832
- * pixel's domain differ. Create-only on Meta's ad reference.
3833
- */
3834
- conversion_domain: z12.string().trim().toLowerCase().regex(/^(?!www\.)[a-z0-9-]+(\.[a-z0-9-]+)+$/, "the domain alone, e.g. example.com (no www., no https://)").optional(),
3835
- ...createLabelFields
3836
- });
3837
- var adUpdateSchema = z12.strictObject({
3838
- name: z12.string().min(1).max(META_LIMITS.ad.nameMax).optional(),
3839
- status: updateStatusSchema.optional(),
3840
- /** Swapping the creative is the Meta way to "edit" an ad's creative. */
3841
- creative: z12.strictObject({ creative_id: parentRefSchema }).optional(),
3842
- tracking_specs: z12.array(z12.record(z12.string(), z12.unknown())).optional(),
3843
- ...labelFields
3844
- }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
3845
- var lookalikeRatioSchema = z12.number().min(0.01).max(0.2).refine(
3846
- (ratio) => Math.abs(Math.round(ratio * 100) - ratio * 100) < 1e-9,
3847
- "Meta sizes a lookalike in 1% steps (0.01\u20130.20)"
3848
- );
3849
- var lookalikeSpecSchema = z12.strictObject({
3850
- origin: z12.array(
3851
- z12.strictObject({
3852
- // An audience this chat creates holds nobody until it publishes and Meta
3853
- // matches it, and Meta refuses a lookalike of an empty seed (1713008).
3854
- id: z12.string().regex(
3855
- NUMERIC_ID_REGEX,
3856
- "a lookalike's seed must already hold people \u2014 an audience this chat creates is empty until it publishes and Meta matches it (up to a day); make the lookalike in a later chat"
3857
- )
3858
- })
3859
- ).min(1).max(1, "Meta builds a lookalike from one seed audience \u2014 make one lookalike per seed").optional(),
3860
- conversions_of: z12.array(z12.string().regex(NUMERIC_ID_REGEX, "a live campaign or ad set id")).min(1).max(10).optional(),
3861
- ratio: lookalikeRatioSchema,
3862
- starting_ratio: z12.number().min(0).max(0.19).refine(
3863
- (ratio) => Math.abs(Math.round(ratio * 100) - ratio * 100) < 1e-9,
3864
- "a band starts on a whole percent (0.00, 0.01, \u2026 0.19)"
3865
- ).optional(),
3866
- country: z12.string().length(2).optional(),
3867
- countries: z12.array(z12.string().length(2)).min(1).max(50).optional(),
3868
- allow_international_seeds: z12.boolean().optional()
3869
- }).superRefine((spec, ctx) => {
3870
- if (spec.origin === void 0 === (spec.conversions_of === void 0)) {
3871
- ctx.addIssue({
3872
- code: "custom",
3873
- path: ["origin"],
3874
- message: "a lookalike has one seed: an audience (origin) or the people who converted in live campaigns or ad sets (conversions_of)"
3875
- });
3876
- }
3877
- if (!spec.country && !spec.countries) {
3878
- ctx.addIssue({
3879
- code: "custom",
3880
- path: ["country"],
3881
- message: "a lookalike is found in a country \u2014 name one (country) or several (countries)"
3882
- });
3883
- }
3884
- if (spec.country && spec.countries) {
3885
- ctx.addIssue({
3886
- code: "custom",
3887
- path: ["countries"],
3888
- message: "name one country or a list of countries, not both"
3889
- });
3890
- }
3891
- if (spec.starting_ratio !== void 0 && (spec.ratio === void 0 || spec.starting_ratio >= spec.ratio)) {
3892
- ctx.addIssue({
3893
- code: "custom",
3894
- path: ["starting_ratio"],
3895
- message: "starting_ratio begins a band that ends at ratio, so it needs a larger ratio (0.01 to 0.03 is the 1%\u20133% band)"
3896
- });
3897
- }
3898
- });
3899
- function valuesOfKey(node, key) {
3900
- if (Array.isArray(node)) return node.flatMap((entry) => valuesOfKey(entry, key));
3901
- if (!node || typeof node !== "object") return [];
3902
- const record = node;
3903
- return [
3904
- ...key in record ? [record[key]] : [],
3905
- ...Object.values(record).flatMap((value) => valuesOfKey(value, key))
3906
- ];
3907
- }
3908
- function mixedEventSourceTypes(rule) {
3909
- const types = valuesOfKey(rule, "event_sources").flatMap((sources) => Array.isArray(sources) ? sources : []).map((source) => source?.type).filter((type) => typeof type === "string");
3910
- const distinct = [...new Set(types)].sort();
3911
- return distinct.length > 1 ? distinct : [];
3912
- }
3913
- var customAudienceMemberSchema = z12.strictObject({
3914
- email: z12.string().min(1).optional(),
3915
- phone: z12.string().min(1).optional(),
3916
- /** Two-letter ISO country (US, GB) — Meta reads a phone without its country code against it. */
3917
- country: z12.string().min(1).optional()
3918
- }).refine((m) => m.email !== void 0 || m.phone !== void 0, "each person needs an email or a phone");
3919
- var customAudienceCreateSchema = z12.strictObject({
3920
- name: z12.string().min(1).max(META_LIMITS.audience.nameMax),
3921
- subtype: z12.enum(CUSTOM_AUDIENCE_SUBTYPES),
3922
- description: z12.string().max(500).optional(),
3923
- customer_file_source: z12.enum(CUSTOMER_FILE_SOURCES).optional(),
3924
- retention_days: z12.number().int().min(1).max(META_LIMITS.audience.retentionDaysMax).optional(),
3925
- lookalike_spec: lookalikeSpecSchema.optional(),
3926
- /** Website/engagement rule — structural passthrough validated by Meta. */
3927
- rule: z12.record(z12.string(), z12.unknown()).optional(),
3928
- /** The people of a customer list (subtype CUSTOM), uploaded right after the audience is created at publish. */
3929
- members: z12.array(customAudienceMemberSchema).min(1).max(META_LIMITS.audience.membersMax).optional(),
3930
- /**
3931
- * A value-based customer list: each person carries what they are worth
3932
- * (the LOOKALIKE_VALUE column), and a lookalike of it finds people like
3933
- * the most valuable ones. Fixed at creation.
3934
- */
3935
- is_value_based: z12.boolean().optional()
3936
- }).superRefine((p, ctx) => {
3937
- if (p.members && p.subtype !== "CUSTOM") {
3938
- ctx.addIssue({
3939
- code: "custom",
3940
- path: ["members"],
3941
- message: "only a customer list (subtype CUSTOM) is made of people you upload \u2014 drop members or use subtype CUSTOM"
3942
- });
3943
- }
3944
- if (p.members && p.is_value_based) {
3945
- ctx.addIssue({
3946
- code: "custom",
3947
- path: ["members"],
3948
- message: "a value-based list needs a value for each person \u2014 create it without members, then use audiences members add with a LOOKALIKE_VALUE column"
3949
- });
3950
- }
3951
- if (p.is_value_based && (p.subtype !== "CUSTOM" || !p.customer_file_source)) {
3952
- ctx.addIssue({
3953
- code: "custom",
3954
- path: ["is_value_based"],
3955
- message: "a value-based audience is a customer list \u2014 subtype CUSTOM with customer_file_source"
3956
- });
3957
- }
3958
- if (p.subtype === "LOOKALIKE" && !p.lookalike_spec) {
3959
- ctx.addIssue({ code: "custom", path: ["lookalike_spec"], message: "LOOKALIKE audiences need a lookalike_spec" });
3960
- }
3961
- if ((p.subtype === "WEBSITE" || p.subtype === "ENGAGEMENT") && !p.rule) {
3962
- ctx.addIssue({ code: "custom", path: ["rule"], message: `${p.subtype} audiences need a rule (use --file)` });
3963
- }
3964
- if (p.rule && p.retention_days !== void 0) {
3965
- ctx.addIssue({
3966
- code: "custom",
3967
- path: ["retention_days"],
3968
- message: "a rule carries its own window in retention_seconds, so drop retention_days \u2014 Meta takes it only on a customer-file audience, and sending both leaves the review showing a window the audience will not have"
3969
- });
3970
- }
3971
- const mixed = mixedEventSourceTypes(p.rule);
3972
- if (mixed.length > 0) {
3973
- ctx.addIssue({
3974
- code: "custom",
3975
- path: ["rule"],
3976
- message: `one audience covers one kind of source, but this rule mixes ${mixed.join(" and ")} \u2014 split it into one audience per source`
3977
- });
3978
- }
3979
- });
3980
- var customAudienceUpdateSchema = z12.strictObject({
3981
- name: z12.string().min(1).max(META_LIMITS.audience.nameMax).optional(),
3982
- description: z12.string().max(500).optional(),
3983
- customer_file_source: z12.enum(CUSTOMER_FILE_SOURCES).optional(),
3984
- opt_out_link: httpsUrlSchema5.optional(),
3985
- rule: z12.record(z12.string(), z12.unknown()).optional(),
3986
- status: z12.literal("DELETED").optional()
3987
- }).superRefine((p, ctx) => {
3988
- if (!Object.values(p).some((val) => val !== void 0)) {
3989
- ctx.addIssue({ code: "custom", message: "update needs at least one field" });
3990
- }
3991
- if (p.status === "DELETED" && Object.values(p).filter((val) => val !== void 0).length > 1) {
3992
- ctx.addIssue({ code: "custom", path: ["status"], message: "a deleted audience takes no other change" });
3993
- }
3994
- const mixed = mixedEventSourceTypes(p.rule);
3995
- if (mixed.length > 0) {
3996
- ctx.addIssue({
3997
- code: "custom",
3998
- path: ["rule"],
3999
- message: `one audience covers one kind of source, but this rule mixes ${mixed.join(" and ")} \u2014 split it into one audience per source`
4000
- });
4001
- }
4002
- });
4003
- var customConversionCreateSchema = z12.strictObject({
4004
- name: z12.string().min(1).max(META_LIMITS.customConversion.nameMax),
4005
- description: z12.string().max(META_LIMITS.customConversion.descriptionMax).optional(),
4006
- /** The pixel the conversion counts from — `event_source_id` on the wire. Baker never creates pixels, so this is always a real id. */
4007
- pixel_id: z12.string().regex(NUMERIC_ID_REGEX),
4008
- custom_event_type: z12.enum(CUSTOM_EVENT_TYPES),
4009
- /** Meta's filter JSON. Built by `buildCustomConversionRule` for the URL case. */
4010
- rule: z12.record(z12.string(), z12.unknown()),
4011
- /** What one conversion is worth, when the site cannot send a value with the event. */
4012
- default_conversion_value: z12.number().min(0).optional()
4013
- }).superRefine((p, ctx) => {
4014
- const refusal = customConversionRuleRefusal(p.rule);
4015
- if (refusal) {
4016
- ctx.addIssue({ code: "custom", path: ["rule"], message: refusal });
4017
- }
4018
- });
4019
- var customConversionUpdateSchema = z12.strictObject({
4020
- name: z12.string().min(1).max(META_LIMITS.customConversion.nameMax).optional(),
4021
- description: z12.string().max(META_LIMITS.customConversion.descriptionMax).optional(),
4022
- default_conversion_value: z12.number().min(0).optional(),
4023
- status: z12.literal("DELETED").optional()
4024
- }).superRefine((p, ctx) => {
4025
- const set = Object.values(p).filter((val) => val !== void 0);
4026
- if (set.length === 0) {
4027
- ctx.addIssue({ code: "custom", message: "update needs at least one field" });
4028
- }
4029
- if (p.status === "DELETED" && set.length > 1) {
4030
- ctx.addIssue({ code: "custom", path: ["status"], message: "a deleted conversion takes no other change" });
4031
- }
4032
- });
4033
- var adLabelCreateSchema = z12.strictObject({
4034
- name: z12.string().trim().min(1).max(META_LIMITS.adLabel.nameMax)
4035
- });
4036
- var adLabelUpdateSchema = z12.strictObject({
4037
- name: z12.string().trim().min(1).max(META_LIMITS.adLabel.nameMax).optional(),
4038
- status: z12.literal("DELETED").optional()
4039
- }).refine((p) => p.name === void 0 !== (p.status === void 0), "rename the label or delete it \u2014 one of them");
4040
- var mediaDeleteSchema = z12.strictObject({
4041
- imageHash: z12.string().regex(IMAGE_HASH_REGEX).optional(),
4042
- /**
4043
- * Or a video, taken out of the ad account's video library
4044
- * (`DELETE /act_<id>/advideos?video_id=`). Live on v26.0, `DELETE /{video_id}`
4045
- * was refused with the user token and the Page token alike (1363055 "You
4046
- * might not have permission to delete this video"), with `pages_manage_posts`
4047
- * granted; the library delete took it off the account.
4048
- */
4049
- videoId: z12.string().regex(NUMERIC_ID_REGEX).optional()
4050
- }).refine((p) => p.imageHash === void 0 !== (p.videoId === void 0), "name imageHash OR videoId");
4051
- var mediaUploadSchema = z12.strictObject({
4052
- kind: z12.enum(MEDIA_KINDS),
4053
- bakerImageId: bakerMediaIdSchema.optional(),
4054
- bakerVideoId: bakerMediaIdSchema.optional(),
4055
- /** Optional display name / filename hint. */
4056
- name: z12.string().max(255).optional()
4057
- }).superRefine((p, ctx) => {
4058
- if (p.kind === "image" && !p.bakerImageId) {
4059
- ctx.addIssue({ code: "custom", path: ["bakerImageId"], message: "image uploads need a bakerImageId" });
4060
- }
4061
- if (p.kind === "video" && !p.bakerVideoId) {
4062
- ctx.addIssue({ code: "custom", path: ["bakerVideoId"], message: "video uploads need a bakerVideoId" });
4063
- }
4064
- });
4065
- var adAccountUpdateSchema = z12.strictObject({
4066
- name: z12.string().trim().min(1).max(100).optional(),
4067
- /** The account spending limit — spending stops when the account has spent this since it was set. */
4068
- spendCap: moneySchema.optional(),
4069
- /** `remove`: no limit at all. `reset`: start counting toward the limit again from zero. */
4070
- spendCapAction: z12.enum(["remove", "reset"]).optional(),
4071
- /**
4072
- * The EU (DSA) advertiser and payer every new ad set on the account starts
4073
- * with (`default_dsa_beneficiary` / `default_dsa_payor`). Meta keeps both or
4074
- * neither, and clears them with two empty strings (`clearDefaultDsa`).
4075
- * Written on the account node, which ignores `validate_only`.
4076
- */
4077
- defaultDsaBeneficiary: z12.string().trim().min(1).max(512).optional(),
4078
- defaultDsaPayor: z12.string().trim().min(1).max(512).optional(),
4079
- clearDefaultDsa: z12.literal(true).optional()
4080
- }).superRefine((p, ctx) => {
4081
- const dsa = [p.defaultDsaBeneficiary, p.defaultDsaPayor].filter((value) => value !== void 0).length;
4082
- if (p.name === void 0 && p.spendCap === void 0 && p.spendCapAction === void 0 && dsa === 0 && !p.clearDefaultDsa) {
4083
- ctx.addIssue({
4084
- code: "custom",
4085
- message: "name, spendCap, spendCapAction, the default EU advertiser and payer, or clearDefaultDsa is required"
4086
- });
4087
- }
4088
- if (dsa === 1) {
4089
- ctx.addIssue({
4090
- code: "custom",
4091
- path: ["defaultDsaPayor"],
4092
- message: "Meta keeps the default EU advertiser and payer together \u2014 pass both (the same name when one business does both)"
4093
- });
4094
- }
4095
- if (dsa > 0 && p.clearDefaultDsa) {
4096
- ctx.addIssue({ code: "custom", path: ["clearDefaultDsa"], message: "set the defaults OR clear them, not both" });
4097
- }
4098
- if (p.spendCap !== void 0 && p.spendCapAction === "remove") {
4099
- ctx.addIssue({
4100
- code: "custom",
4101
- path: ["spendCapAction"],
4102
- message: "set a spending limit OR remove it, not both"
4103
- });
4104
- }
4105
- });
4106
- var META_DRAFT_OP_KINDS = [
4107
- "campaign.create",
4108
- "campaign.update",
4109
- "adSet.create",
4110
- "adSet.update",
4111
- "adCreative.create",
4112
- "adCreative.update",
4113
- "ad.create",
4114
- "ad.update",
4115
- "customAudience.create",
4116
- "customAudience.update",
4117
- "customAudience.members",
4118
- "customConversion.create",
4119
- "customConversion.update",
4120
- "leadForm.create",
4121
- "leadForm.update",
4122
- "media.upload",
4123
- "media.delete",
4124
- "adLabel.create",
4125
- "adLabel.update",
4126
- "adRule.create",
4127
- "adRule.update",
4128
- "adStudy.create",
4129
- "adStudy.update",
4130
- "campaign.copy",
4131
- "adSet.copy",
4132
- "ad.copy",
4133
- "canvas.create",
4134
- "canvas.update",
4135
- "productCatalog.create",
4136
- "productCatalog.update",
4137
- "product.create",
4138
- "product.update",
4139
- "productSet.create",
4140
- "productSet.update",
4141
- "productFeed.create",
4142
- "productFeed.update",
4143
- "pagePhoto.create",
4144
- "pagePhoto.update",
4145
- "adAccount.update",
4146
- "publisherBlockList.create",
4147
- "publisherBlockList.update",
4148
- "reachFrequencyReservation.create",
4149
- "reachFrequencyReservation.update"
4150
- ];
4151
- var metaDraftOpKindSchema = z12.enum(META_DRAFT_OP_KINDS);
4152
- var accountIdSchema = z12.string().regex(NUMERIC_ID_REGEX, "accountId must be the bare numeric ad account id");
4153
- var updateTargetSchema = z12.union([z12.string().regex(NUMERIC_ID_REGEX), tempRefSchema3]);
4154
- function createOp(kind, payload) {
4155
- return z12.object({ kind: z12.literal(kind), accountId: accountIdSchema, payload });
4156
- }
4157
- function updateOp(kind, payload) {
4158
- return z12.object({ kind: z12.literal(kind), accountId: accountIdSchema, target: updateTargetSchema, payload });
4159
- }
4160
- function budgetUpdateOp(kind, payload) {
4161
- return updateOp(kind, payload).extend({ confirmBudgetIncrease: z12.boolean().optional() });
4162
- }
4163
- var metaDraftOpInputSchema = z12.discriminatedUnion("kind", [
4164
- createOp("campaign.create", campaignCreateSchema),
4165
- budgetUpdateOp("campaign.update", campaignUpdateSchema),
4166
- createOp("adSet.create", adSetCreateSchema),
4167
- budgetUpdateOp("adSet.update", adSetUpdateSchema),
4168
- createOp("adCreative.create", adCreativeCreateSchema),
4169
- updateOp("adCreative.update", adCreativeUpdateSchema),
4170
- createOp("ad.create", adCreateSchema),
4171
- updateOp("ad.update", adUpdateSchema),
4172
- createOp("customAudience.create", customAudienceCreateSchema),
4173
- updateOp("customAudience.update", customAudienceUpdateSchema),
4174
- createOp("customAudience.members", customAudienceMembersSchema),
4175
- createOp("customConversion.create", customConversionCreateSchema),
4176
- updateOp("customConversion.update", customConversionUpdateSchema),
4177
- createOp("leadForm.create", leadFormCreateSchema),
4178
- updateOp("leadForm.update", leadFormUpdateSchema),
4179
- createOp("media.upload", mediaUploadSchema),
4180
- createOp("media.delete", mediaDeleteSchema),
4181
- createOp("adLabel.create", adLabelCreateSchema),
4182
- updateOp("adLabel.update", adLabelUpdateSchema),
4183
- createOp("adRule.create", adRuleCreateSchema),
4184
- updateOp("adRule.update", adRuleUpdateSchema),
4185
- createOp("adStudy.create", adStudyCreateSchema),
4186
- updateOp("adStudy.update", adStudyUpdateSchema),
4187
- createOp("campaign.copy", campaignCopySchema),
4188
- createOp("adSet.copy", adSetCopySchema),
4189
- createOp("ad.copy", adCopySchema),
4190
- createOp("canvas.create", canvasCreateSchema),
4191
- updateOp("canvas.update", canvasUpdateSchema),
4192
- createOp("productCatalog.create", productCatalogCreateSchema),
4193
- updateOp("productCatalog.update", productCatalogUpdateSchema),
4194
- createOp("product.create", productCreateSchema),
4195
- updateOp("product.update", productUpdateSchema),
4196
- createOp("productSet.create", productSetCreateSchema),
4197
- updateOp("productSet.update", productSetUpdateSchema),
4198
- createOp("productFeed.create", productFeedCreateSchema),
4199
- updateOp("productFeed.update", productFeedUpdateSchema),
4200
- createOp("pagePhoto.create", pagePhotoCreateSchema),
4201
- updateOp("pagePhoto.update", pagePhotoUpdateSchema),
4202
- updateOp("adAccount.update", adAccountUpdateSchema),
4203
- createOp("publisherBlockList.create", publisherBlockListCreateSchema),
4204
- updateOp("publisherBlockList.update", publisherBlockListUpdateSchema),
4205
- createOp("reachFrequencyReservation.create", reachFrequencyReservationCreateSchema),
4206
- updateOp("reachFrequencyReservation.update", reachFrequencyReservationUpdateSchema)
4207
- ]);
4208
-
4209
- export {
4210
- buildCustomConversionRule,
4211
- isMetaLeadAdsRefusal,
4212
- FACEBOOK_PREVIEW_FORMATS,
4213
- INSTAGRAM_PREVIEW_FORMATS,
4214
- PLATFORM_SCOPED_POSITIONS,
4215
- previewFormatForPosition,
4216
- placementFormatNote,
4217
- brandSafetyTargetingFields,
4218
- retailerIdFilter,
4219
- CUSTOMER_LIST_KEYS,
4220
- UNHASHED_CUSTOMER_LIST_KEYS,
4221
- IDENTIFYING_CUSTOMER_LIST_KEYS,
4222
- CUSTOMER_LIST_BATCH_ROWS,
4223
- CUSTOMER_LIST_MAX_BATCHES,
4224
- customerListBatchSchema,
4225
- customAudienceMembersSchema,
4226
- metaTargetingSchema,
4227
- metaDraftOpInputSchema
4228
- };
4229
- //# sourceMappingURL=chunk-VIPKDXGU.js.map