@koda-sl/baker-cli 0.108.0-dev.d66dc8b3d → 0.109.0-dev.2acd65459

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1006,9 +1006,13 @@ baker ads linkedin conversions create --name "Demo booked" --type LEAD --method
1006
1006
  # Safe duplication — stage-time read of the source → staged DRAFT create ("Duplicate ad", never "Link to original")
1007
1007
  baker ads linkedin campaigns duplicate 123456 --name "New variant"
1008
1008
 
1009
- # Change copy/media/URL on a LIVE ad — LinkedIn makes ad content immutable, so this is ONE command:
1010
- # duplicate with overrides (unchanged fields carry over) + --replace pauses the original once the copy publishes
1011
- baker ads linkedin creatives duplicate 1458413484 --headline "New headline" --description "New copy." --replace
1009
+ # Change copy/media/URL on a LIVE ad — direct-content ads (text/spotlight/follower/jobs) update IN PLACE;
1010
+ # pass only the changed fields, the rest of the ad's current content carries over
1011
+ baker ads linkedin creatives update 1458423674 --headline "New headline" --description "New copy."
1012
+
1013
+ # Post-based ads (image/video/carousel/…) sponsor a post whose content can't be edited — replace in ONE command:
1014
+ # duplicate with overrides (unchanged fields + status carry over) + --replace pauses the original once the copy publishes
1015
+ baker ads linkedin creatives duplicate 1458413484 --headline "New headline" --replace
1012
1016
 
1013
1017
  # Amend staged ops in place — `update <li_temp_ref>` merges into the staged create and re-validates
1014
1018
  baker ads linkedin creatives update li_temp_x3 --headline "Sharper headline" --image-id <bakerImageId>
package/dist/cli.js CHANGED
@@ -1226,14 +1226,17 @@ var spotlightCreativeSchema = z3.object({
1226
1226
  ctaLabel: z3.string().min(1).max(LINKEDIN_LIMITS.creative.spotlightCtaMax),
1227
1227
  logoImageId: bakerMediaIdSchema.optional(),
1228
1228
  logoUrn: z3.string().regex(IMAGE_URN_REGEX).optional(),
1229
- showMemberProfilePhoto: z3.boolean().default(true)
1229
+ showMemberProfilePhoto: z3.boolean().default(true),
1230
+ /** Carried from the live snapshot on updates so LinkedIn's whole-content $set preserves it. */
1231
+ organizationName: z3.string().min(1).max(200).optional()
1230
1232
  });
1231
1233
  var followerCreativeSchema = z3.object({
1232
1234
  format: z3.literal("follower"),
1233
1235
  headline: z3.string().max(LINKEDIN_LIMITS.creative.spotlightHeadlineMax).optional(),
1234
1236
  description: z3.string().max(LINKEDIN_LIMITS.creative.spotlightDescriptionMax).optional(),
1235
1237
  logoImageId: bakerMediaIdSchema.optional(),
1236
- logoUrn: z3.string().regex(IMAGE_URN_REGEX).optional()
1238
+ logoUrn: z3.string().regex(IMAGE_URN_REGEX).optional(),
1239
+ organizationName: z3.string().min(1).max(200).optional()
1237
1240
  });
