@koda-sl/baker-cli 0.379.0-dev.600795410 → 0.379.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -70,9 +70,8 @@ import {
70
70
  validateCanvasDeep,
71
71
  withoutCastName,
72
72
  ytDlpBlockSignal
73
- } from "./chunk-CHJOTJTZ.js";
73
+ } from "./chunk-FGHMWBUD.js";
74
74
  import {
75
- META_ACCOUNTS_CACHE,
76
75
  NAME_CONTAINS_ARG,
77
76
  csvOrJson,
78
77
  daysAgoIso,
@@ -82,7 +81,7 @@ import {
82
81
  resolveEffectiveStatus,
83
82
  statusFilterHints,
84
83
  todayIso
85
- } from "./chunk-MK4AIHRF.js";
84
+ } from "./chunk-VLUGGVJL.js";
86
85
  import {
87
86
  buildQueryCacheKey,
88
87
  cacheGet,
@@ -24296,14 +24295,11 @@ Examples:
24296
24295
  BAKER_META_AD_ACCOUNT_ID=act_123 baker ads meta account`
24297
24296
  },
24298
24297
  args: {
24299
- "account-id": {
24300
- type: "string",
24301
- description: "Meta ad account ID (act_...); defaults to the only connected account"
24302
- },
24298
+ "account-id": { type: "string", description: "Meta ad account ID (act_...)" },
24303
24299
  "no-cache": NO_CACHE_ARG
24304
24300
  },
24305
24301
  run: async ({ args: args5 }) => {
24306
- const accountId = await resolveAccountIdArg(args5);
24302
+ const accountId = resolveAccountIdArg(args5);
24307
24303
  try {
24308
24304
  const params = { "account-id": accountId };
24309
24305
  if (args5["no-cache"]) params["skip-cache"] = "true";
@@ -24349,9 +24345,9 @@ Examples:
24349
24345
  run: async ({ args: args5 }) => {
24350
24346
  const includeAll = args5["include-all"] === true;
24351
24347
  const useCache = !args5["no-cache"];
24352
- const cacheKey = includeAll ? "accounts:all" : META_ACCOUNTS_CACHE.key;
24348
+ const cacheKey = `accounts:${includeAll ? "all" : "scoped"}`;
24353
24349
  if (useCache) {
24354
- const cached = cacheGet(META_ACCOUNTS_CACHE.category, cacheKey);
24350
+ const cached = cacheGet("meta-accounts", cacheKey);
24355
24351
  if (cached) {
24356
24352
  writeJsonEnvelope({
24357
24353
  ok: true,
@@ -24368,7 +24364,7 @@ Examples:
24368
24364
  if (!useCache) params["skip-cache"] = "true";
24369
24365
  const data = await apiGet("/api/ads/meta/accounts", params);
24370
24366
  if (useCache) {
24371
- cacheSet(META_ACCOUNTS_CACHE.category, cacheKey, data, META_ACCOUNTS_CACHE.ttlMs);
24367
+ cacheSet("meta-accounts", cacheKey, data, 60 * 60 * 1e3);
24372
24368
  }
24373
24369
  const fmt = csvOrJson(args5);
24374
24370
  if (fmt !== "json") {
@@ -24541,7 +24537,7 @@ function registerMetaListSchema(kind, description, args5) {
24541
24537
 
24542
24538
  // src/commands/ads/meta/activities.ts
24543
24539
  var listArgs4 = {
24544
- "account-id": { type: "string", description: "Meta ad account ID (act_...); defaults to the only connected account" },
24540
+ "account-id": { type: "string", description: "Meta ad account ID" },
24545
24541
  days: { type: "string", description: "Lookback days (default 7)" },
24546
24542
  limit: { type: "string", description: "Max rows" },
24547
24543
  "no-cache": NO_CACHE_ARG,
@@ -24570,7 +24566,7 @@ Examples:
24570
24566
  },
24571
24567
  args: listArgs4,
24572
24568
  run: async ({ args: args5 }) => {
24573
- const accountId = await resolveAccountIdArg(args5);
24569
+ const accountId = resolveAccountIdArg(args5);
24574
24570
  try {
24575
24571
  const params = { "account-id": accountId };
24576
24572
  if (args5.days) params.days = args5.days;
@@ -25150,7 +25146,8 @@ var LEAD_FORM_CTA_TYPES = [
25150
25146
  var AD_FORMATS2 = ["SINGLE_IMAGE", "CAROUSEL", "SINGLE_VIDEO"];
25151
25147
  var ENROLL_STATUSES = ["OPT_IN", "OPT_OUT"];
25152
25148
  var STAGEABLE_CREATE_STATUSES4 = ["ACTIVE", "PAUSED"];
25153
- var UPDATE_STATUSES = ["ACTIVE", "PAUSED", "ARCHIVED"];
25149
+ var UPDATE_STATUSES = ["ACTIVE", "PAUSED", "ARCHIVED", "DELETED"];
25150
+ var CREATIVE_UPDATE_STATUSES = ["ACTIVE", "PAUSED", "ARCHIVED"];
25154
25151
  var CUSTOM_AUDIENCE_SUBTYPES = ["CUSTOM", "WEBSITE", "ENGAGEMENT", "LOOKALIKE"];
25155
25152
  var CUSTOMER_FILE_SOURCES = [
25156
25153
  "USER_PROVIDED_ONLY",
@@ -25373,7 +25370,7 @@ function positionsMissingRequiredFeed(targeting) {
25373
25370
  // ../api/src/ads-meta/ops.ts
25374
25371
  var tempRefSchema4 = z37.string().regex(TEMP_REF_REGEX4, "expected a meta_temp_* reference");
25375
25372
  var parentRefSchema3 = z37.union([z37.string().regex(NUMERIC_ID_REGEX3, "expected a numeric id"), tempRefSchema4]);
25376
- var moneySchema2 = z37.object({
25373
+ var moneySchema2 = z37.strictObject({
25377
25374
  amount: z37.string().regex(/^\d+(\.\d{1,3})?$/, "expected a decimal amount like 50 or 50.00").refine((val) => Number(val) > 0, "amount must be greater than zero"),
25378
25375
  currencyCode: z37.string().length(3).optional()
25379
25376
  });
@@ -25461,7 +25458,7 @@ function targetingHardLimitsDemographics(t) {
25461
25458
  return narrowsAgeMax || narrowsAgeMin || narrowsGender;
25462
25459
  }
25463
25460
  var specialAdCategoriesSchema = z37.array(z37.enum(SPECIAL_AD_CATEGORIES)).default(["NONE"]);
25464
- var campaignCreateSchema4 = z37.object({
25461
+ var campaignCreateSchema4 = z37.strictObject({
25465
25462
  name: z37.string().min(1).max(META_LIMITS.campaign.nameMax),
25466
25463
  objective: z37.enum(OBJECTIVES2),
25467
25464
  status: stageableStatusSchema3.default("PAUSED"),
@@ -25499,7 +25496,7 @@ var campaignCreateSchema4 = z37.object({
25499
25496
  });
25500
25497
  }
25501
25498
  });
25502
- var campaignUpdateSchema4 = z37.object({
25499
+ var campaignUpdateSchema4 = z37.strictObject({
25503
25500
  name: z37.string().min(1).max(META_LIMITS.campaign.nameMax).optional(),
25504
25501
  status: updateStatusSchema.optional(),
25505
25502
  bid_strategy: z37.enum(BID_STRATEGIES2).optional(),
@@ -25517,7 +25514,7 @@ var campaignUpdateSchema4 = z37.object({
25517
25514
  }
25518
25515
  validateDailyBudgetFloor(p.dailyBudget, ctx, ["dailyBudget", "amount"]);
25519
25516
  });
25520
- var promotedObjectSchema = z37.object({
25517
+ var promotedObjectFields = {
25521
25518
  page_id: parentRefSchema3.optional(),
25522
25519
  pixel_id: z37.string().regex(NUMERIC_ID_REGEX3).optional(),
25523
25520
  custom_event_type: z37.enum(CUSTOM_EVENT_TYPES).optional(),
@@ -25537,9 +25534,12 @@ var promotedObjectSchema = z37.object({
25537
25534
  product_set_id: z37.string().regex(NUMERIC_ID_REGEX3).optional(),
25538
25535
  whatsapp_phone_number: z37.string().optional(),
25539
25536
  offline_conversion_data_set_id: z37.string().regex(NUMERIC_ID_REGEX3).optional()
25540
- }).partial();
25537
+ };
25538
+ var promotedObjectSchema = z37.strictObject(promotedObjectFields, {
25539
+ 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
25540
+ });
25541
25541
  var attributionSpecSchema = z37.array(
25542
- z37.object({
25542
+ z37.strictObject({
25543
25543
  event_type: z37.enum(ATTRIBUTION_EVENT_TYPES),
25544
25544
  window_days: z37.union([z37.literal(1), z37.literal(7), z37.literal(28)])
25545
25545
  })
@@ -25704,7 +25704,7 @@ function validateAdSetPlacements(p, ctx) {
25704
25704
  ctx.addIssue({ code: "custom", path: ["targeting"], message: `${message} (${PLACEMENT_TARGETING_DOC})` });
25705
25705
  }
25706
25706
  }
25707
- var adSetCreateSchema = z37.object(adSetFields).superRefine((p, ctx) => {
25707
+ var adSetCreateSchema = z37.strictObject(adSetFields).superRefine((p, ctx) => {
25708
25708
  validateAdSetBudgetAndBid(p, ctx);
25709
25709
  validateAdSetPromotedObject(p, ctx);
25710
25710
  validateAdvantageAudience(p, ctx);
@@ -25717,7 +25717,7 @@ var adSetCreateSchema = z37.object(adSetFields).superRefine((p, ctx) => {
25717
25717
  });
25718
25718
  }
25719
25719
  });
25720
- var adSetUpdateSchema = z37.object({
25720
+ var adSetUpdateSchema = z37.strictObject({
25721
25721
  name: adSetFields.name.optional(),
25722
25722
  status: updateStatusSchema.optional(),
25723
25723
  dailyBudget: moneySchema2.optional(),
@@ -25747,7 +25747,7 @@ var adSetUpdateSchema = z37.object({
25747
25747
  var messageSchema = z37.string().min(1).max(META_LIMITS.creative.messageHardMax);
25748
25748
  var headlineSchema2 = z37.string().min(1).max(META_LIMITS.creative.headlineMax);
25749
25749
  var descriptionSchema = z37.string().min(1).max(META_LIMITS.creative.descriptionMax);
25750
- var callToActionSchema = z37.object({
25750
+ var callToActionSchema = z37.strictObject({
25751
25751
  type: z37.enum(CTA_TYPES2),
25752
25752
  /** Overrides the base link for the CTA button; defaults to the ad's link. */
25753
25753
  link: httpsUrlSchema3.optional(),
@@ -25768,7 +25768,7 @@ var callToActionSchema = z37.object({
25768
25768
  });
25769
25769
  }
25770
25770
  });
25771
- var creativeEnhancementsSchema = z37.object({
25771
+ var creativeEnhancementsSchema = z37.strictObject({
25772
25772
  standardEnhancements: z37.enum(ENROLL_STATUSES).optional(),
25773
25773
  features: z37.record(z37.string(), z37.enum(ENROLL_STATUSES)).optional()
25774
25774
  });
@@ -25799,7 +25799,7 @@ function countImageRefs(p) {
25799
25799
  function countVideoRefs(p) {
25800
25800
  return [p.videoId, p.videoRef].filter(Boolean).length;
25801
25801
  }
25802
- var singleCreativeSchema = z37.object({
25802
+ var singleCreativeSchema = z37.strictObject({
25803
25803
  creativeType: z37.literal("single"),
25804
25804
  ...creativeSharedFields,
25805
25805
  /** Primary text. */
@@ -25833,7 +25833,7 @@ var singleCreativeSchema = z37.object({
25833
25833
  });
25834
25834
  }
25835
25835
  });
25836
- var carouselCardSchema = z37.object({
25836
+ var carouselCardSchema = z37.strictObject({
25837
25837
  link: httpsUrlSchema3,
25838
25838
  headline: z37.string().max(META_LIMITS.creative.headlineMax).optional(),
25839
25839
  description: z37.string().max(META_LIMITS.creative.descriptionMax).optional(),
@@ -25856,7 +25856,7 @@ var carouselCardSchema = z37.object({
25856
25856
  ctx.addIssue({ code: "custom", path: ["videoId"], message: "each card is an image OR a video, not both" });
25857
25857
  }
25858
25858
  });
25859
- var carouselCreativeSchema2 = z37.object({
25859
+ var carouselCreativeSchema2 = z37.strictObject({
25860
25860
  creativeType: z37.literal("carousel"),
25861
25861
  ...creativeSharedFields,
25862
25862
  message: messageSchema,
@@ -25878,19 +25878,19 @@ var carouselCreativeSchema2 = z37.object({
25878
25878
  });
25879
25879
  }
25880
25880
  });
25881
- var dynamicImageSchema = z37.object({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
25882
- var dynamicVideoSchema = z37.object({
25881
+ var dynamicImageSchema = z37.strictObject({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
25882
+ var dynamicVideoSchema = z37.strictObject({
25883
25883
  videoId: videoMediaFields.videoId,
25884
25884
  videoRef: videoMediaFields.videoRef,
25885
25885
  thumbnailHash: videoMediaFields.thumbnailHash
25886
25886
  }).refine((p) => countVideoRefs(p) === 1, "each dynamic video needs exactly one reference");
25887
25887
  var DYN = META_LIMITS.creative;
25888
- var dynamicCreativeSchema = z37.object({
25888
+ var dynamicCreativeSchema = z37.strictObject({
25889
25889
  creativeType: z37.literal("dynamic"),
25890
25890
  ...creativeSharedFields,
25891
- bodies: z37.array(z37.object({ text: messageSchema })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
25892
- titles: z37.array(z37.object({ text: headlineSchema2 })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
25893
- descriptions: z37.array(z37.object({ text: descriptionSchema })).max(DYN.dynamicTextsMax).optional(),
25891
+ bodies: z37.array(z37.strictObject({ text: messageSchema })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
25892
+ titles: z37.array(z37.strictObject({ text: headlineSchema2 })).min(DYN.dynamicTextsMin).max(DYN.dynamicTextsMax),
25893
+ descriptions: z37.array(z37.strictObject({ text: descriptionSchema })).max(DYN.dynamicTextsMax).optional(),
25894
25894
  images: z37.array(dynamicImageSchema).optional(),
25895
25895
  videos: z37.array(dynamicVideoSchema).optional(),
25896
25896
  /**
@@ -25906,7 +25906,7 @@ var dynamicCreativeSchema = z37.object({
25906
25906
  * different enums.
25907
25907
  */
25908
25908
  call_to_action: callToActionSchema.optional(),
25909
- link_urls: z37.array(z37.object({ website_url: httpsUrlSchema3, display_url: z37.string().optional() })).min(1),
25909
+ link_urls: z37.array(z37.strictObject({ website_url: httpsUrlSchema3, display_url: z37.string().optional() })).min(1),
25910
25910
  /**
25911
25911
  * `asset_feed_spec.optimization_type` — passed through as a free string on
25912
25912
  * purpose. Meta's own 400 enumerates ten values and then accepts
@@ -25937,7 +25937,7 @@ var dynamicCreativeSchema = z37.object({
25937
25937
  });
25938
25938
  });
25939
25939
  });
25940
- var existingPostCreativeSchema = z37.object({
25940
+ var existingPostCreativeSchema = z37.strictObject({
25941
25941
  creativeType: z37.literal("existing_post"),
25942
25942
  name: creativeSharedFields.name,
25943
25943
  /** "<page_id>_<post_id>" object story id of the post to promote. */
@@ -25946,7 +25946,7 @@ var existingPostCreativeSchema = z37.object({
25946
25946
  url_tags: creativeSharedFields.url_tags,
25947
25947
  enhancements: creativeSharedFields.enhancements
25948
25948
  });
25949
- var specCreativeSchema = z37.object({
25949
+ var specCreativeSchema = z37.strictObject({
25950
25950
  creativeType: z37.literal("spec"),
25951
25951
  name: creativeSharedFields.name,
25952
25952
  url_tags: creativeSharedFields.url_tags,
@@ -25975,29 +25975,29 @@ var creativeContentSchema2 = z37.discriminatedUnion("creativeType", [
25975
25975
  specCreativeSchema
25976
25976
  ]);
25977
25977
  var adCreativeCreateSchema = creativeContentSchema2;
25978
- var adCreativeUpdateSchema = z37.object({
25978
+ var adCreativeUpdateSchema = z37.strictObject({
25979
25979
  name: z37.string().max(META_LIMITS.creative.nameMax).optional(),
25980
- status: updateStatusSchema.optional(),
25980
+ status: z37.enum(CREATIVE_UPDATE_STATUSES).optional(),
25981
25981
  /** Content patch — only honored when the target is a staged meta_temp_* creative. */
25982
25982
  content: z37.record(z37.string(), z37.unknown()).optional()
25983
25983
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
25984
- var adCreateSchema2 = z37.object({
25984
+ var adCreateSchema2 = z37.strictObject({
25985
25985
  name: z37.string().min(1).max(META_LIMITS.ad.nameMax),
25986
25986
  adset_id: parentRefSchema3,
25987
25987
  status: stageableStatusSchema3.default("PAUSED"),
25988
- creative: z37.object({ creative_id: parentRefSchema3 }),
25988
+ creative: z37.strictObject({ creative_id: parentRefSchema3 }),
25989
25989
  /** Conversion pixel / offline event set / view tags — structural passthrough. */
25990
25990
  tracking_specs: z37.array(z37.record(z37.string(), z37.unknown())).optional()
25991
25991
  });
25992
- var adUpdateSchema2 = z37.object({
25992
+ var adUpdateSchema2 = z37.strictObject({
25993
25993
  name: z37.string().min(1).max(META_LIMITS.ad.nameMax).optional(),
25994
25994
  status: updateStatusSchema.optional(),
25995
25995
  /** Swapping the creative is the Meta way to "edit" an ad's creative. */
25996
- creative: z37.object({ creative_id: parentRefSchema3 }).optional(),
25996
+ creative: z37.strictObject({ creative_id: parentRefSchema3 }).optional(),
25997
25997
  tracking_specs: z37.array(z37.record(z37.string(), z37.unknown())).optional()
25998
25998
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
25999
- var lookalikeSpecSchema = z37.object({
26000
- origin: z37.array(z37.object({ id: parentRefSchema3 })).min(1),
25999
+ var lookalikeSpecSchema = z37.strictObject({
26000
+ origin: z37.array(z37.strictObject({ id: parentRefSchema3 })).min(1),
26001
26001
  ratio: z37.number().min(0.01).max(0.2).optional(),
26002
26002
  country: z37.string().length(2).optional()
26003
26003
  });
@@ -26015,7 +26015,7 @@ function mixedEventSourceTypes(rule) {
26015
26015
  const distinct = [...new Set(types)].sort();
26016
26016
  return distinct.length > 1 ? distinct : [];
26017
26017
  }
26018
- var customAudienceCreateSchema = z37.object({
26018
+ var customAudienceCreateSchema = z37.strictObject({
26019
26019
  name: z37.string().min(1).max(META_LIMITS.audience.nameMax),
26020
26020
  subtype: z37.enum(CUSTOM_AUDIENCE_SUBTYPES),
26021
26021
  description: z37.string().max(500).optional(),
@@ -26047,11 +26047,11 @@ var customAudienceCreateSchema = z37.object({
26047
26047
  });
26048
26048
  }
26049
26049
  });
26050
- var customAudienceUpdateSchema = z37.object({
26050
+ var customAudienceUpdateSchema = z37.strictObject({
26051
26051
  name: z37.string().min(1).max(META_LIMITS.audience.nameMax).optional(),
26052
26052
  description: z37.string().max(500).optional()
26053
26053
  }).refine((p) => Object.values(p).some((val) => val !== void 0), "update needs at least one field");
26054
- var customConversionCreateSchema = z37.object({
26054
+ var customConversionCreateSchema = z37.strictObject({
26055
26055
  name: z37.string().min(1).max(META_LIMITS.customConversion.nameMax),
26056
26056
  description: z37.string().max(META_LIMITS.customConversion.descriptionMax).optional(),
26057
26057
  /** The pixel the conversion counts from — `event_source_id` on the wire. Baker never creates pixels, so this is always a real id. */
@@ -26067,7 +26067,7 @@ var customConversionCreateSchema = z37.object({
26067
26067
  ctx.addIssue({ code: "custom", path: ["rule"], message: refusal });
26068
26068
  }
26069
26069
  });
26070
- var mediaUploadSchema = z37.object({
26070
+ var mediaUploadSchema = z37.strictObject({
26071
26071
  kind: z37.enum(MEDIA_KINDS),
26072
26072
  bakerImageId: bakerMediaIdSchema2.optional(),
26073
26073
  bakerVideoId: bakerMediaIdSchema2.optional(),
@@ -26243,13 +26243,20 @@ import { defineCommand as defineCommand57 } from "citty";
26243
26243
 
26244
26244
  // src/commands/ads/meta/write-shared.ts
26245
26245
  import { readFileSync as readFileSync9 } from "fs";
26246
- async function bareAccountId2(args5) {
26247
- return (await resolveAccountIdArg(args5)).replace(/^act_/, "");
26246
+ function bareAccountId2(args5) {
26247
+ return resolveAccountIdArg(args5).replace(/^act_/, "");
26248
26248
  }
26249
26249
  function failWriteValidation3(message) {
26250
26250
  writeJsonEnvelope({ ok: false, error: { code: "VALIDATION_ERROR", message } });
26251
26251
  process.exit(1);
26252
26252
  }
26253
+ function refuseDeleteByUpdate(payload, group) {
26254
+ if (payload.status === "DELETED") {
26255
+ failWriteValidation3(
26256
+ `update does not delete \u2014 deleting is permanent. Use \`baker ads meta ${group} delete <id>\` if the user asked to delete; otherwise pause or archive.`
26257
+ );
26258
+ }
26259
+ }
26253
26260
  function loadJsonFileArg3(path48) {
26254
26261
  if (typeof path48 !== "string" || path48.length === 0) {
26255
26262
  return {};
@@ -26370,7 +26377,7 @@ async function stageStatusChange2(input) {
26370
26377
  // src/commands/ads/meta/write-commands.ts
26371
26378
  var STAGED_NOTE2 = "Staged until publish \u2014 review with `baker ads meta draft`.";
26372
26379
  var accountArgs2 = {
26373
- "account-id": { type: "string", description: "Numeric account ID or act_N; defaults to the only connected account" }
26380
+ "account-id": { type: "string", description: "Numeric account ID or act_N" }
26374
26381
  };
26375
26382
  function campaignPayloadFromFlags2(args5) {
26376
26383
  return {
@@ -26426,7 +26433,7 @@ Example: baker ads meta campaigns create --name "Q3 Prospecting" --objective OUT
26426
26433
  file: { type: "string", description: "JSON file with the full payload; flags override file keys" }
26427
26434
  },
26428
26435
  run: async ({ args: args5 }) => {
26429
- const accountId = await bareAccountId2(args5);
26436
+ const accountId = bareAccountId2(args5);
26430
26437
  const payload = mergePayload3(loadJsonFileArg3(args5.file), campaignPayloadFromFlags2(args5));
26431
26438
  await stageOp2({ kind: "campaign.create", accountId, payload });
26432
26439
  }
@@ -26446,7 +26453,7 @@ Pass a meta_temp_* ref to amend a campaign staged in this chat. Example: baker a
26446
26453
  file: { type: "string", description: "JSON file with fields to change" }
26447
26454
  },
26448
26455
  run: async ({ args: args5 }) => {
26449
- const accountId = await bareAccountId2(args5);
26456
+ const accountId = bareAccountId2(args5);
26450
26457
  const payload = mergePayload3(loadJsonFileArg3(args5.file), {
26451
26458
  name: args5.name,
26452
26459
  status: upper(args5.status),
@@ -26457,6 +26464,7 @@ Pass a meta_temp_* ref to amend a campaign staged in this chat. Example: baker a
26457
26464
  start_time: parseDateFlag2(args5.start, "--start"),
26458
26465
  stop_time: parseDateFlag2(args5.stop, "--stop")
26459
26466
  });
26467
+ refuseDeleteByUpdate(payload, "campaigns");
26460
26468
  await stageOp2({
26461
26469
  kind: "campaign.update",
26462
26470
  accountId,
@@ -26539,7 +26547,7 @@ Example: baker ads meta custom-conversions create --name "Lead formulario" --pix
26539
26547
  value: { type: "string", description: "Default value of one conversion, when the site sends no value" }
26540
26548
  },
26541
26549
  run: async ({ args: args5 }) => {
26542
- const accountId = await bareAccountId2(args5);
26550
+ const accountId = bareAccountId2(args5);
26543
26551
  await stageOp2({
26544
26552
  kind: "customConversion.create",
26545
26553
  accountId,
@@ -26596,7 +26604,7 @@ Example: baker ads meta adsets create --campaign meta_temp_ab12 --name "US 25-54
26596
26604
  },
26597
26605
  args: { campaign: { type: "string", description: "Parent campaign id or meta_temp_* ref" }, ...adSetWriteArgs },
26598
26606
  run: async ({ args: args5 }) => {
26599
- const accountId = await bareAccountId2(args5);
26607
+ const accountId = bareAccountId2(args5);
26600
26608
  const payload = mergePayload3(loadJsonFileArg3(args5.file), adSetPayloadFromFlags(args5));
26601
26609
  await stageOp2({ kind: "adSet.create", accountId, payload });
26602
26610
  }
@@ -26610,13 +26618,14 @@ Example: baker ads meta adsets update 6123 --daily-budget 80`
26610
26618
  },
26611
26619
  args: { id: { type: "positional", description: "Ad set id or meta_temp_* ref", required: true }, ...adSetWriteArgs },
26612
26620
  run: async ({ args: args5 }) => {
26613
- const accountId = await bareAccountId2(args5);
26621
+ const accountId = bareAccountId2(args5);
26614
26622
  const {
26615
26623
  campaign_id: _drop,
26616
26624
  billing_event: _be,
26617
26625
  ...payload
26618
26626
  } = adSetPayloadFromFlags(args5);
26619
26627
  const merged = mergePayload3(loadJsonFileArg3(args5.file), payload);
26628
+ refuseDeleteByUpdate(merged, "adsets");
26620
26629
  await stageOp2({
26621
26630
  kind: "adSet.update",
26622
26631
  accountId,
@@ -26712,7 +26721,7 @@ Example: baker ads meta creatives create --page 555 --message "Save now" --link
26712
26721
  file: { type: "string", description: "JSON file with the full creative payload (carousel cards / dynamic assets)" }
26713
26722
  },
26714
26723
  run: async ({ args: args5 }) => {
26715
- const accountId = await bareAccountId2(args5);
26724
+ const accountId = bareAccountId2(args5);
26716
26725
  const payload = mergePayload3(loadJsonFileArg3(args5.file), creativePayloadFromFlags(args5));
26717
26726
  if (payload.creativeType === void 0) {
26718
26727
  payload.creativeType = "single";
@@ -26743,7 +26752,7 @@ Amending a staged (meta_temp_*) creative merges fields into the create. Example:
26743
26752
  }
26744
26753
  },
26745
26754
  run: async ({ args: args5 }) => {
26746
- const accountId = await bareAccountId2(args5);
26755
+ const accountId = bareAccountId2(args5);
26747
26756
  const file = loadJsonFileArg3(args5.file);
26748
26757
  const payload = mergePayload3(file, {
26749
26758
  name: args5.name,
@@ -26777,7 +26786,7 @@ Example: baker ads meta ads create --name "Ad 1" --adset meta_temp_as01 --creati
26777
26786
  file: { type: "string", description: "JSON file with the full payload" }
26778
26787
  },
26779
26788
  run: async ({ args: args5 }) => {
26780
- const accountId = await bareAccountId2(args5);
26789
+ const accountId = bareAccountId2(args5);
26781
26790
  const tracking = args5["tracking-file"] ? loadJsonFileArg3(args5["tracking-file"]).tracking_specs : void 0;
26782
26791
  const payload = mergePayload3(loadJsonFileArg3(args5.file), {
26783
26792
  name: args5.name,
@@ -26804,12 +26813,13 @@ Example: baker ads meta ads update 6123 --creative meta_temp_cr02`
26804
26813
  file: { type: "string", description: "JSON file with fields to change" }
26805
26814
  },
26806
26815
  run: async ({ args: args5 }) => {
26807
- const accountId = await bareAccountId2(args5);
26816
+ const accountId = bareAccountId2(args5);
26808
26817
  const payload = mergePayload3(loadJsonFileArg3(args5.file), {
26809
26818
  name: args5.name,
26810
26819
  status: upper(args5.status),
26811
26820
  creative: args5.creative ? { creative_id: String(args5.creative) } : void 0
26812
26821
  });
26822
+ refuseDeleteByUpdate(payload, "ads");
26813
26823
  await stageOp2({
26814
26824
  kind: "ad.update",
26815
26825
  accountId,
@@ -26840,9 +26850,9 @@ Example: baker ads meta ads retag 120252158038400247 --url-tags "utm_source={{si
26840
26850
  const { apiPost: apiPost2 } = await import("./client-GR6YL3YX.js");
26841
26851
  const { requireChatId: requireChatId2 } = await import("./env-4P5HOGNA.js");
26842
26852
  const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-NMQXZF3Z.js");
26843
- const { handleMetaError: handleMetaError2 } = await import("./shared-DDBXEUL4.js");
26853
+ const { handleMetaError: handleMetaError2 } = await import("./shared-J7DQZ2ED.js");
26844
26854
  try {
26845
- const accountId = await bareAccountId2(args5);
26855
+ const accountId = bareAccountId2(args5);
26846
26856
  const urlTags = typeof args5["url-tags"] === "string" ? args5["url-tags"] : void 0;
26847
26857
  const setRaw = typeof args5.set === "string" ? args5.set : void 0;
26848
26858
  if (urlTags === void 0 === (setRaw === void 0)) {
@@ -26896,7 +26906,7 @@ Example: baker ads meta audiences create --name "Site visitors 30d" --subtype WE
26896
26906
  file: { type: "string", description: "JSON file with lookalike_spec / rule / full payload" }
26897
26907
  },
26898
26908
  run: async ({ args: args5 }) => {
26899
- const accountId = await bareAccountId2(args5);
26909
+ const accountId = bareAccountId2(args5);
26900
26910
  const payload = mergePayload3(loadJsonFileArg3(args5.file), {
26901
26911
  name: args5.name,
26902
26912
  subtype: upper(args5.subtype),
@@ -26919,7 +26929,7 @@ var audiencesUpdateCommand = defineCommand57({
26919
26929
  file: { type: "string", description: "JSON file with fields to change" }
26920
26930
  },
26921
26931
  run: async ({ args: args5 }) => {
26922
- const accountId = await bareAccountId2(args5);
26932
+ const accountId = bareAccountId2(args5);
26923
26933
  const payload = mergePayload3(loadJsonFileArg3(args5.file), { name: args5.name, description: args5.description });
26924
26934
  await stageOp2({
26925
26935
  kind: "customAudience.update",
@@ -26943,7 +26953,7 @@ Example: baker ads meta media upload --kind image --image-id <bakerImageId>`
26943
26953
  name: { type: "string", description: "Display name / filename hint" }
26944
26954
  },
26945
26955
  run: async ({ args: args5 }) => {
26946
- const accountId = await bareAccountId2(args5);
26956
+ const accountId = bareAccountId2(args5);
26947
26957
  const kind = String(args5.kind ?? "").toLowerCase();
26948
26958
  if (kind !== "image" && kind !== "video") {
26949
26959
  failWriteValidation3("--kind must be image or video");
@@ -26955,13 +26965,19 @@ Example: baker ads meta media upload --kind image --image-id <bakerImageId>`
26955
26965
  });
26956
26966
  }
26957
26967
  });
26968
+ var STATUS_BY_COMMAND = { pause: "PAUSED", resume: "ACTIVE", archive: "ARCHIVED", delete: "DELETED" };
26969
+ var STATUS_COMMAND_NOTE = {
26970
+ archive: "Archived stays readable in Ads Manager and can be found with --effective-status ARCHIVED.",
26971
+ delete: "Deleting is permanent and cannot be undone \u2014 Meta removes it and everything under it. Prefer pause or archive unless the user asked to delete."
26972
+ };
26958
26973
  function statusCommand3(name, kind, label) {
26959
- const status = name === "pause" ? "PAUSED" : name === "resume" ? "ACTIVE" : "ARCHIVED";
26974
+ const status = STATUS_BY_COMMAND[name];
26975
+ const note = STATUS_COMMAND_NOTE[name];
26960
26976
  return defineCommand57({
26961
- meta: { name, description: `Stage ${name} for a ${label}. ${STAGED_NOTE2}` },
26977
+ meta: { name, description: `Stage ${name} for a ${label}. ${note ? `${note} ` : ""}${STAGED_NOTE2}` },
26962
26978
  args: { id: { type: "positional", description: `${label} id`, required: true }, ...accountArgs2 },
26963
26979
  run: async ({ args: args5 }) => {
26964
- const accountId = await bareAccountId2(args5);
26980
+ const accountId = bareAccountId2(args5);
26965
26981
  await stageStatusChange2({
26966
26982
  kind,
26967
26983
  accountId,
@@ -26988,9 +27004,9 @@ function duplicateCommand2(entity, label) {
26988
27004
  const { apiPost: apiPost2 } = await import("./client-GR6YL3YX.js");
26989
27005
  const { requireChatId: requireChatId2 } = await import("./env-4P5HOGNA.js");
26990
27006
  const { writeJsonEnvelope: writeJsonEnvelope2 } = await import("./output-NMQXZF3Z.js");
26991
- const { handleMetaError: handleMetaError2 } = await import("./shared-DDBXEUL4.js");
27007
+ const { handleMetaError: handleMetaError2 } = await import("./shared-J7DQZ2ED.js");
26992
27008
  try {
26993
- const accountId = await bareAccountId2(args5);
27009
+ const accountId = bareAccountId2(args5);
26994
27010
  const chatId = requireChatId2();
26995
27011
  const response = await apiPost2("/api/ads/meta/draft/duplicate", {
26996
27012
  chatId,
@@ -27010,19 +27026,22 @@ function duplicateCommand2(entity, label) {
27010
27026
  var campaignsPauseCommand2 = statusCommand3("pause", "campaign.update", "campaign");
27011
27027
  var campaignsResumeCommand2 = statusCommand3("resume", "campaign.update", "campaign");
27012
27028
  var campaignsArchiveCommand2 = statusCommand3("archive", "campaign.update", "campaign");
27029
+ var campaignsDeleteCommand = statusCommand3("delete", "campaign.update", "campaign");
27013
27030
  var campaignsDuplicateCommand2 = duplicateCommand2("campaign", "campaign");
27014
27031
  var adSetsPauseCommand = statusCommand3("pause", "adSet.update", "ad set");
27015
27032
  var adSetsResumeCommand = statusCommand3("resume", "adSet.update", "ad set");
27016
27033
  var adSetsArchiveCommand = statusCommand3("archive", "adSet.update", "ad set");
27034
+ var adSetsDeleteCommand = statusCommand3("delete", "adSet.update", "ad set");
27017
27035
  var adSetsDuplicateCommand = duplicateCommand2("adSet", "ad set");
27018
27036
  var adsPauseCommand = statusCommand3("pause", "ad.update", "ad");
27019
27037
  var adsResumeCommand = statusCommand3("resume", "ad.update", "ad");
27020
27038
  var adsArchiveCommand = statusCommand3("archive", "ad.update", "ad");
27039
+ var adsDeleteCommand = statusCommand3("delete", "ad.update", "ad");
27021
27040
  var adsDuplicateCommand = duplicateCommand2("ad", "ad");
27022
27041
 
27023
27042
  // src/commands/ads/meta/ads.ts
27024
27043
  var listArgs5 = {
27025
- "account-id": { type: "string", description: "Meta ad account ID (act_...); defaults to the only connected account" },
27044
+ "account-id": { type: "string", description: "Meta ad account ID" },
27026
27045
  "adset-id": { type: "string", description: "Filter to one adset" },
27027
27046
  "campaign-id": { type: "string", description: "Filter to one campaign" },
27028
27047
  "effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
@@ -27044,7 +27063,7 @@ var listCommand4 = defineCommand58({
27044
27063
  },
27045
27064
  args: listArgs5,
27046
27065
  run: async ({ args: args5 }) => {
27047
- const accountId = await resolveAccountIdArg(args5);
27066
+ const accountId = resolveAccountIdArg(args5);
27048
27067
  const effectiveStatus = resolveEffectiveStatus(args5);
27049
27068
  try {
27050
27069
  const params = { "account-id": accountId };
@@ -27065,7 +27084,7 @@ var listCommand4 = defineCommand58({
27065
27084
  var adsListCommand = defineCommand58({
27066
27085
  meta: {
27067
27086
  name: "ads",
27068
- description: `List ads in a Meta ad account, or stage writes (create/update/pause/resume/archive/duplicate/retag).
27087
+ description: `List ads in a Meta ad account, or stage writes (create/update/pause/resume/archive/delete/duplicate/retag).
27069
27088
  Defaults to ACTIVE only \u2014 pass --all-statuses to widen. Write subcommands stage ops on this chat's draft.
27070
27089
 
27071
27090
  The dashboard shows effective_status (e.g. WITH_ISSUES, PENDING_REVIEW, DISAPPROVED, ADSET_PAUSED), not status.
@@ -27090,6 +27109,7 @@ Examples:
27090
27109
  pause: adsPauseCommand,
27091
27110
  resume: adsResumeCommand,
27092
27111
  archive: adsArchiveCommand,
27112
+ delete: adsDeleteCommand,
27093
27113
  duplicate: adsDuplicateCommand,
27094
27114
  retag: adsRetagCommand
27095
27115
  },
@@ -27104,7 +27124,7 @@ Examples:
27104
27124
  // src/commands/ads/meta/adsets.ts
27105
27125
  import { defineCommand as defineCommand59 } from "citty";
27106
27126
  var listArgs6 = {
27107
- "account-id": { type: "string", description: "Meta ad account ID (act_...); defaults to the only connected account" },
27127
+ "account-id": { type: "string", description: "Meta ad account ID" },
27108
27128
  "campaign-id": { type: "string", description: "Filter to one campaign" },
27109
27129
  "effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
27110
27130
  "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
@@ -27125,7 +27145,7 @@ var listCommand5 = defineCommand59({
27125
27145
  },
27126
27146
  args: listArgs6,
27127
27147
  run: async ({ args: args5 }) => {
27128
- const accountId = await resolveAccountIdArg(args5);
27148
+ const accountId = resolveAccountIdArg(args5);
27129
27149
  const effectiveStatus = resolveEffectiveStatus(args5);
27130
27150
  try {
27131
27151
  const params = { "account-id": accountId };
@@ -27145,7 +27165,7 @@ var listCommand5 = defineCommand59({
27145
27165
  var adsetsCommand = defineCommand59({
27146
27166
  meta: {
27147
27167
  name: "adsets",
27148
- description: `List ad sets in a Meta ad account, or stage writes (create/update/pause/resume/archive/duplicate).
27168
+ description: `List ad sets in a Meta ad account, or stage writes (create/update/pause/resume/archive/delete/duplicate).
27149
27169
  Defaults to ACTIVE only. Write subcommands stage ops on this chat's draft.
27150
27170
 
27151
27171
  Listings print a table by default: id, name, campaign_id, effective_status, optimization_goal, billing_event,
@@ -27166,6 +27186,7 @@ Examples:
27166
27186
  pause: adSetsPauseCommand,
27167
27187
  resume: adSetsResumeCommand,
27168
27188
  archive: adSetsArchiveCommand,
27189
+ delete: adSetsDeleteCommand,
27169
27190
  duplicate: adSetsDuplicateCommand
27170
27191
  },
27171
27192
  // `args` stays even though the parent has no `run`: citty scans rawArgs for the
@@ -27179,7 +27200,7 @@ Examples:
27179
27200
  // src/commands/ads/meta/audiences.ts
27180
27201
  import { defineCommand as defineCommand60 } from "citty";
27181
27202
  var listArgs7 = {
27182
- "account-id": { type: "string", description: "Meta ad account ID (act_...); defaults to the only connected account" },
27203
+ "account-id": { type: "string", description: "Meta ad account ID" },
27183
27204
  limit: { type: "string", description: "Max rows" },
27184
27205
  "no-cache": NO_CACHE_ARG,
27185
27206
  output: { type: "string", description: "Output format", default: "json" }
@@ -27191,7 +27212,7 @@ var listCommand6 = defineCommand60({
27191
27212
  },
27192
27213
  args: listArgs7,
27193
27214
  run: async ({ args: args5 }) => {
27194
- const accountId = await resolveAccountIdArg(args5);
27215
+ const accountId = resolveAccountIdArg(args5);
27195
27216
  try {
27196
27217
  const params = { "account-id": accountId };
27197
27218
  if (args5.limit) params.limit = args5.limit;
@@ -27265,7 +27286,7 @@ Examples:
27265
27286
  // src/commands/ads/meta/campaigns.ts
27266
27287
  import { defineCommand as defineCommand62 } from "citty";
27267
27288
  var listArgs8 = {
27268
- "account-id": { type: "string", description: "Meta ad account ID (act_...); defaults to the only connected account" },
27289
+ "account-id": { type: "string", description: "Meta ad account ID" },
27269
27290
  "effective-status": { type: "string", description: "Comma-separated effective_status filter (overrides default)" },
27270
27291
  "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter and return everything" },
27271
27292
  "name-contains": NAME_CONTAINS_ARG,
@@ -27285,7 +27306,7 @@ var listCommand7 = defineCommand62({
27285
27306
  },
27286
27307
  args: listArgs8,
27287
27308
  run: async ({ args: args5 }) => {
27288
- const accountId = await resolveAccountIdArg(args5);
27309
+ const accountId = resolveAccountIdArg(args5);
27289
27310
  const effectiveStatus = resolveEffectiveStatus(args5);
27290
27311
  try {
27291
27312
  const params = { "account-id": accountId };
@@ -27304,7 +27325,7 @@ var listCommand7 = defineCommand62({
27304
27325
  var campaignsCommand3 = defineCommand62({
27305
27326
  meta: {
27306
27327
  name: "campaigns",
27307
- description: `List campaigns for a Meta ad account, or stage writes (create/update/pause/resume/archive/duplicate).
27328
+ description: `List campaigns for a Meta ad account, or stage writes (create/update/pause/resume/archive/delete/duplicate).
27308
27329
  Defaults to ACTIVE only \u2014 pass --all-statuses to widen. Write subcommands stage ops on this chat's draft and
27309
27330
  apply only when the chat is published.
27310
27331
 
@@ -27331,6 +27352,7 @@ Examples:
27331
27352
  pause: campaignsPauseCommand2,
27332
27353
  resume: campaignsResumeCommand2,
27333
27354
  archive: campaignsArchiveCommand2,
27355
+ delete: campaignsDeleteCommand,
27334
27356
  duplicate: campaignsDuplicateCommand2
27335
27357
  },
27336
27358
  // `args` stays even though the parent has no `run`: citty scans rawArgs for the
@@ -27344,10 +27366,7 @@ Examples:
27344
27366
  // src/commands/ads/meta/creatives.ts
27345
27367
  import { defineCommand as defineCommand63 } from "citty";
27346
27368
  var listArgs9 = {
27347
- "account-id": {
27348
- type: "string",
27349
- description: "Meta ad account ID (act_...) when listing without --creative-id; defaults to the only connected account"
27350
- },
27369
+ "account-id": { type: "string", description: "Meta ad account ID (required if no --creative-id)" },
27351
27370
  "creative-id": { type: "string", description: "Single creative ID" },
27352
27371
  limit: { type: "string", description: "Max rows (default 500)" },
27353
27372
  "no-cache": NO_CACHE_ARG,
@@ -27365,7 +27384,7 @@ var listCommand8 = defineCommand63({
27365
27384
  if (args5["creative-id"]) {
27366
27385
  params["creative-id"] = args5["creative-id"];
27367
27386
  } else {
27368
- const accountId = await resolveAccountIdArg(args5);
27387
+ const accountId = resolveAccountIdArg(args5);
27369
27388
  params["account-id"] = accountId;
27370
27389
  }
27371
27390
  if (args5.limit) params.limit = args5.limit;
@@ -27445,11 +27464,7 @@ registerSchema({
27445
27464
  command: "ads.meta.custom-conversions",
27446
27465
  description: "List the Custom Conversions defined on a Meta ad account \u2014 the measurement objects a marketer sets up in Events Manager (a pixel event narrowed by a rule, e.g. 'PageView on /thank-you'). Start here whenever the user talks about their own conversions rather than a standard event: an ad set optimizes toward one with `adsets create --custom-conversion-id <id>`.",
27447
27466
  args: {
27448
- "account-id": {
27449
- type: "string",
27450
- description: "Meta ad account ID (act_...); defaults to the only connected account",
27451
- required: false
27452
- },
27467
+ "account-id": { type: "string", description: "Meta ad account ID (act_123)", required: false },
27453
27468
  full: { type: "boolean", description: "Include the raw rule JSON, retention and creation times", required: false },
27454
27469
  limit: { type: "string", description: "Max rows", required: false },
27455
27470
  "no-cache": { type: "boolean", description: "Bypass the cache", required: false },
@@ -27457,7 +27472,7 @@ registerSchema({
27457
27472
  }
27458
27473
  });
27459
27474
  var listArgs10 = {
27460
- "account-id": { type: "string", description: "Meta ad account ID (act_...); defaults to the only connected account" },
27475
+ "account-id": { type: "string", description: "Meta ad account ID" },
27461
27476
  full: { type: "boolean", description: "Include the raw rule JSON, retention and creation times" },
27462
27477
  limit: { type: "string", description: "Max rows" },
27463
27478
  "no-cache": NO_CACHE_ARG,
@@ -27470,7 +27485,7 @@ var listCommand9 = defineCommand64({
27470
27485
  },
27471
27486
  args: listArgs10,
27472
27487
  run: async ({ args: args5 }) => {
27473
- const accountId = await resolveAccountIdArg(args5);
27488
+ const accountId = resolveAccountIdArg(args5);
27474
27489
  try {
27475
27490
  const params = { "account-id": accountId };
27476
27491
  if (args5.limit) params.limit = args5.limit;
@@ -28347,10 +28362,7 @@ Examples:
28347
28362
  baker ads meta pixels --account-id act_123 --pixel-id 9876 --stats --days 7`
28348
28363
  },
28349
28364
  args: {
28350
- "account-id": {
28351
- type: "string",
28352
- description: "Meta ad account ID (act_...); defaults to the only connected account"
28353
- },
28365
+ "account-id": { type: "string", description: "Meta ad account ID" },
28354
28366
  "pixel-id": { type: "string", description: "Pixel ID for --stats" },
28355
28367
  stats: { type: "boolean", description: "Fetch firing stats for the pixel" },
28356
28368
  aggregation: {
@@ -28394,7 +28406,7 @@ async function runStats(args5) {
28394
28406
  emit(data, args5);
28395
28407
  }
28396
28408
  async function runList(args5) {
28397
- const accountId = await resolveAccountIdArg(args5);
28409
+ const accountId = resolveAccountIdArg(args5);
28398
28410
  const params = { "account-id": accountId };
28399
28411
  if (args5["no-cache"]) params["skip-cache"] = "true";
28400
28412
  const { pixels, restrictedFields } = await apiGet("/api/ads/meta/pixels", params);