@koda-sl/baker-cli 0.26.0 → 0.27.1-dev.bcbc31f8

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 (104) hide show
  1. package/README.md +146 -0
  2. package/dist/cli.js +1 -1
  3. package/dist/commands/actions/create.d.ts.map +1 -1
  4. package/dist/commands/actions/create.js +10 -2
  5. package/dist/commands/actions/create.js.map +1 -1
  6. package/dist/commands/ads/index.d.ts.map +1 -1
  7. package/dist/commands/ads/index.js +7 -3
  8. package/dist/commands/ads/index.js.map +1 -1
  9. package/dist/commands/ads/linkedin/account.d.ts +20 -0
  10. package/dist/commands/ads/linkedin/account.d.ts.map +1 -0
  11. package/dist/commands/ads/linkedin/account.js +39 -0
  12. package/dist/commands/ads/linkedin/account.js.map +1 -0
  13. package/dist/commands/ads/linkedin/accounts.d.ts +20 -0
  14. package/dist/commands/ads/linkedin/accounts.d.ts.map +1 -0
  15. package/dist/commands/ads/linkedin/accounts.js +56 -0
  16. package/dist/commands/ads/linkedin/accounts.js.map +1 -0
  17. package/dist/commands/ads/linkedin/analytics.d.ts +84 -0
  18. package/dist/commands/ads/linkedin/analytics.d.ts.map +1 -0
  19. package/dist/commands/ads/linkedin/analytics.js +249 -0
  20. package/dist/commands/ads/linkedin/analytics.js.map +1 -0
  21. package/dist/commands/ads/linkedin/audience-size.d.ts +28 -0
  22. package/dist/commands/ads/linkedin/audience-size.d.ts.map +1 -0
  23. package/dist/commands/ads/linkedin/audience-size.js +75 -0
  24. package/dist/commands/ads/linkedin/audience-size.js.map +1 -0
  25. package/dist/commands/ads/linkedin/audit.d.ts +35 -0
  26. package/dist/commands/ads/linkedin/audit.d.ts.map +1 -0
  27. package/dist/commands/ads/linkedin/audit.js +136 -0
  28. package/dist/commands/ads/linkedin/audit.js.map +1 -0
  29. package/dist/commands/ads/linkedin/bid-pricing.d.ts +38 -0
  30. package/dist/commands/ads/linkedin/bid-pricing.d.ts.map +1 -0
  31. package/dist/commands/ads/linkedin/bid-pricing.js +76 -0
  32. package/dist/commands/ads/linkedin/bid-pricing.js.map +1 -0
  33. package/dist/commands/ads/linkedin/campaign-groups.d.ts +32 -0
  34. package/dist/commands/ads/linkedin/campaign-groups.d.ts.map +1 -0
  35. package/dist/commands/ads/linkedin/campaign-groups.js +50 -0
  36. package/dist/commands/ads/linkedin/campaign-groups.js.map +1 -0
  37. package/dist/commands/ads/linkedin/campaigns.d.ts +36 -0
  38. package/dist/commands/ads/linkedin/campaigns.d.ts.map +1 -0
  39. package/dist/commands/ads/linkedin/campaigns.js +57 -0
  40. package/dist/commands/ads/linkedin/campaigns.js.map +1 -0
  41. package/dist/commands/ads/linkedin/conversation.d.ts +36 -0
  42. package/dist/commands/ads/linkedin/conversation.d.ts.map +1 -0
  43. package/dist/commands/ads/linkedin/conversation.js +77 -0
  44. package/dist/commands/ads/linkedin/conversation.js.map +1 -0
  45. package/dist/commands/ads/linkedin/conversions.d.ts +2 -0
  46. package/dist/commands/ads/linkedin/conversions.d.ts.map +1 -0
  47. package/dist/commands/ads/linkedin/conversions.js +102 -0
  48. package/dist/commands/ads/linkedin/conversions.js.map +1 -0
  49. package/dist/commands/ads/linkedin/creatives.d.ts +36 -0
  50. package/dist/commands/ads/linkedin/creatives.d.ts.map +1 -0
  51. package/dist/commands/ads/linkedin/creatives.js +57 -0
  52. package/dist/commands/ads/linkedin/creatives.js.map +1 -0
  53. package/dist/commands/ads/linkedin/demographics.d.ts +40 -0
  54. package/dist/commands/ads/linkedin/demographics.d.ts.map +1 -0
  55. package/dist/commands/ads/linkedin/demographics.js +117 -0
  56. package/dist/commands/ads/linkedin/demographics.js.map +1 -0
  57. package/dist/commands/ads/linkedin/facets.d.ts +2 -0
  58. package/dist/commands/ads/linkedin/facets.d.ts.map +1 -0
  59. package/dist/commands/ads/linkedin/facets.js +95 -0
  60. package/dist/commands/ads/linkedin/facets.js.map +1 -0
  61. package/dist/commands/ads/linkedin/forecast.d.ts +50 -0
  62. package/dist/commands/ads/linkedin/forecast.d.ts.map +1 -0
  63. package/dist/commands/ads/linkedin/forecast.js +83 -0
  64. package/dist/commands/ads/linkedin/forecast.js.map +1 -0
  65. package/dist/commands/ads/linkedin/index.d.ts +19 -0
  66. package/dist/commands/ads/linkedin/index.d.ts.map +1 -0
  67. package/dist/commands/ads/linkedin/index.js +83 -0
  68. package/dist/commands/ads/linkedin/index.js.map +1 -0
  69. package/dist/commands/ads/linkedin/leads.d.ts +40 -0
  70. package/dist/commands/ads/linkedin/leads.d.ts.map +1 -0
  71. package/dist/commands/ads/linkedin/leads.js +75 -0
  72. package/dist/commands/ads/linkedin/leads.js.map +1 -0
  73. package/dist/commands/ads/linkedin/presets.d.ts +40 -0
  74. package/dist/commands/ads/linkedin/presets.d.ts.map +1 -0
  75. package/dist/commands/ads/linkedin/presets.js +193 -0
  76. package/dist/commands/ads/linkedin/presets.js.map +1 -0
  77. package/dist/commands/ads/linkedin/presets.test.d.ts +2 -0
  78. package/dist/commands/ads/linkedin/presets.test.d.ts.map +1 -0
  79. package/dist/commands/ads/linkedin/presets.test.js +98 -0
  80. package/dist/commands/ads/linkedin/presets.test.js.map +1 -0
  81. package/dist/commands/ads/linkedin/schemas.d.ts +2 -0
  82. package/dist/commands/ads/linkedin/schemas.d.ts.map +1 -0
  83. package/dist/commands/ads/linkedin/schemas.js +300 -0
  84. package/dist/commands/ads/linkedin/schemas.js.map +1 -0
  85. package/dist/commands/ads/linkedin/shared.d.ts +17 -0
  86. package/dist/commands/ads/linkedin/shared.d.ts.map +1 -0
  87. package/dist/commands/ads/linkedin/shared.js +116 -0
  88. package/dist/commands/ads/linkedin/shared.js.map +1 -0
  89. package/dist/commands/ads/linkedin/top-companies.d.ts +44 -0
  90. package/dist/commands/ads/linkedin/top-companies.d.ts.map +1 -0
  91. package/dist/commands/ads/linkedin/top-companies.js +86 -0
  92. package/dist/commands/ads/linkedin/top-companies.js.map +1 -0
  93. package/dist/env.d.ts +1 -0
  94. package/dist/env.d.ts.map +1 -1
  95. package/dist/env.js +4 -0
  96. package/dist/env.js.map +1 -1
  97. package/dist/error-handler.d.ts +1 -1
  98. package/dist/error-handler.d.ts.map +1 -1
  99. package/dist/error-handler.js +3 -0
  100. package/dist/error-handler.js.map +1 -1
  101. package/dist/output.d.ts +1 -0
  102. package/dist/output.d.ts.map +1 -1
  103. package/dist/output.js.map +1 -1
  104. package/package.json +1 -1
