@koda-sl/baker-cli 0.25.1 → 0.27.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/README.md +218 -0
- package/dist/cli.js +1 -1
- package/dist/commands/ads/index.d.ts.map +1 -1
- package/dist/commands/ads/index.js +12 -3
- package/dist/commands/ads/index.js.map +1 -1
- package/dist/commands/ads/linkedin/account.d.ts +20 -0
- package/dist/commands/ads/linkedin/account.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/account.js +39 -0
- package/dist/commands/ads/linkedin/account.js.map +1 -0
- package/dist/commands/ads/linkedin/accounts.d.ts +20 -0
- package/dist/commands/ads/linkedin/accounts.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/accounts.js +56 -0
- package/dist/commands/ads/linkedin/accounts.js.map +1 -0
- package/dist/commands/ads/linkedin/analytics.d.ts +84 -0
- package/dist/commands/ads/linkedin/analytics.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/analytics.js +249 -0
- package/dist/commands/ads/linkedin/analytics.js.map +1 -0
- package/dist/commands/ads/linkedin/audience-size.d.ts +28 -0
- package/dist/commands/ads/linkedin/audience-size.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/audience-size.js +75 -0
- package/dist/commands/ads/linkedin/audience-size.js.map +1 -0
- package/dist/commands/ads/linkedin/audit.d.ts +35 -0
- package/dist/commands/ads/linkedin/audit.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/audit.js +136 -0
- package/dist/commands/ads/linkedin/audit.js.map +1 -0
- package/dist/commands/ads/linkedin/bid-pricing.d.ts +38 -0
- package/dist/commands/ads/linkedin/bid-pricing.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/bid-pricing.js +76 -0
- package/dist/commands/ads/linkedin/bid-pricing.js.map +1 -0
- package/dist/commands/ads/linkedin/campaign-groups.d.ts +32 -0
- package/dist/commands/ads/linkedin/campaign-groups.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/campaign-groups.js +50 -0
- package/dist/commands/ads/linkedin/campaign-groups.js.map +1 -0
- package/dist/commands/ads/linkedin/campaigns.d.ts +36 -0
- package/dist/commands/ads/linkedin/campaigns.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/campaigns.js +57 -0
- package/dist/commands/ads/linkedin/campaigns.js.map +1 -0
- package/dist/commands/ads/linkedin/conversation.d.ts +36 -0
- package/dist/commands/ads/linkedin/conversation.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/conversation.js +77 -0
- package/dist/commands/ads/linkedin/conversation.js.map +1 -0
- package/dist/commands/ads/linkedin/conversions.d.ts +2 -0
- package/dist/commands/ads/linkedin/conversions.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/conversions.js +102 -0
- package/dist/commands/ads/linkedin/conversions.js.map +1 -0
- package/dist/commands/ads/linkedin/creatives.d.ts +36 -0
- package/dist/commands/ads/linkedin/creatives.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/creatives.js +57 -0
- package/dist/commands/ads/linkedin/creatives.js.map +1 -0
- package/dist/commands/ads/linkedin/demographics.d.ts +40 -0
- package/dist/commands/ads/linkedin/demographics.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/demographics.js +117 -0
- package/dist/commands/ads/linkedin/demographics.js.map +1 -0
- package/dist/commands/ads/linkedin/facets.d.ts +2 -0
- package/dist/commands/ads/linkedin/facets.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/facets.js +95 -0
- package/dist/commands/ads/linkedin/facets.js.map +1 -0
- package/dist/commands/ads/linkedin/forecast.d.ts +50 -0
- package/dist/commands/ads/linkedin/forecast.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/forecast.js +83 -0
- package/dist/commands/ads/linkedin/forecast.js.map +1 -0
- package/dist/commands/ads/linkedin/index.d.ts +19 -0
- package/dist/commands/ads/linkedin/index.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/index.js +83 -0
- package/dist/commands/ads/linkedin/index.js.map +1 -0
- package/dist/commands/ads/linkedin/leads.d.ts +40 -0
- package/dist/commands/ads/linkedin/leads.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/leads.js +75 -0
- package/dist/commands/ads/linkedin/leads.js.map +1 -0
- package/dist/commands/ads/linkedin/presets.d.ts +40 -0
- package/dist/commands/ads/linkedin/presets.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/presets.js +193 -0
- package/dist/commands/ads/linkedin/presets.js.map +1 -0
- package/dist/commands/ads/linkedin/presets.test.d.ts +2 -0
- package/dist/commands/ads/linkedin/presets.test.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/presets.test.js +98 -0
- package/dist/commands/ads/linkedin/presets.test.js.map +1 -0
- package/dist/commands/ads/linkedin/schemas.d.ts +2 -0
- package/dist/commands/ads/linkedin/schemas.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/schemas.js +300 -0
- package/dist/commands/ads/linkedin/schemas.js.map +1 -0
- package/dist/commands/ads/linkedin/shared.d.ts +17 -0
- package/dist/commands/ads/linkedin/shared.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/shared.js +116 -0
- package/dist/commands/ads/linkedin/shared.js.map +1 -0
- package/dist/commands/ads/linkedin/top-companies.d.ts +44 -0
- package/dist/commands/ads/linkedin/top-companies.d.ts.map +1 -0
- package/dist/commands/ads/linkedin/top-companies.js +86 -0
- package/dist/commands/ads/linkedin/top-companies.js.map +1 -0
- package/dist/commands/ads/x/accounts.d.ts +14 -0
- package/dist/commands/ads/x/accounts.d.ts.map +1 -0
- package/dist/commands/ads/x/accounts.js +73 -0
- package/dist/commands/ads/x/accounts.js.map +1 -0
- package/dist/commands/ads/x/active-entities.d.ts +43 -0
- package/dist/commands/ads/x/active-entities.d.ts.map +1 -0
- package/dist/commands/ads/x/active-entities.js +88 -0
- package/dist/commands/ads/x/active-entities.js.map +1 -0
- package/dist/commands/ads/x/audiences.d.ts +19 -0
- package/dist/commands/ads/x/audiences.d.ts.map +1 -0
- package/dist/commands/ads/x/audiences.js +65 -0
- package/dist/commands/ads/x/audiences.js.map +1 -0
- package/dist/commands/ads/x/campaigns.d.ts +34 -0
- package/dist/commands/ads/x/campaigns.d.ts.map +1 -0
- package/dist/commands/ads/x/campaigns.js +56 -0
- package/dist/commands/ads/x/campaigns.js.map +1 -0
- package/dist/commands/ads/x/cards.d.ts +19 -0
- package/dist/commands/ads/x/cards.d.ts.map +1 -0
- package/dist/commands/ads/x/cards.js +65 -0
- package/dist/commands/ads/x/cards.js.map +1 -0
- package/dist/commands/ads/x/error-parser.d.ts +3 -0
- package/dist/commands/ads/x/error-parser.d.ts.map +1 -0
- package/dist/commands/ads/x/error-parser.js +80 -0
- package/dist/commands/ads/x/error-parser.js.map +1 -0
- package/dist/commands/ads/x/funding.d.ts +19 -0
- package/dist/commands/ads/x/funding.d.ts.map +1 -0
- package/dist/commands/ads/x/funding.js +65 -0
- package/dist/commands/ads/x/funding.js.map +1 -0
- package/dist/commands/ads/x/index.d.ts +2 -0
- package/dist/commands/ads/x/index.d.ts.map +1 -0
- package/dist/commands/ads/x/index.js +50 -0
- package/dist/commands/ads/x/index.js.map +1 -0
- package/dist/commands/ads/x/line-items.d.ts +34 -0
- package/dist/commands/ads/x/line-items.d.ts.map +1 -0
- package/dist/commands/ads/x/line-items.js +55 -0
- package/dist/commands/ads/x/line-items.js.map +1 -0
- package/dist/commands/ads/x/media.d.ts +24 -0
- package/dist/commands/ads/x/media.d.ts.map +1 -0
- package/dist/commands/ads/x/media.js +70 -0
- package/dist/commands/ads/x/media.js.map +1 -0
- package/dist/commands/ads/x/output.d.ts +13 -0
- package/dist/commands/ads/x/output.d.ts.map +1 -0
- package/dist/commands/ads/x/output.js +75 -0
- package/dist/commands/ads/x/output.js.map +1 -0
- package/dist/commands/ads/x/presets.d.ts +15 -0
- package/dist/commands/ads/x/presets.d.ts.map +1 -0
- package/dist/commands/ads/x/presets.js +60 -0
- package/dist/commands/ads/x/presets.js.map +1 -0
- package/dist/commands/ads/x/promoted-tweets.d.ts +29 -0
- package/dist/commands/ads/x/promoted-tweets.d.ts.map +1 -0
- package/dist/commands/ads/x/promoted-tweets.js +74 -0
- package/dist/commands/ads/x/promoted-tweets.js.map +1 -0
- package/dist/commands/ads/x/run-list.d.ts +17 -0
- package/dist/commands/ads/x/run-list.d.ts.map +1 -0
- package/dist/commands/ads/x/run-list.js +60 -0
- package/dist/commands/ads/x/run-list.js.map +1 -0
- package/dist/commands/ads/x/stats/index.d.ts +2 -0
- package/dist/commands/ads/x/stats/index.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/index.js +32 -0
- package/dist/commands/ads/x/stats/index.js.map +1 -0
- package/dist/commands/ads/x/stats/job-create.d.ts +58 -0
- package/dist/commands/ads/x/stats/job-create.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/job-create.js +95 -0
- package/dist/commands/ads/x/stats/job-create.js.map +1 -0
- package/dist/commands/ads/x/stats/job-status.d.ts +18 -0
- package/dist/commands/ads/x/stats/job-status.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/job-status.js +58 -0
- package/dist/commands/ads/x/stats/job-status.js.map +1 -0
- package/dist/commands/ads/x/stats/job.d.ts +63 -0
- package/dist/commands/ads/x/stats/job.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/job.js +183 -0
- package/dist/commands/ads/x/stats/job.js.map +1 -0
- package/dist/commands/ads/x/stats/sync.d.ts +73 -0
- package/dist/commands/ads/x/stats/sync.d.ts.map +1 -0
- package/dist/commands/ads/x/stats/sync.js +151 -0
- package/dist/commands/ads/x/stats/sync.js.map +1 -0
- package/dist/commands/ads/x/targeting-constants.d.ts +34 -0
- package/dist/commands/ads/x/targeting-constants.d.ts.map +1 -0
- package/dist/commands/ads/x/targeting-constants.js +80 -0
- package/dist/commands/ads/x/targeting-constants.js.map +1 -0
- package/dist/commands/ads/x/targeting-criteria.d.ts +24 -0
- package/dist/commands/ads/x/targeting-criteria.d.ts.map +1 -0
- package/dist/commands/ads/x/targeting-criteria.js +69 -0
- package/dist/commands/ads/x/targeting-criteria.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +8 -0
- package/dist/env.js.map +1 -1
- package/dist/error-handler.d.ts +1 -1
- package/dist/error-handler.d.ts.map +1 -1
- package/dist/error-handler.js +6 -0
- package/dist/error-handler.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { ApiError, apiGet } from "../../../client.js";
|
|
3
|
+
import { registerSchema } from "../../../schemas.js";
|
|
4
|
+
import { cacheGet, cacheSet } from "../cache.js";
|
|
5
|
+
import { writeAdsJson, writeAdsOutput } from "../output.js";
|
|
6
|
+
import { parseXApiError } from "./error-parser.js";
|
|
7
|
+
import { resolveXAccountId } from "./output.js";
|
|
8
|
+
registerSchema({
|
|
9
|
+
command: "ads.x.funding",
|
|
10
|
+
description: "List funding instruments for an X Ads account. Returns id, type, currency, credit_limit_local_micro, funded_amount_local_micro, status. Falls back to BAKER_X_ADS_ACCOUNT_ID env var.",
|
|
11
|
+
args: {
|
|
12
|
+
"account-id": { type: "string", description: "X Ads account ID (base36)", required: false },
|
|
13
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
export const fundingCommand = defineCommand({
|
|
17
|
+
meta: {
|
|
18
|
+
name: "funding",
|
|
19
|
+
description: `List funding instruments for an X Ads account.
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
baker ads x funding --account-id 18ce53xyz`,
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
"account-id": { type: "string", description: "X Ads account ID", required: false },
|
|
26
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
27
|
+
output: { type: "string", description: "Format: json|csv|md", required: false, default: "json" },
|
|
28
|
+
},
|
|
29
|
+
run: async ({ args }) => {
|
|
30
|
+
const accountId = await resolveXAccountId(args);
|
|
31
|
+
const useCache = !args["no-cache"];
|
|
32
|
+
const cacheKey = `funding:${accountId}`;
|
|
33
|
+
if (useCache) {
|
|
34
|
+
const cached = cacheGet("x-account-data", cacheKey);
|
|
35
|
+
if (cached) {
|
|
36
|
+
writeAdsJson({ ok: true, data: cached.data, cached: true });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const params = { "account-id": accountId };
|
|
42
|
+
if (!useCache)
|
|
43
|
+
params["skip-cache"] = "true";
|
|
44
|
+
const data = await apiGet("/api/ads/x/funding-instruments", params);
|
|
45
|
+
if (useCache) {
|
|
46
|
+
cacheSet("x-account-data", cacheKey, data, 60 * 60 * 1000);
|
|
47
|
+
}
|
|
48
|
+
const format = args.output || "json";
|
|
49
|
+
if (format !== "json") {
|
|
50
|
+
writeAdsOutput(data, format);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
writeAdsJson({ ok: true, data });
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
if (err instanceof ApiError) {
|
|
57
|
+
writeAdsJson(parseXApiError(err.message, accountId));
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=funding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"funding.js","sourceRoot":"","sources":["../../../../src/commands/ads/x/funding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/x/index.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,QAAQ,qDAmCnB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { accountsCommand } from "./accounts.js";
|
|
3
|
+
import { activeEntitiesCommand } from "./active-entities.js";
|
|
4
|
+
import { audiencesCommand } from "./audiences.js";
|
|
5
|
+
import { campaignsCommand } from "./campaigns.js";
|
|
6
|
+
import { cardsCommand } from "./cards.js";
|
|
7
|
+
import { fundingCommand } from "./funding.js";
|
|
8
|
+
import { lineItemsCommand } from "./line-items.js";
|
|
9
|
+
import { mediaCommand } from "./media.js";
|
|
10
|
+
import { promotedTweetsCommand } from "./promoted-tweets.js";
|
|
11
|
+
import { statsCommand } from "./stats/index.js";
|
|
12
|
+
import { targetingConstantsCommand } from "./targeting-constants.js";
|
|
13
|
+
import { targetingCriteriaCommand } from "./targeting-criteria.js";
|
|
14
|
+
export const xCommand = defineCommand({
|
|
15
|
+
meta: {
|
|
16
|
+
name: "x",
|
|
17
|
+
description: `X (Twitter) Ads commands. Read campaigns, line items, promoted tweets, creatives, audiences, and analytics.
|
|
18
|
+
|
|
19
|
+
Start here:
|
|
20
|
+
baker ads x accounts — list accessible X Ads accounts
|
|
21
|
+
baker ads x stats sync --list-presets — see available stats presets
|
|
22
|
+
baker ads x targeting-constants --constant locations --q "Madrid"
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
baker ads x campaigns --account-id 18ce53xyz
|
|
26
|
+
baker ads x line-items --account-id 18ce53xyz --campaign-ids abc
|
|
27
|
+
baker ads x promoted-tweets --account-id 18ce53xyz
|
|
28
|
+
baker ads x stats sync --preset campaign-engagement-7d --entity-ids abc,def
|
|
29
|
+
baker ads x stats job-create --entity CAMPAIGN --entity-ids abc \\
|
|
30
|
+
--start-time 2026-04-01T00:00:00Z --end-time 2026-05-01T00:00:00Z \\
|
|
31
|
+
--metric-groups ENGAGEMENT,BILLING --segmentation-type LOCATIONS
|
|
32
|
+
|
|
33
|
+
The CLI auto-detects --account-id when exactly one X Ads account is connected, or via BAKER_X_ADS_ACCOUNT_ID.`,
|
|
34
|
+
},
|
|
35
|
+
subCommands: {
|
|
36
|
+
accounts: accountsCommand,
|
|
37
|
+
funding: fundingCommand,
|
|
38
|
+
campaigns: campaignsCommand,
|
|
39
|
+
"line-items": lineItemsCommand,
|
|
40
|
+
"promoted-tweets": promotedTweetsCommand,
|
|
41
|
+
cards: cardsCommand,
|
|
42
|
+
media: mediaCommand,
|
|
43
|
+
audiences: audiencesCommand,
|
|
44
|
+
"targeting-criteria": targetingCriteriaCommand,
|
|
45
|
+
"targeting-constants": targetingConstantsCommand,
|
|
46
|
+
"active-entities": activeEntitiesCommand,
|
|
47
|
+
stats: statsCommand,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/ads/x/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,MAAM,CAAC,MAAM,QAAQ,GAAG,aAAa,CAAC;IACpC,IAAI,EAAE;QACJ,IAAI,EAAE,GAAG;QACT,WAAW,EAAE;;;;;;;;;;;;;;;;8GAgB6F;KAC3G;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,cAAc;QACvB,SAAS,EAAE,gBAAgB;QAC3B,YAAY,EAAE,gBAAgB;QAC9B,iBAAiB,EAAE,qBAAqB;QACxC,KAAK,EAAE,YAAY;QACnB,KAAK,EAAE,YAAY;QACnB,SAAS,EAAE,gBAAgB;QAC3B,oBAAoB,EAAE,wBAAwB;QAC9C,qBAAqB,EAAE,yBAAyB;QAChD,iBAAiB,EAAE,qBAAqB;QACxC,KAAK,EAAE,YAAY;KACpB;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare const lineItemsCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "account-id": {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "X Ads account ID";
|
|
5
|
+
readonly required: false;
|
|
6
|
+
};
|
|
7
|
+
readonly "campaign-ids": {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "CSV of campaign IDs";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
readonly "line-item-ids": {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly description: "CSV of line item IDs";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
};
|
|
17
|
+
readonly "with-deleted": {
|
|
18
|
+
readonly type: "boolean";
|
|
19
|
+
readonly description: "Include deleted";
|
|
20
|
+
readonly required: false;
|
|
21
|
+
};
|
|
22
|
+
readonly "no-cache": {
|
|
23
|
+
readonly type: "boolean";
|
|
24
|
+
readonly description: "Skip cache";
|
|
25
|
+
readonly required: false;
|
|
26
|
+
};
|
|
27
|
+
readonly output: {
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
readonly description: "Format: json|csv|md";
|
|
30
|
+
readonly required: false;
|
|
31
|
+
readonly default: "json";
|
|
32
|
+
};
|
|
33
|
+
}>;
|
|
34
|
+
//# sourceMappingURL=line-items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-items.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/x/line-items.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsC3B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { registerSchema } from "../../../schemas.js";
|
|
3
|
+
import { resolveXAccountId } from "./output.js";
|
|
4
|
+
import { runListCommand } from "./run-list.js";
|
|
5
|
+
registerSchema({
|
|
6
|
+
command: "ads.x.lineItems",
|
|
7
|
+
description: "List line items (ad groups) for an X Ads account. Returns bid, product_type, objective, placements, schedule. Filter by campaign-ids or line-item-ids (CSV).",
|
|
8
|
+
args: {
|
|
9
|
+
"account-id": { type: "string", description: "X Ads account ID", required: false },
|
|
10
|
+
"campaign-ids": { type: "string", description: "CSV of campaign IDs", required: false },
|
|
11
|
+
"line-item-ids": { type: "string", description: "CSV of line item IDs", required: false },
|
|
12
|
+
"with-deleted": { type: "boolean", description: "Include deleted", required: false },
|
|
13
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
export const lineItemsCommand = defineCommand({
|
|
17
|
+
meta: {
|
|
18
|
+
name: "line-items",
|
|
19
|
+
description: `List X Ads line items (ad groups).
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
baker ads x line-items --account-id 18ce53xyz --campaign-ids abc
|
|
23
|
+
baker ads x line-items --account-id 18ce53xyz --with-deleted`,
|
|
24
|
+
},
|
|
25
|
+
args: {
|
|
26
|
+
"account-id": { type: "string", description: "X Ads account ID", required: false },
|
|
27
|
+
"campaign-ids": { type: "string", description: "CSV of campaign IDs", required: false },
|
|
28
|
+
"line-item-ids": { type: "string", description: "CSV of line item IDs", required: false },
|
|
29
|
+
"with-deleted": { type: "boolean", description: "Include deleted", required: false },
|
|
30
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
31
|
+
output: { type: "string", description: "Format: json|csv|md", required: false, default: "json" },
|
|
32
|
+
},
|
|
33
|
+
run: async ({ args }) => {
|
|
34
|
+
const accountId = await resolveXAccountId(args);
|
|
35
|
+
const useCache = !args["no-cache"];
|
|
36
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
37
|
+
const cacheKey = `line-items:${accountId}:${today}:${args["campaign-ids"] ?? ""}:${args["line-item-ids"] ?? ""}:${args["with-deleted"] ? "1" : "0"}`;
|
|
38
|
+
await runListCommand({
|
|
39
|
+
path: "/api/ads/x/line-items",
|
|
40
|
+
cacheCategory: "x-account-data",
|
|
41
|
+
cacheKey,
|
|
42
|
+
cacheTtlMs: 60 * 60 * 1000,
|
|
43
|
+
params: {
|
|
44
|
+
"account-id": accountId,
|
|
45
|
+
"campaign-ids": args["campaign-ids"],
|
|
46
|
+
"line-item-ids": args["line-item-ids"],
|
|
47
|
+
"with-deleted": args["with-deleted"] ? "true" : undefined,
|
|
48
|
+
},
|
|
49
|
+
format: args.output || "json",
|
|
50
|
+
accountId,
|
|
51
|
+
useCache,
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=line-items.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"line-items.js","sourceRoot":"","sources":["../../../../src/commands/ads/x/line-items.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const mediaCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "account-id": {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "X Ads account ID";
|
|
5
|
+
readonly required: false;
|
|
6
|
+
};
|
|
7
|
+
readonly "media-type": {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "IMAGE | GIF | VIDEO";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
readonly "no-cache": {
|
|
13
|
+
readonly type: "boolean";
|
|
14
|
+
readonly description: "Skip cache";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
};
|
|
17
|
+
readonly output: {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
readonly description: "Format: json|csv|md";
|
|
20
|
+
readonly required: false;
|
|
21
|
+
readonly default: "json";
|
|
22
|
+
};
|
|
23
|
+
}>;
|
|
24
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/x/media.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;EAkDvB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { ApiError, apiGet } from "../../../client.js";
|
|
3
|
+
import { registerSchema } from "../../../schemas.js";
|
|
4
|
+
import { cacheGet, cacheSet } from "../cache.js";
|
|
5
|
+
import { writeAdsJson, writeAdsOutput } from "../output.js";
|
|
6
|
+
import { parseXApiError } from "./error-parser.js";
|
|
7
|
+
import { resolveXAccountId } from "./output.js";
|
|
8
|
+
registerSchema({
|
|
9
|
+
command: "ads.x.media",
|
|
10
|
+
description: "List media assets in the X Ads media library (images, GIFs, videos). Filter by media-type (IMAGE, GIF, VIDEO).",
|
|
11
|
+
args: {
|
|
12
|
+
"account-id": { type: "string", description: "X Ads account ID", required: false },
|
|
13
|
+
"media-type": { type: "string", description: "IMAGE | GIF | VIDEO", required: false },
|
|
14
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
export const mediaCommand = defineCommand({
|
|
18
|
+
meta: {
|
|
19
|
+
name: "media",
|
|
20
|
+
description: `List media assets in the X Ads media library.
|
|
21
|
+
|
|
22
|
+
Examples:
|
|
23
|
+
baker ads x media --account-id 18ce53xyz
|
|
24
|
+
baker ads x media --account-id 18ce53xyz --media-type VIDEO`,
|
|
25
|
+
},
|
|
26
|
+
args: {
|
|
27
|
+
"account-id": { type: "string", description: "X Ads account ID", required: false },
|
|
28
|
+
"media-type": { type: "string", description: "IMAGE | GIF | VIDEO", required: false },
|
|
29
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
30
|
+
output: { type: "string", description: "Format: json|csv|md", required: false, default: "json" },
|
|
31
|
+
},
|
|
32
|
+
run: async ({ args }) => {
|
|
33
|
+
const accountId = await resolveXAccountId(args);
|
|
34
|
+
const useCache = !args["no-cache"];
|
|
35
|
+
const cacheKey = `media:${accountId}:${args["media-type"] ?? "ALL"}`;
|
|
36
|
+
if (useCache) {
|
|
37
|
+
const cached = cacheGet("x-account-data", cacheKey);
|
|
38
|
+
if (cached) {
|
|
39
|
+
writeAdsJson({ ok: true, data: cached.data, cached: true });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const params = { "account-id": accountId };
|
|
45
|
+
if (args["media-type"])
|
|
46
|
+
params["media-type"] = args["media-type"];
|
|
47
|
+
if (!useCache)
|
|
48
|
+
params["skip-cache"] = "true";
|
|
49
|
+
const data = await apiGet("/api/ads/x/media-library", params);
|
|
50
|
+
if (useCache) {
|
|
51
|
+
cacheSet("x-account-data", cacheKey, data, 6 * 60 * 60 * 1000);
|
|
52
|
+
}
|
|
53
|
+
const format = args.output || "json";
|
|
54
|
+
if (format !== "json") {
|
|
55
|
+
writeAdsOutput(data, format);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
writeAdsJson({ ok: true, data });
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof ApiError) {
|
|
62
|
+
writeAdsJson(parseXApiError(err.message, accountId));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../../../src/commands/ads/x/media.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface XAccountInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
approval_status?: string;
|
|
5
|
+
timezone?: string;
|
|
6
|
+
currency?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Resolve an X Ads account_id from either --account-id, BAKER_X_ADS_ACCOUNT_ID, or
|
|
10
|
+
* (if exactly one account is connected) auto-detect.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveXAccountId(args: Record<string, unknown>): Promise<string>;
|
|
13
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/x/output.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiBD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAmDtF"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { ApiError, apiGet } from "../../../client.js";
|
|
2
|
+
import { getEnv } from "../../../env.js";
|
|
3
|
+
import { handleConnectionError } from "../../../error-handler.js";
|
|
4
|
+
import { cacheGet, cacheSet } from "../cache.js";
|
|
5
|
+
import { writeAdsJson } from "../output.js";
|
|
6
|
+
const ACCOUNTS_CACHE_TTL_MS = 60 * 60 * 1000;
|
|
7
|
+
async function fetchXAccounts(useCache) {
|
|
8
|
+
if (useCache) {
|
|
9
|
+
const cached = cacheGet("x-accounts", "list");
|
|
10
|
+
if (cached)
|
|
11
|
+
return cached.data;
|
|
12
|
+
}
|
|
13
|
+
const params = !useCache ? { "skip-cache": "true" } : undefined;
|
|
14
|
+
const data = await apiGet("/api/ads/x/accounts", params);
|
|
15
|
+
if (useCache) {
|
|
16
|
+
cacheSet("x-accounts", "list", data, ACCOUNTS_CACHE_TTL_MS);
|
|
17
|
+
}
|
|
18
|
+
return data;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve an X Ads account_id from either --account-id, BAKER_X_ADS_ACCOUNT_ID, or
|
|
22
|
+
* (if exactly one account is connected) auto-detect.
|
|
23
|
+
*/
|
|
24
|
+
export async function resolveXAccountId(args) {
|
|
25
|
+
const fromArgs = args["account-id"];
|
|
26
|
+
const accountId = fromArgs || getEnv().BAKER_X_ADS_ACCOUNT_ID;
|
|
27
|
+
if (accountId) {
|
|
28
|
+
if (!/^[a-z0-9]+$/.test(accountId)) {
|
|
29
|
+
writeAdsJson({
|
|
30
|
+
ok: false,
|
|
31
|
+
error: {
|
|
32
|
+
code: "INVALID_ACCOUNT_ID",
|
|
33
|
+
message: "X Ads account ID must be a base36 string (lowercase letters and digits). Pass --account-id or set BAKER_X_ADS_ACCOUNT_ID.",
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
return accountId;
|
|
39
|
+
}
|
|
40
|
+
const useCache = !args["no-cache"];
|
|
41
|
+
try {
|
|
42
|
+
const accounts = await fetchXAccounts(useCache);
|
|
43
|
+
const [single] = accounts;
|
|
44
|
+
if (accounts.length === 1 && single) {
|
|
45
|
+
process.stderr.write(`Using account "${single.name}" (${single.id})\n`);
|
|
46
|
+
return single.id;
|
|
47
|
+
}
|
|
48
|
+
if (accounts.length === 0) {
|
|
49
|
+
handleConnectionError("x_ads");
|
|
50
|
+
}
|
|
51
|
+
const list = accounts.map((a) => ` ${a.id} ${a.name}`).join("\n");
|
|
52
|
+
writeAdsJson({
|
|
53
|
+
ok: false,
|
|
54
|
+
error: {
|
|
55
|
+
code: "MULTIPLE_ACCOUNTS",
|
|
56
|
+
message: `Multiple X Ads accounts found. Pass --account-id or set BAKER_X_ADS_ACCOUNT_ID:\n${list}`,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
if (err instanceof ApiError && (err.code === "UNAUTHORIZED" || err.code === "NOT_FOUND")) {
|
|
63
|
+
handleConnectionError("x_ads", err.message);
|
|
64
|
+
}
|
|
65
|
+
writeAdsJson({
|
|
66
|
+
ok: false,
|
|
67
|
+
error: {
|
|
68
|
+
code: "INVALID_ACCOUNT_ID",
|
|
69
|
+
message: "Could not auto-detect account. Pass --account-id or set BAKER_X_ADS_ACCOUNT_ID.",
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../../src/commands/ads/x/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface XStatsPreset {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
entity: string;
|
|
5
|
+
metricGroups: string[];
|
|
6
|
+
granularity: "TOTAL" | "DAY" | "HOUR";
|
|
7
|
+
defaultDays: number;
|
|
8
|
+
placement: "ALL_ON_TWITTER" | "PUBLISHER_NETWORK";
|
|
9
|
+
}
|
|
10
|
+
export declare const X_STATS_PRESETS: XStatsPreset[];
|
|
11
|
+
export declare function getPreset(name: string): XStatsPreset | undefined;
|
|
12
|
+
/** Hour-aligned ISO 8601 string `daysAgo` days before now (UTC). */
|
|
13
|
+
export declare function isoHourFloor(daysAgo: number): string;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/x/presets.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,gBAAgB,GAAG,mBAAmB,CAAC;CACnD;AAED,eAAO,MAAM,eAAe,EAAE,YAAY,EA8CzC,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEhE;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOpD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const X_STATS_PRESETS = [
|
|
2
|
+
{
|
|
3
|
+
name: "campaign-engagement-7d",
|
|
4
|
+
description: "Campaign-level engagements + impressions over the last 7 days, daily granularity",
|
|
5
|
+
entity: "CAMPAIGN",
|
|
6
|
+
metricGroups: ["ENGAGEMENT"],
|
|
7
|
+
granularity: "DAY",
|
|
8
|
+
defaultDays: 7,
|
|
9
|
+
placement: "ALL_ON_TWITTER",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: "campaign-spend-30d",
|
|
13
|
+
description: "Campaign-level billed engagements + spend over the last 30 days, daily",
|
|
14
|
+
entity: "CAMPAIGN",
|
|
15
|
+
metricGroups: ["BILLING"],
|
|
16
|
+
granularity: "DAY",
|
|
17
|
+
defaultDays: 30,
|
|
18
|
+
placement: "ALL_ON_TWITTER",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "tweet-performance-7d",
|
|
22
|
+
description: "Promoted tweet engagement + media metrics over the last 7 days, daily",
|
|
23
|
+
entity: "PROMOTED_TWEET",
|
|
24
|
+
metricGroups: ["ENGAGEMENT", "MEDIA"],
|
|
25
|
+
granularity: "DAY",
|
|
26
|
+
defaultDays: 7,
|
|
27
|
+
placement: "ALL_ON_TWITTER",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "video-performance-30d",
|
|
31
|
+
description: "Promoted tweet video views/CTAs + engagement over the last 30 days, daily",
|
|
32
|
+
entity: "PROMOTED_TWEET",
|
|
33
|
+
metricGroups: ["VIDEO", "ENGAGEMENT"],
|
|
34
|
+
granularity: "DAY",
|
|
35
|
+
defaultDays: 30,
|
|
36
|
+
placement: "ALL_ON_TWITTER",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "line-item-conversions-30d",
|
|
40
|
+
description: "Line item web conversions + billing over the last 30 days, daily",
|
|
41
|
+
entity: "LINE_ITEM",
|
|
42
|
+
metricGroups: ["WEB_CONVERSION", "BILLING"],
|
|
43
|
+
granularity: "DAY",
|
|
44
|
+
defaultDays: 30,
|
|
45
|
+
placement: "ALL_ON_TWITTER",
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
export function getPreset(name) {
|
|
49
|
+
return X_STATS_PRESETS.find((p) => p.name === name);
|
|
50
|
+
}
|
|
51
|
+
/** Hour-aligned ISO 8601 string `daysAgo` days before now (UTC). */
|
|
52
|
+
export function isoHourFloor(daysAgo) {
|
|
53
|
+
const d = new Date();
|
|
54
|
+
d.setUTCMilliseconds(0);
|
|
55
|
+
d.setUTCSeconds(0);
|
|
56
|
+
d.setUTCMinutes(0);
|
|
57
|
+
d.setUTCDate(d.getUTCDate() - daysAgo);
|
|
58
|
+
return d.toISOString();
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../../src/commands/ads/x/presets.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,eAAe,GAAmB;IAC7C;QACE,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,kFAAkF;QAC/F,MAAM,EAAE,UAAU;QAClB,YAAY,EAAE,CAAC,YAAY,CAAC;QAC5B,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,gBAAgB;KAC5B;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,wEAAwE;QACrF,MAAM,EAAE,UAAU;QAClB,YAAY,EAAE,CAAC,SAAS,CAAC;QACzB,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,gBAAgB;KAC5B;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,uEAAuE;QACpF,MAAM,EAAE,gBAAgB;QACxB,YAAY,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC;QACrC,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,gBAAgB;KAC5B;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,2EAA2E;QACxF,MAAM,EAAE,gBAAgB;QACxB,YAAY,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC;QACrC,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,gBAAgB;KAC5B;IACD;QACE,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,kEAAkE;QAC/E,MAAM,EAAE,WAAW;QACnB,YAAY,EAAE,CAAC,gBAAgB,EAAE,SAAS,CAAC;QAC3C,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,gBAAgB;KAC5B;CACF,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACtD,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,OAAO,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const promotedTweetsCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly "account-id": {
|
|
3
|
+
readonly type: "string";
|
|
4
|
+
readonly description: "X Ads account ID";
|
|
5
|
+
readonly required: false;
|
|
6
|
+
};
|
|
7
|
+
readonly "line-item-ids": {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "CSV of line item IDs";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
readonly "with-deleted": {
|
|
13
|
+
readonly type: "boolean";
|
|
14
|
+
readonly description: "Include deleted";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
};
|
|
17
|
+
readonly "no-cache": {
|
|
18
|
+
readonly type: "boolean";
|
|
19
|
+
readonly description: "Skip cache";
|
|
20
|
+
readonly required: false;
|
|
21
|
+
};
|
|
22
|
+
readonly output: {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
readonly description: "Format: json|csv|md";
|
|
25
|
+
readonly required: false;
|
|
26
|
+
readonly default: "json";
|
|
27
|
+
};
|
|
28
|
+
}>;
|
|
29
|
+
//# sourceMappingURL=promoted-tweets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promoted-tweets.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/x/promoted-tweets.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoDhC,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { ApiError, apiGet } from "../../../client.js";
|
|
3
|
+
import { registerSchema } from "../../../schemas.js";
|
|
4
|
+
import { cacheGet, cacheSet } from "../cache.js";
|
|
5
|
+
import { writeAdsJson, writeAdsOutput } from "../output.js";
|
|
6
|
+
import { parseXApiError } from "./error-parser.js";
|
|
7
|
+
import { resolveXAccountId } from "./output.js";
|
|
8
|
+
registerSchema({
|
|
9
|
+
command: "ads.x.promotedTweets",
|
|
10
|
+
description: "List promoted tweets for an X Ads account. Returns id, line_item_id, tweet_id, approval_status. Filter by line-item-ids (CSV).",
|
|
11
|
+
args: {
|
|
12
|
+
"account-id": { type: "string", description: "X Ads account ID", required: false },
|
|
13
|
+
"line-item-ids": { type: "string", description: "CSV of line item IDs", required: false },
|
|
14
|
+
"with-deleted": { type: "boolean", description: "Include deleted", required: false },
|
|
15
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
export const promotedTweetsCommand = defineCommand({
|
|
19
|
+
meta: {
|
|
20
|
+
name: "promoted-tweets",
|
|
21
|
+
description: `List X Ads promoted tweets.
|
|
22
|
+
|
|
23
|
+
Examples:
|
|
24
|
+
baker ads x promoted-tweets --account-id 18ce53xyz --line-item-ids abc,def`,
|
|
25
|
+
},
|
|
26
|
+
args: {
|
|
27
|
+
"account-id": { type: "string", description: "X Ads account ID", required: false },
|
|
28
|
+
"line-item-ids": { type: "string", description: "CSV of line item IDs", required: false },
|
|
29
|
+
"with-deleted": { type: "boolean", description: "Include deleted", required: false },
|
|
30
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
31
|
+
output: { type: "string", description: "Format: json|csv|md", required: false, default: "json" },
|
|
32
|
+
},
|
|
33
|
+
run: async ({ args }) => {
|
|
34
|
+
const accountId = await resolveXAccountId(args);
|
|
35
|
+
const useCache = !args["no-cache"];
|
|
36
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
37
|
+
const cacheKey = `promoted-tweets:${accountId}:${today}:${args["line-item-ids"] ?? ""}:${args["with-deleted"] ? "1" : "0"}`;
|
|
38
|
+
if (useCache) {
|
|
39
|
+
const cached = cacheGet("x-account-data", cacheKey);
|
|
40
|
+
if (cached) {
|
|
41
|
+
writeAdsJson({ ok: true, data: cached.data, cached: true });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const params = { "account-id": accountId };
|
|
47
|
+
if (args["line-item-ids"])
|
|
48
|
+
params["line-item-ids"] = args["line-item-ids"];
|
|
49
|
+
if (args["with-deleted"])
|
|
50
|
+
params["with-deleted"] = "true";
|
|
51
|
+
if (!useCache)
|
|
52
|
+
params["skip-cache"] = "true";
|
|
53
|
+
const data = await apiGet("/api/ads/x/promoted-tweets", params);
|
|
54
|
+
if (useCache) {
|
|
55
|
+
cacheSet("x-account-data", cacheKey, data, 60 * 60 * 1000);
|
|
56
|
+
}
|
|
57
|
+
const format = args.output || "json";
|
|
58
|
+
if (format !== "json") {
|
|
59
|
+
writeAdsOutput(data, format);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
writeAdsJson({ ok: true, data });
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
if (err instanceof ApiError) {
|
|
66
|
+
writeAdsJson(parseXApiError(err.message, accountId));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=promoted-tweets.js.map
|