@koda-sl/baker-cli 0.248.0 → 0.249.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
@@ -19688,7 +19688,15 @@ var descriptionSchema = z25.string().min(1).max(META_LIMITS.creative.description
19688
19688
  var callToActionSchema = z25.object({
19689
19689
  type: z25.enum(CTA_TYPES2),
19690
19690
  /** Overrides the base link for the CTA button; defaults to the ad's link. */
19691
- link: httpsUrlSchema3.optional()
19691
+ link: httpsUrlSchema3.optional(),
19692
+ /**
19693
+ * The instant form the button opens — Meta's `call_to_action.value.lead_gen_form_id`.
19694
+ * This is the ONLY place an instant form is named: the ad set says leads open
19695
+ * on the ad (`destination_type: ON_AD`), and the creative says which form.
19696
+ * Without it Meta refuses every ad in that ad set with subcode 3390001,
19697
+ * "Choose or create an instant form for your leads campaign".
19698
+ */
19699
+ lead_gen_form_id: z25.string().regex(NUMERIC_ID_REGEX3).optional()
19692
19700
  });
19693
19701
  var creativeEnhancementsSchema = z25.object({
19694
19702
  standardEnhancements: z25.enum(ENROLL_STATUSES).optional(),
@@ -19786,6 +19794,19 @@ var carouselCreativeSchema2 = z25.object({
19786
19794
  link: httpsUrlSchema3.optional(),
19787
19795
  call_to_action: callToActionSchema.optional(),
19788
19796
  cards: z25.array(carouselCardSchema).min(META_LIMITS.creative.carouselCardsMin).max(META_LIMITS.creative.carouselCardsMax)
19797
+ }).superRefine((p, ctx) => {
19798
+ const forms = new Set(
19799
+ [p.call_to_action?.lead_gen_form_id, ...p.cards.map((card) => card.call_to_action?.lead_gen_form_id)].filter(
19800
+ Boolean
19801
+ )
19802
+ );
19803
+ if (forms.size > 1) {
19804
+ ctx.addIssue({
19805
+ code: "custom",
19806
+ path: ["cards"],
19807
+ message: `every card of a carousel must open the SAME instant form \u2014 this one names ${[...forms].join(" and ")}`
19808
+ });
19809
+ }
19789
19810
  });
19790
19811
  var dynamicImageSchema = z25.object({ ...imageMediaFields }).refine((p) => countImageRefs(p) === 1, "each dynamic image needs exactly one reference");
19791
19812
  var dynamicVideoSchema = z25.object({
@@ -20362,7 +20383,7 @@ function creativePayloadFromFlags(args) {
20362
20383
  headline: args.headline,
20363
20384
  description: args.description,
20364
20385
  caption: args.caption,
20365
- call_to_action: args.cta ? { type: upper(args.cta) } : void 0,
20386
+ call_to_action: creativeCta(args),
20366
20387
  imageHash: args["image-hash"],
20367
20388
  imageRef: args["image-ref"],
20368
20389
  videoId: args["video-id"],
@@ -20372,6 +20393,26 @@ function creativePayloadFromFlags(args) {
20372
20393
  enhancements
20373
20394
  };
20374
20395
  }
20396
+ function ctaPatchFromFlags(args) {
20397
+ const patch = {
20398
+ ...args.cta ? { type: String(upper(args.cta)) } : {},
20399
+ ...args["lead-form"] === void 0 ? {} : { lead_gen_form_id: String(args["lead-form"]) }
20400
+ };
20401
+ return Object.keys(patch).length > 0 ? patch : void 0;
20402
+ }
20403
+ function creativeCta(args) {
20404
+ const patch = ctaPatchFromFlags(args);
20405
+ return patch ? { type: "SIGN_UP", ...patch } : void 0;
20406
+ }
20407
+ function creativeContentPatch2(file, args) {
20408
+ const cta = ctaPatchFromFlags(args);
20409
+ if (!cta) {
20410
+ return void 0;
20411
+ }
20412
+ const fileContent = file.content ?? {};
20413
+ const fileCta = fileContent.call_to_action ?? {};
20414
+ return { ...fileContent, call_to_action: { ...fileCta, ...cta } };
20415
+ }
20375
20416
  function parseEnroll(value) {
20376
20417
  const raw = String(value).toLowerCase();
20377
20418
  if (raw === "on" || raw === "true" || raw === "opt_in") return "OPT_IN";
@@ -20398,6 +20439,10 @@ Example: baker ads meta creatives create --page 555 --message "Save now" --link
20398
20439
  description: { type: "string", description: "Description" },
20399
20440
  caption: { type: "string", description: "Display URL / caption" },
20400
20441
  cta: { type: "string", description: "Call-to-action type (SHOP_NOW|LEARN_MORE|SIGN_UP|\u2026)" },
20442
+ "lead-form": {
20443
+ type: "string",
20444
+ description: "Instant form id the button opens \u2014 REQUIRED for an ad set that collects leads on the ad. List them with `baker ads meta lead-forms`"
20445
+ },
20401
20446
  "image-hash": { type: "string", description: "Meta ad-image hash (already uploaded)" },
20402
20447
  "image-ref": { type: "string", description: "meta_temp_* ref of a staged media upload" },
20403
20448
  "video-id": { type: "string", description: "Meta video id (already uploaded)" },
@@ -20431,6 +20476,11 @@ Amending a staged (meta_temp_*) creative merges fields into the create. Example:
20431
20476
  ...accountArgs2,
20432
20477
  name: { type: "string", description: "New name" },
20433
20478
  status: { type: "string", description: "ACTIVE|PAUSED|ARCHIVED" },
20479
+ cta: { type: "string", description: "Call-to-action type (staged creatives only)" },
20480
+ "lead-form": {
20481
+ type: "string",
20482
+ description: "Instant form id the button opens (staged creatives only) \u2014 `baker ads meta lead-forms` lists them"
20483
+ },
20434
20484
  file: {
20435
20485
  type: "string",
20436
20486
  description: "JSON file with fields to change (content only merges into a staged creative)"
@@ -20438,7 +20488,15 @@ Amending a staged (meta_temp_*) creative merges fields into the create. Example:
20438
20488
  },
20439
20489
  run: async ({ args }) => {
20440
20490
  const accountId = bareAccountId2(args);
20441
- const payload = mergePayload3(loadJsonFileArg3(args.file), { name: args.name, status: upper(args.status) });
20491
+ const file = loadJsonFileArg3(args.file);
20492
+ const payload = mergePayload3(file, {
20493
+ name: args.name,
20494
+ status: upper(args.status),
20495
+ // A creative's content is immutable on Meta, so this only ever lands on a
20496
+ // creative still staged in this chat — which is exactly the fix path when
20497
+ // staging an ad refuses it for naming no instant form.
20498
+ content: creativeContentPatch2(file, args)
20499
+ });
20442
20500
  await stageOp2({
20443
20501
  kind: "adCreative.update",
20444
20502
  accountId,