1238
1241
  var documentCreativeSchema = z3.object({
1239
1242
  format: z3.literal("document"),
@@ -5565,7 +5568,7 @@ registerSchema({
5565
5568
  });
5566
5569
  registerSchema({
5567
5570
  command: "ads.linkedin.creatives.duplicate",
5568
- description: "Stage a copy of an existing ad, optionally with new content \u2014 the ONLY way to change copy/media/URL on a live ad (LinkedIn makes ad content immutable after creation). Direct-content ads (text/spotlight/follower/jobs) copy field-by-field; post-based ads re-sponsor the same post. --replace also stages pausing the original, gated on the new ad publishing successfully.",
5571
+ description: "Stage a copy of an existing ad, optionally with new content. Direct-content ads (text/spotlight/follower/jobs) copy field-by-field; post-based ads re-sponsor the same post \u2014 and since post content can't be edited, duplicate --replace is how post-based ads change copy (direct-content ads update in place via creatives.update instead). --replace stages pausing the original, gated on the new ad publishing successfully, and the copy inherits the source's status.",
5569
5572
  args: {
5570
5573
  id: { type: "positional", description: "Source creative id or URN", required: true },
5571
5574
  ...writeAccountArgs,
@@ -5617,27 +5620,27 @@ registerSchema({
5617
5620
  });
5618
5621
  registerSchema({
5619
5622
  command: "ads.linkedin.creatives.update",
5620
- description: "Stage changes to an existing creative (intendedStatus, name only \u2014 LinkedIn makes ad content immutable; to change copy/media/URL use creatives.duplicate with --replace), or AMEND a creative staged in this chat by passing its li_temp_* ref \u2014 amends accept the content flags from creatives.create (headline, intro, description, image-id, landing-url, cta, \u2026) and merge into the staged ad, re-validating the result. Use amends to apply feedback to staged ads instead of remove + re-create. Applies on chat publish.",
5623
+ description: "Stage changes to an existing creative. Direct-content ads (text/spotlight/follower/jobs) update copy/media/URL IN PLACE \u2014 pass only the changed fields (headline, description, landing-url, image-id, \u2026); the ad's current content carries over. Post-based ads (image/video/carousel/\u2026) can't edit content \u2014 use creatives.duplicate with --replace for those. Passing a li_temp_* ref AMENDS the creative staged in this chat instead. Applies on chat publish.",
5621
5624
  args: {
5622
5625
  id: { type: "positional", description: "Creative id/URN, or li_temp_* ref staged in this chat", required: true },
5623
5626
  ...writeAccountArgs,
5624
5627
  "intended-status": { type: "string", description: "ACTIVE|PAUSED|ARCHIVED|DRAFT", required: false },
5625
5628
  name: { type: "string", description: "New creative name", required: false },
5626
- headline: { type: "string", description: "Amend only: new headline", required: false },
5627
- intro: { type: "string", description: "Amend only: commentary / intro text", required: false },
5628
- description: { type: "string", description: "Amend only: description (text/spotlight)", required: false },
5629
+ headline: { type: "string", description: "New headline", required: false },
5630
+ intro: { type: "string", description: "Commentary / intro text", required: false },
5631
+ description: { type: "string", description: "Description (text/spotlight)", required: false },
5629
5632
  "landing-url": { type: "string", description: "New https destination URL", required: false },
5630
5633
  cta: { type: "string", description: "New CTA", required: false },
5631
- "image-id": { type: "string", description: "Amend only: Baker image library id", required: false },
5632
- "image-urn": { type: "string", description: "Amend only: existing urn:li:image:*", required: false },
5633
- "video-id": { type: "string", description: "Amend only: Baker video library id", required: false },
5634
- "logo-image-id": { type: "string", description: "Amend only: Baker image id for the logo", required: false },
5634
+ "image-id": { type: "string", description: "Baker image library id", required: false },
5635
+ "image-urn": { type: "string", description: "Existing urn:li:image:*", required: false },
5636
+ "video-id": { type: "string", description: "Baker video library id", required: false },
5637
+ "logo-image-id": { type: "string", description: "Baker image id for the logo", required: false },
5635
5638
  "thumbnail-image-id": {
5636
5639
  type: "string",
5637
- description: "Amend only: Baker image id for the article thumbnail",
5640
+ description: "Baker image id for the article thumbnail",
5638
5641
  required: false
5639
5642
  },
5640
- title: { type: "string", description: "Amend only: media or article title", required: false },
5643
+ title: { type: "string", description: "Media or article title", required: false },
5641
5644
  file: { type: "string", description: "JSON file with fields to change; flags override file keys", required: false }
5642
5645
  }
5643
5646
  });
@@ -7041,8 +7044,14 @@ Examples:
7041
7044
  id: { type: "positional", description: "Source creative id or URN", required: true },
7042
7045
  ...accountArgs,
7043
7046
  campaign: { type: "string", description: "Stage the copy under a different ad set (id/URN or li_temp_*)" },
7044
- "intended-status": { type: "string", description: "Status for the copy (default DRAFT)" },
7045
- replace: { type: "boolean", description: "Also pause the original once the new ad publishes" },
7047
+ "intended-status": {
7048
+ type: "string",
7049
+ description: "Status for the copy (default DRAFT; with --replace, the source's status)"
7050
+ },
7051
+ replace: {
7052
+ type: "boolean",
7053
+ description: "Also pause the original once the new ad publishes; the copy inherits the source's status"
7054
+ },
7046
7055
  intro: { type: "string", description: "New commentary / intro text" },
7047
7056
  headline: { type: "string", description: "New headline" },
7048
7057
  description: { type: "string", description: "New description (text/spotlight ads)" },
@@ -7188,7 +7197,6 @@ var CREATIVE_AMEND_CONTENT_FLAGS = [
7188
7197
  ["thumbnail-urn", "thumbnailUrn"],
7189
7198
  ["title", "title"]
7190
7199
  ];
7191
- var CREATIVE_LIVE_BLOCKED_FILE_KEYS = ["headline", "landingUrl", "cta", "content"];
7192
7200
  function creativeContentPatch(args) {
7193
7201
  const patch = {};
7194
7202
  for (const [flag, key] of CREATIVE_AMEND_CONTENT_FLAGS) {
@@ -7205,30 +7213,30 @@ var creativesUpdateCommand = defineCommand36({
7205
7213
  meta: {
7206
7214
  name: "update",
7207
7215
  description: `Stage changes to an existing creative, or amend a creative staged in this chat by passing its li_temp_* ref. ${STAGED_NOTE}
7208
- Staged creatives (li_temp_*) accept the content flags from \`creatives create\` \u2014 fields merge into the staged ad and re-validate. Creatives already on LinkedIn only accept --intended-status/--name (LinkedIn makes ad content immutable \u2014 to change copy/media/URL use \`creatives duplicate <id> --headline "\u2026" --replace\`).
7216
+ Direct-content ads (text/spotlight/follower/jobs) update copy/media/URL IN PLACE \u2014 changed fields merge into the ad's current content. Post-based ads (image/video/carousel/\u2026) can't edit content; use \`creatives duplicate <id> --headline "\u2026" --replace\` for those. Staged creatives (li_temp_*) accept all content flags and re-validate.
7209
7217
  Examples:
7210
- baker ads linkedin creatives update urn:li:sponsoredCreative:789 --intended-status PAUSED
7211
- baker ads linkedin creatives update li_temp_a1b2 --headline "Sharper headline" --image-id <bakerImageId>`
7218
+ baker ads linkedin creatives update 1458423674 --headline "Sharper headline" --description "New copy."
7219
+ baker ads linkedin creatives update urn:li:sponsoredCreative:789 --intended-status PAUSED`
7212
7220
  },
7213
7221
  args: {
7214
7222
  id: { type: "positional", description: "Creative id/URN, or li_temp_* ref staged in this chat", required: true },
7215
7223
  ...accountArgs,
7216
7224
  "intended-status": { type: "string", description: "ACTIVE|PAUSED|ARCHIVED|DRAFT" },
7217
7225
  name: { type: "string", description: "New creative name" },
7218
- intro: { type: "string", description: "Amend only: commentary / intro text" },
7226
+ intro: { type: "string", description: "Commentary / intro text" },
7219
7227
  headline: { type: "string", description: "New headline" },
7220
- description: { type: "string", description: "Amend only: description (text/spotlight ads)" },
7228
+ description: { type: "string", description: "Description (text/spotlight ads)" },
7221
7229
  "landing-url": { type: "string", description: "New https destination URL" },
7222
7230
  cta: { type: "string", description: "New CTA (LEARN_MORE|REQUEST_DEMO|\u2026)" },
7223
- "cta-label": { type: "string", description: "Amend only: spotlight custom CTA label" },
7224
- "image-id": { type: "string", description: "Amend only: Baker image library id" },
7225
- "image-urn": { type: "string", description: "Amend only: existing urn:li:image:*" },
7226
- "video-id": { type: "string", description: "Amend only: Baker video library id" },
7227
- "video-urn": { type: "string", description: "Amend only: existing urn:li:video:*" },
7228
- "logo-image-id": { type: "string", description: "Amend only: Baker image id for the logo" },
7229
- "thumbnail-image-id": { type: "string", description: "Amend only: Baker image id for the article thumbnail" },
7230
- "thumbnail-urn": { type: "string", description: "Amend only: existing urn:li:image:* thumbnail" },
7231
- title: { type: "string", description: "Amend only: media or article title" },
7231
+ "cta-label": { type: "string", description: "Spotlight custom CTA label" },
7232
+ "image-id": { type: "string", description: "Baker image library id" },
7233
+ "image-urn": { type: "string", description: "Existing urn:li:image:*" },
7234
+ "video-id": { type: "string", description: "Baker video library id" },
7235
+ "video-urn": { type: "string", description: "Existing urn:li:video:*" },
7236
+ "logo-image-id": { type: "string", description: "Baker image id for the logo" },
7237
+ "thumbnail-image-id": { type: "string", description: "Baker image id for the article thumbnail" },
7238
+ "thumbnail-urn": { type: "string", description: "Existing urn:li:image:* thumbnail" },
7239
+ title: { type: "string", description: "Media or article title" },
7232
7240
  file: { type: "string", description: "JSON file with fields to change; flags override file keys" }
7233
7241
  },
7234
7242
  run: async ({ args }) => {
@@ -7237,26 +7245,13 @@ Examples:
7237
7245
  const file = loadJsonFileArg(args.file);
7238
7246
  const contentPatch = creativeContentPatch(args);
7239
7247
  const intendedStatus = args["intended-status"] ? String(args["intended-status"]).toUpperCase() : void 0;
7240
- if (target.startsWith("li_temp_")) {
7241
- const fileContent = file.content !== null && typeof file.content === "object" && !Array.isArray(file.content) ? file.content : {};
7242
- const content = { ...fileContent, ...contentPatch };
7243
- const payload2 = mergePayload(file, {
7244
- intendedStatus,
7245
- content: Object.keys(content).length > 0 ? content : void 0
7246
- });
7247
- await stageOp({ kind: "creative.update", accountId, target, payload: payload2 });
7248
- return;
7249
- }
7250
- const blocked = [
7251
- ...Object.keys(contentPatch),
7252
- ...CREATIVE_LIVE_BLOCKED_FILE_KEYS.filter((key) => file[key] !== void 0)
7253
- ];
7254
- if (blocked.length > 0) {
7255
- failWriteValidation(
7256
- `LinkedIn can't change ad content once created (${[...new Set(blocked)].join(", ")}) \u2014 stage a replacement instead: \`baker ads linkedin creatives duplicate ${target} --headline "\u2026" --replace\` copies this ad with your changes and pauses the original when published. (li_temp_* refs staged in this chat stay fully editable.)`
7257
- );
7258
- }
7259
- const payload = mergePayload(file, { intendedStatus, name: args.name });
7248
+ const fileContent = file.content !== null && typeof file.content === "object" && !Array.isArray(file.content) ? file.content : {};
7249
+ const content = { ...fileContent, ...contentPatch };
7250
+ const payload = mergePayload(file, {
7251
+ intendedStatus,
7252
+ name: args.name,
7253
+ content: Object.keys(content).length > 0 ? content : void 0
7254
+ });
7260
7255
  await stageOp({ kind: "creative.update", accountId, target, payload });
7261
7256
  }
7262
7257
  });