@@ -0,0 +1,76 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { defineCommand } from "citty";
3
+ import { apiPost } from "../../../client.js";
4
+ import { writeAdsJson } from "../output.js";
5
+ import { handleLinkedinError, resolveAccountIdArg } from "./shared.js";
6
+ function loadTargeting(args) {
7
+ const inline = args.targeting;
8
+ if (inline) {
9
+ try {
10
+ return JSON.parse(inline);
11
+ }
12
+ catch {
13
+ handleLinkedinError(new Error("--targeting must be valid JSON. See LinkedIn 'targetingCriteria' shape."));
14
+ }
15
+ }
16
+ const file = args["targeting-file"];
17
+ if (file) {
18
+ try {
19
+ return JSON.parse(readFileSync(file, "utf-8"));
20
+ }
21
+ catch (e) {
22
+ handleLinkedinError(new Error(`Failed to read --targeting-file: ${e instanceof Error ? e.message : "I/O error"}`));
23
+ }
24
+ }
25
+ handleLinkedinError(new Error("Pass --targeting-file <path> or --targeting '{...JSON...}'"));
26
+ }
27
+ export const bidPricingCommand = defineCommand({
28
+ meta: {
29
+ name: "bid-pricing",
30
+ description: `Get LinkedIn's suggested bid range for a targeting + objective + cost type.
31
+
32
+ Returns LinkedIn's min / suggested / max bid plus the playbook §06 floor
33
+ (2/3 of suggested — the recommended manual CPC starting point).
34
+
35
+ Objective types: BRAND_AWARENESS | WEBSITE_TRAFFIC | WEBSITE_VISIT |
36
+ ENGAGEMENT | WEBSITE_CONVERSION | LEAD_GENERATION |
37
+ JOB_APPLICANT | VIDEO_VIEW
38
+ Cost types: CPC | CPM | CPV | CPS
39
+
40
+ Examples:
41
+ baker ads linkedin bid-pricing --account-id 503001492 --objective WEBSITE_CONVERSION --cost-type CPC --targeting-file targeting.json
42
+ baker ads linkedin bid-pricing --account-id 503001492 --objective LEAD_GENERATION --cost-type CPM --targeting '{"include":...}'`,
43
+ },
44
+ args: {
45
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
46
+ "account-urn": { type: "string", description: "Alias for --account-id" },
47
+ objective: {
48
+ type: "string",
49
+ description: "Objective type (e.g. WEBSITE_CONVERSION, LEAD_GENERATION)",
50
+ required: true,
51
+ },
52
+ "cost-type": { type: "string", description: "CPC | CPM | CPV | CPS", required: true },
53
+ targeting: { type: "string", description: "Inline JSON targetingCriteria" },
54
+ "targeting-file": { type: "string", description: "Path to JSON file with targetingCriteria" },
55
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
56
+ output: { type: "string", description: "json", default: "json" },
57
+ },
58
+ run: async ({ args }) => {
59
+ const accountId = resolveAccountIdArg(args);
60
+ const targetingCriteria = loadTargeting(args);
61
+ try {
62
+ const data = await apiPost("/api/ads/linkedin/bid-pricing", {
63
+ accountId,
64
+ objectiveType: String(args.objective),
65
+ costType: String(args["cost-type"]).toUpperCase(),
66
+ targetingCriteria,
67
+ skipCache: Boolean(args["skip-cache"]),
68
+ });
69
+ writeAdsJson({ ok: true, data });
70
+ }
71
+ catch (err) {
72
+ handleLinkedinError(err);
73
+ }
74
+ },
75
+ });
76
+ //# sourceMappingURL=bid-pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bid-pricing.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/bid-pricing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export declare const campaignGroupsCommand: import("citty").CommandDef<{
2
+ readonly "account-id": {
3
+ readonly type: "string";
4
+ readonly description: "Numeric account ID or urn:li:sponsoredAccount:N";
5
+ };
6
+ readonly "account-urn": {
7
+ readonly type: "string";
8
+ readonly description: "Alias for --account-id";
9
+ };
10
+ readonly "all-statuses": {
11
+ readonly type: "boolean";
12
+ readonly description: "Drop the default ACTIVE filter";
13
+ };
14
+ readonly statuses: {
15
+ readonly type: "string";
16
+ readonly description: "CSV of statuses (ACTIVE,PAUSED,ARCHIVED,COMPLETED,DRAFT)";
17
+ };
18
+ readonly limit: {
19
+ readonly type: "string";
20
+ readonly description: "Max rows (default: 500)";
21
+ };
22
+ readonly "skip-cache": {
23
+ readonly type: "boolean";
24
+ readonly description: "Bypass server-side cache";
25
+ };
26
+ readonly output: {
27
+ readonly type: "string";
28
+ readonly description: "json|csv|jsonl|md";
29
+ readonly default: "json";
30
+ };
31
+ }>;
32
+ //# sourceMappingURL=campaign-groups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaign-groups.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/campaign-groups.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyChC,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiGet } from "../../../client.js";
3
+ import { writeAdsJson, writeAdsOutput } from "../output.js";
4
+ import { csvOrJson, handleLinkedinError, resolveAccountIdArg, resolveStatusFilter } from "./shared.js";
5
+ export const campaignGroupsCommand = defineCommand({
6
+ meta: {
7
+ name: "campaign-groups",
8
+ description: `List LinkedIn campaign groups.
9
+
10
+ Default: ACTIVE only. Pass --all-statuses to widen, or --statuses ACTIVE,PAUSED to override.
11
+
12
+ Examples:
13
+ baker ads linkedin campaign-groups --account-id 503001492
14
+ baker ads linkedin campaign-groups --account-id 503001492 --all-statuses
15
+ baker ads linkedin campaign-groups --account-id 503001492 --statuses ACTIVE,PAUSED --output csv`,
16
+ },
17
+ args: {
18
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
19
+ "account-urn": { type: "string", description: "Alias for --account-id" },
20
+ "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
21
+ statuses: { type: "string", description: "CSV of statuses (ACTIVE,PAUSED,ARCHIVED,COMPLETED,DRAFT)" },
22
+ limit: { type: "string", description: "Max rows (default: 500)" },
23
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
24
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
25
+ },
26
+ run: async ({ args }) => {
27
+ const accountId = resolveAccountIdArg(args);
28
+ try {
29
+ const params = { "account-id": accountId };
30
+ const statuses = resolveStatusFilter(args);
31
+ if (statuses)
32
+ params.statuses = statuses.join(",");
33
+ if (args.limit)
34
+ params.limit = String(args.limit);
35
+ if (args["skip-cache"])
36
+ params["skip-cache"] = "true";
37
+ const data = await apiGet("/api/ads/linkedin/campaign-groups", params);
38
+ const fmt = csvOrJson(args);
39
+ if (fmt !== "json") {
40
+ writeAdsOutput(data, fmt);
41
+ return;
42
+ }
43
+ writeAdsJson({ ok: true, data });
44
+ }
45
+ catch (err) {
46
+ handleLinkedinError(err);
47
+ }
48
+ },
49
+ });
50
+ //# sourceMappingURL=campaign-groups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaign-groups.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/campaign-groups.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAavG,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAC;IACjD,IAAI,EAAE;QACJ,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE;;;;;;;kGAOiF;KAC/F;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iDAAiD,EAAE;QAChG,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;QACxE,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,gCAAgC,EAAE;QAClF,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0DAA0D,EAAE;QACrG,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;QACjE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,0BAA0B,EAAE;QAC1E,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE;KAC9E;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,MAAM,GAA2B,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,IAAI,CAAC,KAAK;gBAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,IAAI,CAAC,YAAY,CAAC;gBAAE,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC;YAEtD,MAAM,IAAI,GAAG,MAAM,MAAM,CAA6B,mCAAmC,EAAE,MAAM,CAAC,CAAC;YACnG,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,cAAc,CAAC,IAAiD,EAAE,GAAG,CAAC,CAAC;gBACvE,OAAO;YACT,CAAC;YACD,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ export declare const campaignsCommand: import("citty").CommandDef<{
2
+ readonly "account-id": {
3
+ readonly type: "string";
4
+ readonly description: "Numeric account ID or urn:li:sponsoredAccount:N";
5
+ };
6
+ readonly "account-urn": {
7
+ readonly type: "string";
8
+ readonly description: "Alias for --account-id";
9
+ };
10
+ readonly "campaign-group-id": {
11
+ readonly type: "string";
12
+ readonly description: "Filter by campaign group";
13
+ };
14
+ readonly "all-statuses": {
15
+ readonly type: "boolean";
16
+ readonly description: "Drop the default ACTIVE filter";
17
+ };
18
+ readonly statuses: {
19
+ readonly type: "string";
20
+ readonly description: "CSV of statuses";
21
+ };
22
+ readonly limit: {
23
+ readonly type: "string";
24
+ readonly description: "Max rows (default: 500)";
25
+ };
26
+ readonly "skip-cache": {
27
+ readonly type: "boolean";
28
+ readonly description: "Bypass server-side cache";
29
+ };
30
+ readonly output: {
31
+ readonly type: "string";
32
+ readonly description: "json|csv|jsonl|md";
33
+ readonly default: "json";
34
+ };
35
+ }>;
36
+ //# sourceMappingURL=campaigns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaigns.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/campaigns.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+C3B,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiGet } from "../../../client.js";
3
+ import { writeAdsJson, writeAdsOutput } from "../output.js";
4
+ import { csvOrJson, handleLinkedinError, resolveAccountIdArg, resolveStatusFilter } from "./shared.js";
5
+ export const campaignsCommand = defineCommand({
6
+ meta: {
7
+ name: "campaigns",
8
+ description: `List LinkedIn campaigns.
9
+
10
+ Default: ACTIVE only. The schema includes the audit-relevant settings:
11
+ audienceExpansionEnabled — playbook §02 silent budget drain (should be false)
12
+ offsiteDeliveryEnabled — LinkedIn Audience Network gate
13
+ optimizationTargetType — driver of the bidding strategy
14
+ costType — CPC | CPM | CPV | CPS
15
+
16
+ Examples:
17
+ baker ads linkedin campaigns --account-id 503001492
18
+ baker ads linkedin campaigns --account-id 503001492 --campaign-group-id 12345
19
+ baker ads linkedin campaigns --account-id 503001492 --all-statuses --output csv`,
20
+ },
21
+ args: {
22
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
23
+ "account-urn": { type: "string", description: "Alias for --account-id" },
24
+ "campaign-group-id": { type: "string", description: "Filter by campaign group" },
25
+ "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
26
+ statuses: { type: "string", description: "CSV of statuses" },
27
+ limit: { type: "string", description: "Max rows (default: 500)" },
28
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
29
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
30
+ },
31
+ run: async ({ args }) => {
32
+ const accountId = resolveAccountIdArg(args);
33
+ try {
34
+ const params = { "account-id": accountId };
35
+ const statuses = resolveStatusFilter(args);
36
+ if (statuses)
37
+ params.statuses = statuses.join(",");
38
+ if (args["campaign-group-id"])
39
+ params["campaign-group-id"] = String(args["campaign-group-id"]);
40
+ if (args.limit)
41
+ params.limit = String(args.limit);
42
+ if (args["skip-cache"])
43
+ params["skip-cache"] = "true";
44
+ const data = await apiGet("/api/ads/linkedin/campaigns", params);
45
+ const fmt = csvOrJson(args);
46
+ if (fmt !== "json") {
47
+ writeAdsOutput(data, fmt);
48
+ return;
49
+ }
50
+ writeAdsJson({ ok: true, data });
51
+ }
52
+ catch (err) {
53
+ handleLinkedinError(err);
54
+ }
55
+ },
56
+ });
57
+ //# sourceMappingURL=campaigns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"campaigns.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/campaigns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAwBvG,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;IAC5C,IAAI,EAAE;QACJ,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE;;;;;;;;;;;kFAWiE;KAC/E;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iDAAiD,EAAE;QAChG,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;QACxE,mBAAmB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;QAChF,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,gCAAgC,EAAE;QAClF,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE;QAC5D,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;QACjE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,0BAA0B,EAAE;QAC1E,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE;KAC9E;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,MAAM,GAA2B,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,IAAI,CAAC,mBAAmB,CAAC;gBAAE,MAAM,CAAC,mBAAmB,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;YAC/F,IAAI,IAAI,CAAC,KAAK;gBAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,IAAI,CAAC,YAAY,CAAC;gBAAE,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC;YAEtD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAwB,6BAA6B,EAAE,MAAM,CAAC,CAAC;YACxF,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,cAAc,CAAC,IAAiD,EAAE,GAAG,CAAC,CAAC;gBACvE,OAAO;YACT,CAAC;YACD,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Conversation Ads (Sponsored Messaging) per-button analytics. Wraps
3
+ * --pivot conversation-node-button on /api/ads/linkedin/analytics.
4
+ *
5
+ * Lets agents see which CTA button inside a multi-step Sponsored Message
6
+ * actually drives clicks — no other ad platform exposes this granularity.
7
+ */
8
+ export declare const conversationCommand: import("citty").CommandDef<{
9
+ readonly "campaign-id": {
10
+ readonly type: "string";
11
+ readonly description: "Comma-separated campaign IDs (Conversation Ad campaigns)";
12
+ readonly required: true;
13
+ };
14
+ readonly start: {
15
+ readonly type: "string";
16
+ readonly description: "Start date YYYY-MM-DD";
17
+ };
18
+ readonly end: {
19
+ readonly type: "string";
20
+ readonly description: "End date YYYY-MM-DD";
21
+ };
22
+ readonly "last-days": {
23
+ readonly type: "string";
24
+ readonly description: "Window relative to today (default: 30)";
25
+ };
26
+ readonly "skip-cache": {
27
+ readonly type: "boolean";
28
+ readonly description: "Bypass server-side cache";
29
+ };
30
+ readonly output: {
31
+ readonly type: "string";
32
+ readonly description: "json|csv|jsonl|md";
33
+ readonly default: "json";
34
+ };
35
+ }>;
36
+ //# sourceMappingURL=conversation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/conversation.ts"],"names":[],"mappings":"AAWA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgE9B,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiPost } from "../../../client.js";
3
+ import { writeAdsJson, writeAdsOutput } from "../output.js";
4
+ import { csvOrJson, daysAgoIso, handleLinkedinError, todayIso } from "./shared.js";
5
+ /**
6
+ * Conversation Ads (Sponsored Messaging) per-button analytics. Wraps
7
+ * --pivot conversation-node-button on /api/ads/linkedin/analytics.
8
+ *
9
+ * Lets agents see which CTA button inside a multi-step Sponsored Message
10
+ * actually drives clicks — no other ad platform exposes this granularity.
11
+ */
12
+ export const conversationCommand = defineCommand({
13
+ meta: {
14
+ name: "conversation",
15
+ description: `Per-button click rates inside Sponsored Messaging / Conversation Ads.
16
+
17
+ Returns one row per CONVERSATION_NODE_BUTTON pivot, sorted by clicks desc.
18
+ Use this to A/B test button copy and the cascade tree.
19
+
20
+ Examples:
21
+ baker ads linkedin conversation --campaign-id 1234
22
+ baker ads linkedin conversation --campaign-id 1234 --last-days 30 --output csv`,
23
+ },
24
+ args: {
25
+ "campaign-id": {
26
+ type: "string",
27
+ description: "Comma-separated campaign IDs (Conversation Ad campaigns)",
28
+ required: true,
29
+ },
30
+ start: { type: "string", description: "Start date YYYY-MM-DD" },
31
+ end: { type: "string", description: "End date YYYY-MM-DD" },
32
+ "last-days": { type: "string", description: "Window relative to today (default: 30)" },
33
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
34
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
35
+ },
36
+ run: async ({ args }) => {
37
+ const campaignIdsRaw = args["campaign-id"];
38
+ if (!campaignIdsRaw) {
39
+ handleLinkedinError(new Error("--campaign-id is required"));
40
+ }
41
+ const ids = campaignIdsRaw
42
+ .split(",")
43
+ .map((s) => s.trim())
44
+ .filter(Boolean);
45
+ const start = args.start ?? daysAgoIso(args["last-days"] ? Number(args["last-days"]) : 30);
46
+ const end = args.end ?? todayIso();
47
+ try {
48
+ const data = await apiPost("/api/ads/linkedin/analytics", {
49
+ request: {
50
+ level: "campaign",
51
+ ids,
52
+ intent: "inmail",
53
+ pivot: "conversation-node-button",
54
+ start,
55
+ end,
56
+ granularity: "ALL",
57
+ limit: 500,
58
+ },
59
+ skipCache: Boolean(args["skip-cache"]),
60
+ });
61
+ const sorted = [...data.rows].sort((a, b) => Number(b.clicks ?? 0) - Number(a.clicks ?? 0));
62
+ const fmt = csvOrJson(args);
63
+ if (fmt !== "json") {
64
+ writeAdsOutput(sorted, fmt, data.fields);
65
+ return;
66
+ }
67
+ writeAdsJson({
68
+ ok: true,
69
+ data: { query: { campaigns: ids, start, end }, rows: sorted, warnings: data.warnings },
70
+ });
71
+ }
72
+ catch (err) {
73
+ handleLinkedinError(err);
74
+ }
75
+ },
76
+ });
77
+ //# sourceMappingURL=conversation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/conversation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAQnF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAC;IAC/C,IAAI,EAAE;QACJ,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE;;;;;;;iFAOgE;KAC9E;IACD,IAAI,EAAE;QACJ,aAAa,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,0DAA0D;YACvE,QAAQ,EAAE,IAAI;SACf;QACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;QAC/D,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qBAAqB,EAAE;QAC3D,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wCAAwC,EAAE;QACtF,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,0BAA0B,EAAE;QAC1E,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE;KAC9E;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAuB,CAAC;QACjE,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,mBAAmB,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,GAAG,GAAG,cAAc;aACvB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC,CAAC;QACnB,MAAM,KAAK,GAAI,IAAI,CAAC,KAA4B,IAAI,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnH,MAAM,GAAG,GAAI,IAAI,CAAC,GAA0B,IAAI,QAAQ,EAAE,CAAC;QAE3D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAoB,6BAA6B,EAAE;gBAC3E,OAAO,EAAE;oBACP,KAAK,EAAE,UAAU;oBACjB,GAAG;oBACH,MAAM,EAAE,QAAQ;oBAChB,KAAK,EAAE,0BAA0B;oBACjC,KAAK;oBACL,GAAG;oBACH,WAAW,EAAE,KAAK;oBAClB,KAAK,EAAE,GAAG;iBACX;gBACD,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;aACvC,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5F,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBACzC,OAAO;YACT,CAAC;YACD,YAAY,CAAC;gBACX,EAAE,EAAE,IAAI;gBACR,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;aACvF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const conversionsCommand: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ //# sourceMappingURL=conversions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversions.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/conversions.ts"],"names":[],"mappings":"AAsHA,eAAO,MAAM,kBAAkB,qDAa7B,CAAC"}
@@ -0,0 +1,102 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiGet } from "../../../client.js";
3
+ import { writeAdsJson, writeAdsOutput } from "../output.js";
4
+ import { csvOrJson, handleLinkedinError, resolveAccountIdArg } from "./shared.js";
5
+ const DAY_MS = 86_400_000;
6
+ function healthOf(rules) {
7
+ const enabled = rules.filter((r) => r.enabled !== false);
8
+ const capi = enabled.filter((r) => r.conversionMethod === "CONVERSIONS_API");
9
+ const pixel = enabled.filter((r) => r.conversionMethod === "PIXEL");
10
+ const staleCapi = capi.filter((r) => !r.lastConversionReportedAt || Date.now() - r.lastConversionReportedAt > 7 * DAY_MS);
11
+ const longView = enabled.filter((r) => r.viewThroughAttributionWindowSize !== undefined && r.viewThroughAttributionWindowSize > 7);
12
+ const leads = enabled.filter((r) => r.type === "LEAD");
13
+ const wrongDedup = leads.filter((r) => r.countingMethod && r.countingMethod !== "ONE_TIME_EACH_MEMBER");
14
+ return {
15
+ totalRules: rules.length,
16
+ enabledRules: enabled.length,
17
+ capiRules: capi.length,
18
+ pixelRules: pixel.length,
19
+ hasLeadEvent: leads.length > 0,
20
+ hasPurchaseEvent: enabled.some((r) => r.type === "PURCHASE"),
21
+ staleCapiRules: staleCapi,
22
+ longViewWindow: longView,
23
+ wrongLeadDedup: wrongDedup,
24
+ };
25
+ }
26
+ const listCmd = defineCommand({
27
+ meta: {
28
+ name: "list",
29
+ description: `List conversion rules on the account.`,
30
+ },
31
+ args: {
32
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
33
+ "account-urn": { type: "string", description: "Alias for --account-id" },
34
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
35
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
36
+ },
37
+ run: async ({ args }) => {
38
+ const accountId = resolveAccountIdArg(args);
39
+ try {
40
+ const params = { "account-id": accountId };
41
+ if (args["skip-cache"])
42
+ params["skip-cache"] = "true";
43
+ const data = await apiGet("/api/ads/linkedin/conversions", params);
44
+ const fmt = csvOrJson(args);
45
+ if (fmt !== "json") {
46
+ writeAdsOutput(data, fmt);
47
+ return;
48
+ }
49
+ writeAdsJson({ ok: true, data });
50
+ }
51
+ catch (err) {
52
+ handleLinkedinError(err);
53
+ }
54
+ },
55
+ });
56
+ const healthCmd = defineCommand({
57
+ meta: {
58
+ name: "health",
59
+ description: `5-point Insight Tag / CAPI health check (playbook §07).
60
+
61
+ Surfaces:
62
+ - Are rules enabled?
63
+ - Do we have at least one LEAD or PURCHASE event?
64
+ - Do CAPI rules show recent activity (≤7 days)?
65
+ - Is the view-through window ≤7 days?
66
+ - Do LEAD rules use ONE_TIME_EACH_MEMBER de-dup?`,
67
+ },
68
+ args: {
69
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
70
+ "account-urn": { type: "string", description: "Alias for --account-id" },
71
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
72
+ output: { type: "string", description: "json", default: "json" },
73
+ },
74
+ run: async ({ args }) => {
75
+ const accountId = resolveAccountIdArg(args);
76
+ try {
77
+ const params = { "account-id": accountId };
78
+ if (args["skip-cache"])
79
+ params["skip-cache"] = "true";
80
+ const data = await apiGet("/api/ads/linkedin/conversions", params);
81
+ writeAdsJson({ ok: true, data: healthOf(data) });
82
+ }
83
+ catch (err) {
84
+ handleLinkedinError(err);
85
+ }
86
+ },
87
+ });
88
+ export const conversionsCommand = defineCommand({
89
+ meta: {
90
+ name: "conversions",
91
+ description: `Conversion rules — Insight Tag and Conversions API.
92
+
93
+ Subcommands:
94
+ list — every rule on the account
95
+ health — playbook §07 5-point health check`,
96
+ },
97
+ subCommands: {
98
+ list: listCmd,
99
+ health: healthCmd,
100
+ },
101
+ });
102
+ //# sourceMappingURL=conversions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversions.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/conversions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export declare const creativesCommand: import("citty").CommandDef<{
2
+ readonly "account-id": {
3
+ readonly type: "string";
4
+ readonly description: "Numeric account ID or urn:li:sponsoredAccount:N";
5
+ };
6
+ readonly "account-urn": {
7
+ readonly type: "string";
8
+ readonly description: "Alias for --account-id";
9
+ };
10
+ readonly "campaign-id": {
11
+ readonly type: "string";
12
+ readonly description: "Filter by campaign ID";
13
+ };
14
+ readonly "all-statuses": {
15
+ readonly type: "boolean";
16
+ readonly description: "Drop the default ACTIVE filter";
17
+ };
18
+ readonly statuses: {
19
+ readonly type: "string";
20
+ readonly description: "CSV of intended statuses (ACTIVE,PAUSED,DRAFT,ARCHIVED)";
21
+ };
22
+ readonly limit: {
23
+ readonly type: "string";
24
+ readonly description: "Max rows (default: 500)";
25
+ };
26
+ readonly "skip-cache": {
27
+ readonly type: "boolean";
28
+ readonly description: "Bypass server-side cache";
29
+ };
30
+ readonly output: {
31
+ readonly type: "string";
32
+ readonly description: "json|csv|jsonl|md";
33
+ readonly default: "json";
34
+ };
35
+ }>;
36
+ //# sourceMappingURL=creatives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"creatives.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/creatives.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+C3B,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { defineCommand } from "citty";
2
+ import { apiGet } from "../../../client.js";
3
+ import { writeAdsJson, writeAdsOutput } from "../output.js";
4
+ import { csvOrJson, handleLinkedinError, resolveAccountIdArg, resolveStatusFilter } from "./shared.js";
5
+ export const creativesCommand = defineCommand({
6
+ meta: {
7
+ name: "creatives",
8
+ description: `List LinkedIn creatives (ads).
9
+
10
+ Defaults to ACTIVE intended-status. Pass --all-statuses or --statuses ACTIVE,PAUSED to widen.
11
+
12
+ The 'content' block is opaque (varies by creative type — image, video, document,
13
+ spotlight, conversation, dynamic). Use 'reviewStatus' to spot rejected/pending
14
+ creatives during an audit.
15
+
16
+ Examples:
17
+ baker ads linkedin creatives --account-id 503001492
18
+ baker ads linkedin creatives --account-id 503001492 --campaign-id 1234
19
+ baker ads linkedin creatives --account-id 503001492 --all-statuses --output csv`,
20
+ },
21
+ args: {
22
+ "account-id": { type: "string", description: "Numeric account ID or urn:li:sponsoredAccount:N" },
23
+ "account-urn": { type: "string", description: "Alias for --account-id" },
24
+ "campaign-id": { type: "string", description: "Filter by campaign ID" },
25
+ "all-statuses": { type: "boolean", description: "Drop the default ACTIVE filter" },
26
+ statuses: { type: "string", description: "CSV of intended statuses (ACTIVE,PAUSED,DRAFT,ARCHIVED)" },
27
+ limit: { type: "string", description: "Max rows (default: 500)" },
28
+ "skip-cache": { type: "boolean", description: "Bypass server-side cache" },
29
+ output: { type: "string", description: "json|csv|jsonl|md", default: "json" },
30
+ },
31
+ run: async ({ args }) => {
32
+ const accountId = resolveAccountIdArg(args);
33
+ try {
34
+ const params = { "account-id": accountId };
35
+ const statuses = resolveStatusFilter(args);
36
+ if (statuses)
37
+ params.statuses = statuses.join(",");
38
+ if (args["campaign-id"])
39
+ params["campaign-id"] = String(args["campaign-id"]);
40
+ if (args.limit)
41
+ params.limit = String(args.limit);
42
+ if (args["skip-cache"])
43
+ params["skip-cache"] = "true";
44
+ const data = await apiGet("/api/ads/linkedin/creatives", params);
45
+ const fmt = csvOrJson(args);
46
+ if (fmt !== "json") {
47
+ writeAdsOutput(data, fmt);
48
+ return;
49
+ }
50
+ writeAdsJson({ ok: true, data });
51
+ }
52
+ catch (err) {
53
+ handleLinkedinError(err);
54
+ }
55
+ },
56
+ });
57
+ //# sourceMappingURL=creatives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"creatives.js","sourceRoot":"","sources":["../../../../src/commands/ads/linkedin/creatives.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAevG,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;IAC5C,IAAI,EAAE;QACJ,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE;;;;;;;;;;;kFAWiE;KAC/E;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iDAAiD,EAAE;QAChG,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;QACxE,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;QACvE,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,gCAAgC,EAAE;QAClF,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yDAAyD,EAAE;QACpG,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yBAAyB,EAAE;QACjE,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,0BAA0B,EAAE;QAC1E,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE;KAC9E;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,MAAM,GAA2B,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,IAAI,CAAC,aAAa,CAAC;gBAAE,MAAM,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;YAC7E,IAAI,IAAI,CAAC,KAAK;gBAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,IAAI,CAAC,YAAY,CAAC;gBAAE,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC;YAEtD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAwB,6BAA6B,EAAE,MAAM,CAAC,CAAC;YACxF,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;gBACnB,cAAc,CAAC,IAAiD,EAAE,GAAG,CAAC,CAAC;gBACvE,OAAO;YACT,CAAC;YACD,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}