@koda-sl/baker-cli 0.557.0 → 0.558.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{account-reads-T6GTSAXE.js → account-reads-GQWTMLTY.js} +2 -2
- package/dist/{accounts-HJAQTVDA.js → accounts-ZFQYZT3J.js} +7 -2
- package/dist/accounts-ZFQYZT3J.js.map +1 -0
- package/dist/{ads-WWZK7UYG.js → ads-VYMFRGAC.js} +2 -2
- package/dist/{advertisers-FME2ABRB.js → advertisers-A3Q53R2S.js} +2 -2
- package/dist/{autocomplete-CBOYGT73.js → autocomplete-OOLUPUIJ.js} +2 -2
- package/dist/{changes-OIVPZJHE.js → changes-MVCX3GLE.js} +16 -11
- package/dist/changes-MVCX3GLE.js.map +1 -0
- package/dist/{chunk-JPK34QPS.js → chunk-2L24FULD.js} +3 -3
- package/dist/chunk-2L24FULD.js.map +1 -0
- package/dist/{chunk-PQ7RLE43.js → chunk-HNELOMY2.js} +26 -433
- package/dist/chunk-HNELOMY2.js.map +1 -0
- package/dist/chunk-NPGPRZW2.js +1313 -0
- package/dist/chunk-NPGPRZW2.js.map +1 -0
- package/dist/{chunk-SNWFM2DB.js → chunk-Q2JDS6WL.js} +11 -1
- package/dist/chunk-Q2JDS6WL.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/{conversion-upload-command-J2FIO74Y.js → conversion-upload-command-U36QYHUT.js} +2 -2
- package/dist/{currency-B5T7TYKD.js → currency-XFY2EX72.js} +3 -3
- package/dist/{discover-SS3PO5Y6.js → discover-J5344ATV.js} +2 -2
- package/dist/{draft-EB5ZFDVN.js → draft-OIGJUFOH.js} +2 -2
- package/dist/{forecast-XDRKCR65.js → forecast-HFCRTFIF.js} +2 -2
- package/dist/{google-UJ4YJGTJ.js → google-TOO3FDZ6.js} +22 -22
- package/dist/{intent-OMSJPOJZ.js → intent-PU3XUDLL.js} +2 -2
- package/dist/{keyword-gap-3P72T4NV.js → keyword-gap-B6T7ZFTZ.js} +2 -2
- package/dist/{keyword-metrics-DDY2RDYK.js → keyword-metrics-CXGNLERO.js} +2 -2
- package/dist/{keywords-for-site-TFHOM23P.js → keywords-for-site-OYMDRMMX.js} +2 -2
- package/dist/{languages-WWKMRZCH.js → languages-ETKG5WM3.js} +2 -2
- package/dist/{locations-P3CUBKYZ.js → locations-VPZYTFVK.js} +2 -2
- package/dist/{metrics-PSXIV4QS.js → metrics-J3WD2CUD.js} +2 -2
- package/dist/{query-PC7V3OFF.js → query-ZYG5RCCW.js} +5 -5
- package/dist/{relevant-pages-3CCAQA5Y.js → relevant-pages-7U6I2WPM.js} +2 -2
- package/dist/{research-M6LXE3VX.js → research-3BWJCS7N.js} +8 -8
- package/dist/{themes-BGBDYQQK.js → themes-C4PPU427.js} +2 -2
- package/dist/{url-options-GJ7ZIUPD.js → url-options-C3ZOWN2L.js} +3 -3
- package/package.json +1 -1
- package/dist/accounts-HJAQTVDA.js.map +0 -1
- package/dist/changes-OIVPZJHE.js.map +0 -1
- package/dist/chunk-6HPTF5YS.js +0 -857
- package/dist/chunk-6HPTF5YS.js.map +0 -1
- package/dist/chunk-JPK34QPS.js.map +0 -1
- package/dist/chunk-PQ7RLE43.js.map +0 -1
- package/dist/chunk-SNWFM2DB.js.map +0 -1
- /package/dist/{account-reads-T6GTSAXE.js.map → account-reads-GQWTMLTY.js.map} +0 -0
- /package/dist/{ads-WWZK7UYG.js.map → ads-VYMFRGAC.js.map} +0 -0
- /package/dist/{advertisers-FME2ABRB.js.map → advertisers-A3Q53R2S.js.map} +0 -0
- /package/dist/{autocomplete-CBOYGT73.js.map → autocomplete-OOLUPUIJ.js.map} +0 -0
- /package/dist/{conversion-upload-command-J2FIO74Y.js.map → conversion-upload-command-U36QYHUT.js.map} +0 -0
- /package/dist/{currency-B5T7TYKD.js.map → currency-XFY2EX72.js.map} +0 -0
- /package/dist/{discover-SS3PO5Y6.js.map → discover-J5344ATV.js.map} +0 -0
- /package/dist/{draft-EB5ZFDVN.js.map → draft-OIGJUFOH.js.map} +0 -0
- /package/dist/{forecast-XDRKCR65.js.map → forecast-HFCRTFIF.js.map} +0 -0
- /package/dist/{google-UJ4YJGTJ.js.map → google-TOO3FDZ6.js.map} +0 -0
- /package/dist/{intent-OMSJPOJZ.js.map → intent-PU3XUDLL.js.map} +0 -0
- /package/dist/{keyword-gap-3P72T4NV.js.map → keyword-gap-B6T7ZFTZ.js.map} +0 -0
- /package/dist/{keyword-metrics-DDY2RDYK.js.map → keyword-metrics-CXGNLERO.js.map} +0 -0
- /package/dist/{keywords-for-site-TFHOM23P.js.map → keywords-for-site-OYMDRMMX.js.map} +0 -0
- /package/dist/{languages-WWKMRZCH.js.map → languages-ETKG5WM3.js.map} +0 -0
- /package/dist/{locations-P3CUBKYZ.js.map → locations-VPZYTFVK.js.map} +0 -0
- /package/dist/{metrics-PSXIV4QS.js.map → metrics-J3WD2CUD.js.map} +0 -0
- /package/dist/{query-PC7V3OFF.js.map → query-ZYG5RCCW.js.map} +0 -0
- /package/dist/{relevant-pages-3CCAQA5Y.js.map → relevant-pages-7U6I2WPM.js.map} +0 -0
- /package/dist/{research-M6LXE3VX.js.map → research-3BWJCS7N.js.map} +0 -0
- /package/dist/{themes-BGBDYQQK.js.map → themes-C4PPU427.js.map} +0 -0
- /package/dist/{url-options-GJ7ZIUPD.js.map → url-options-C3ZOWN2L.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import "./chunk-4NZ47VXO.js";
|
|
|
12
12
|
import "./chunk-D5FY4FAK.js";
|
|
13
13
|
import "./chunk-4H6XLX7E.js";
|
|
14
14
|
import "./chunk-QALAJNBG.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-Q2JDS6WL.js";
|
|
16
16
|
import {
|
|
17
17
|
getManagerIdForCustomer,
|
|
18
18
|
writeJsonEnvelope
|
|
@@ -216,4 +216,4 @@ export {
|
|
|
216
216
|
invoicesCommand,
|
|
217
217
|
previewsCommand
|
|
218
218
|
};
|
|
219
|
-
//# sourceMappingURL=account-reads-
|
|
219
|
+
//# sourceMappingURL=account-reads-GQWTMLTY.js.map
|
|
@@ -5,6 +5,10 @@ import {
|
|
|
5
5
|
AVAILABLE_ARG,
|
|
6
6
|
writeAvailableAccounts
|
|
7
7
|
} from "./chunk-ZU6JW3ZB.js";
|
|
8
|
+
import {
|
|
9
|
+
serverFailure
|
|
10
|
+
} from "./chunk-NPGPRZW2.js";
|
|
11
|
+
import "./chunk-Q2JDS6WL.js";
|
|
8
12
|
import {
|
|
9
13
|
cacheGet,
|
|
10
14
|
cacheSet,
|
|
@@ -14,6 +18,7 @@ import {
|
|
|
14
18
|
writeAdsOutput,
|
|
15
19
|
writeJsonEnvelope
|
|
16
20
|
} from "./chunk-QYH2UZAK.js";
|
|
21
|
+
import "./chunk-MSMTG6OC.js";
|
|
17
22
|
import {
|
|
18
23
|
ApiError,
|
|
19
24
|
apiGet
|
|
@@ -49,7 +54,7 @@ function handleAccountsError(err) {
|
|
|
49
54
|
if (needsConnectionFix(err.code, err.message)) {
|
|
50
55
|
handleConnectionError("google_ads", err.message);
|
|
51
56
|
}
|
|
52
|
-
const envelope = {
|
|
57
|
+
const envelope = serverFailure(err.code, err.message) ?? {
|
|
53
58
|
ok: false,
|
|
54
59
|
error: {
|
|
55
60
|
code: err.code,
|
|
@@ -111,4 +116,4 @@ Examples:
|
|
|
111
116
|
export {
|
|
112
117
|
accountsCommand
|
|
113
118
|
};
|
|
114
|
-
//# sourceMappingURL=accounts-
|
|
119
|
+
//# sourceMappingURL=accounts-ZFQYZT3J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/google/accounts.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { AVAILABLE_ARG, writeAvailableAccounts } from \"../../../available-accounts.ts\";\nimport { ApiError, apiGet } from \"../../../client.ts\";\nimport { connectedResourceHints } from \"../../../connected-resources.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { cacheGet, cacheSet } from \"../cache.ts\";\nimport { writeAdsJson, writeAdsOutput, writeJsonEnvelope } from \"../output.ts\";\nimport type { AdsErrorEnvelope } from \"../types.ts\";\nimport { serverFailure } from \"./error-parser.ts\";\n\nregisterSchema({\n command: \"ads.google.accounts\",\n description:\n \"List the Google Ads accounts this company connected — there can be several, and every one of them is yours to work in. Returns accounts with id, name, access_type (direct or managed), level in the hierarchy, and optional manager_id for managed accounts. Run this first to find account IDs for other commands.\",\n args: {\n \"no-cache\": { type: \"boolean\", description: \"Skip cache, hit API directly\", required: false },\n output: { type: \"string\", description: \"Format: json|csv|md\", required: false, default: \"json\" },\n available: AVAILABLE_ARG,\n },\n});\n\ninterface AccountInfo {\n id: string;\n name: string;\n access_type: \"direct\" | \"managed\";\n level: number;\n manager_id?: string;\n}\n\nimport { handleConnectionError, needsConnectionFix } from \"../../../error-handler.ts\";\n\nfunction accountHints(accounts: AccountInfo[]): string[] {\n return connectedResourceHints({\n plural: \"Google Ads accounts\",\n singular: \"Google Ads account\",\n flag: \"--customer-id\",\n resources: accounts.map((account) => ({ id: account.id, label: account.name })),\n });\n}\n\nfunction handleAccountsError(err: unknown): never {\n if (err instanceof ApiError) {\n if (needsConnectionFix(err.code, err.message)) {\n handleConnectionError(\"google_ads\", err.message);\n }\n const envelope: AdsErrorEnvelope = serverFailure(err.code, err.message) ?? {\n ok: false,\n error: {\n code: err.code,\n message: err.message,\n fix: {\n action: \"reject\",\n explanation: err.message,\n },\n retryable: false,\n },\n };\n writeAdsJson(envelope);\n process.exit(1);\n }\n writeAdsJson({ ok: false, error: { code: \"NETWORK_ERROR\", message: \"Unexpected error\" } });\n process.exit(1);\n}\n\nexport const accountsCommand = defineCommand({\n meta: {\n name: \"accounts\",\n description: `List accessible Google Ads accounts. Returns customer IDs needed for all other commands.\n\nExamples:\n baker ads google accounts\n baker ads google accounts --available # every account the login reaches, selected or not`,\n },\n args: {\n \"no-cache\": { type: \"boolean\", description: \"Skip cache\", required: false },\n output: { type: \"string\", description: \"Format: json|csv|md\", required: false, default: \"json\" },\n available: AVAILABLE_ARG,\n },\n run: async ({ args }) => {\n if (args.available) return writeAvailableAccounts(\"google-ads\", handleAccountsError);\n const useCache = !args[\"no-cache\"];\n\n if (useCache) {\n const cached = cacheGet<AccountInfo[]>(\"accounts\", \"list\");\n if (cached) {\n writeJsonEnvelope({ ok: true, data: cached.data, cached: true, hints: accountHints(cached.data) });\n return;\n }\n }\n\n try {\n const params = !useCache ? { \"skip-cache\": \"true\" } : undefined;\n const data = await apiGet<AccountInfo[]>(\"/api/ads/google/accounts\", params);\n if (useCache) {\n cacheSet(\"accounts\", \"list\", data, 60 * 60 * 1000);\n }\n const format = (args.output as string) || \"json\";\n if (format !== \"json\") {\n writeAdsOutput(data as unknown as Array<Record<string, unknown>>, format);\n return;\n }\n writeJsonEnvelope({ ok: true, data, hints: accountHints(data) });\n } catch (err) {\n handleAccountsError(err);\n }\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;AAU9B,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,YAAY,EAAE,MAAM,WAAW,aAAa,gCAAgC,UAAU,MAAM;AAAA,IAC5F,QAAQ,EAAE,MAAM,UAAU,aAAa,uBAAuB,UAAU,OAAO,SAAS,OAAO;AAAA,IAC/F,WAAW;AAAA,EACb;AACF,CAAC;AAYD,SAAS,aAAa,UAAmC;AACvD,SAAO,uBAAuB;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,MAAM;AAAA,IACN,WAAW,SAAS,IAAI,CAAC,aAAa,EAAE,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,EAAE;AAAA,EAChF,CAAC;AACH;AAEA,SAAS,oBAAoB,KAAqB;AAChD,MAAI,eAAe,UAAU;AAC3B,QAAI,mBAAmB,IAAI,MAAM,IAAI,OAAO,GAAG;AAC7C,4BAAsB,cAAc,IAAI,OAAO;AAAA,IACjD;AACA,UAAM,WAA6B,cAAc,IAAI,MAAM,IAAI,OAAO,KAAK;AAAA,MACzE,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM,IAAI;AAAA,QACV,SAAS,IAAI;AAAA,QACb,KAAK;AAAA,UACH,QAAQ;AAAA,UACR,aAAa,IAAI;AAAA,QACnB;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF;AACA,iBAAa,QAAQ;AACrB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,eAAa,EAAE,IAAI,OAAO,OAAO,EAAE,MAAM,iBAAiB,SAAS,mBAAmB,EAAE,CAAC;AACzF,UAAQ,KAAK,CAAC;AAChB;AAEO,IAAM,kBAAkB,cAAc;AAAA,EAC3C,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf;AAAA,EACA,MAAM;AAAA,IACJ,YAAY,EAAE,MAAM,WAAW,aAAa,cAAc,UAAU,MAAM;AAAA,IAC1E,QAAQ,EAAE,MAAM,UAAU,aAAa,uBAAuB,UAAU,OAAO,SAAS,OAAO;AAAA,IAC/F,WAAW;AAAA,EACb;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AACvB,QAAI,KAAK,UAAW,QAAO,uBAAuB,cAAc,mBAAmB;AACnF,UAAM,WAAW,CAAC,KAAK,UAAU;AAEjC,QAAI,UAAU;AACZ,YAAM,SAAS,SAAwB,YAAY,MAAM;AACzD,UAAI,QAAQ;AACV,0BAAkB,EAAE,IAAI,MAAM,MAAM,OAAO,MAAM,QAAQ,MAAM,OAAO,aAAa,OAAO,IAAI,EAAE,CAAC;AACjG;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,CAAC,WAAW,EAAE,cAAc,OAAO,IAAI;AACtD,YAAM,OAAO,MAAM,OAAsB,4BAA4B,MAAM;AAC3E,UAAI,UAAU;AACZ,iBAAS,YAAY,QAAQ,MAAM,KAAK,KAAK,GAAI;AAAA,MACnD;AACA,YAAM,SAAU,KAAK,UAAqB;AAC1C,UAAI,WAAW,QAAQ;AACrB,uBAAe,MAAmD,MAAM;AACxE;AAAA,MACF;AACA,wBAAkB,EAAE,IAAI,MAAM,MAAM,OAAO,aAAa,IAAI,EAAE,CAAC;AAAA,IACjE,SAAS,KAAK;AACZ,0BAAoB,GAAG;AAAA,IACzB;AAAA,EACF;AACF,CAAC;","names":[]}
|
|
@@ -33,7 +33,7 @@ Examples:
|
|
|
33
33
|
Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedin|x|chatgpt|performance|terms)`
|
|
34
34
|
},
|
|
35
35
|
subCommands: {
|
|
36
|
-
google: () => import("./google-
|
|
36
|
+
google: () => import("./google-TOO3FDZ6.js").then((m) => m.googleCommand),
|
|
37
37
|
meta: () => import("./meta-XUHI3E3L.js").then((m) => m.metaCommand),
|
|
38
38
|
linkedin: () => import("./linkedin-6NRMXGBT.js").then((m) => m.linkedinCommand),
|
|
39
39
|
x: () => import("./x-QX4JZDM4.js").then((m) => m.xCommand),
|
|
@@ -45,4 +45,4 @@ Full guides: __tooling__/docs/tools/baker/ads-<platform>.md (google|meta|linkedi
|
|
|
45
45
|
export {
|
|
46
46
|
adsCommand
|
|
47
47
|
};
|
|
48
|
-
//# sourceMappingURL=ads-
|
|
48
|
+
//# sourceMappingURL=ads-VYMFRGAC.js.map
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
buildResearchQueryContext,
|
|
13
13
|
warnDefaults
|
|
14
14
|
} from "./chunk-FVDC6AKZ.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-Q2JDS6WL.js";
|
|
16
16
|
import "./chunk-MVTPNWRQ.js";
|
|
17
17
|
import "./chunk-QV6AST5T.js";
|
|
18
18
|
import "./chunk-WCU362Z6.js";
|
|
@@ -120,4 +120,4 @@ Examples:
|
|
|
120
120
|
export {
|
|
121
121
|
advertisersCommand
|
|
122
122
|
};
|
|
123
|
-
//# sourceMappingURL=advertisers-
|
|
123
|
+
//# sourceMappingURL=advertisers-A3Q53R2S.js.map
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
buildResearchQueryContext,
|
|
13
13
|
warnDefaults
|
|
14
14
|
} from "./chunk-FVDC6AKZ.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-Q2JDS6WL.js";
|
|
16
16
|
import "./chunk-MVTPNWRQ.js";
|
|
17
17
|
import "./chunk-QV6AST5T.js";
|
|
18
18
|
import "./chunk-WCU362Z6.js";
|
|
@@ -111,4 +111,4 @@ Examples:
|
|
|
111
111
|
export {
|
|
112
112
|
autocompleteCommand
|
|
113
113
|
};
|
|
114
|
-
//# sourceMappingURL=autocomplete-
|
|
114
|
+
//# sourceMappingURL=autocomplete-OOLUPUIJ.js.map
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getFieldDescriptions
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2L24FULD.js";
|
|
4
4
|
import {
|
|
5
5
|
cappedChangesHint,
|
|
6
6
|
parseApiError,
|
|
7
7
|
resolveChangesWindow
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NPGPRZW2.js";
|
|
9
9
|
import {
|
|
10
|
+
CHANGES_MAX_LIMIT,
|
|
11
|
+
CHANGE_RESOURCE_TYPES,
|
|
10
12
|
CHANGE_SCOPE_MAX_DAYS,
|
|
11
13
|
DEFAULT_CHANGE_DAYS
|
|
12
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-Q2JDS6WL.js";
|
|
13
15
|
import {
|
|
14
16
|
getManagerIdForCustomer,
|
|
15
17
|
resolveCustomerId,
|
|
@@ -54,12 +56,12 @@ registerSchema({
|
|
|
54
56
|
},
|
|
55
57
|
"resource-type": {
|
|
56
58
|
type: "string",
|
|
57
|
-
description:
|
|
59
|
+
description: `Filter by type: ${CHANGE_RESOURCE_TYPES.join(", ")}. CAMPAIGN_CRITERION covers campaign-level negatives, location and audience exclusions.`,
|
|
58
60
|
required: false
|
|
59
61
|
},
|
|
60
62
|
limit: {
|
|
61
63
|
type: "string",
|
|
62
|
-
description:
|
|
64
|
+
description: `Max change events (default: 50, max: ${CHANGES_MAX_LIMIT}). A read that comes back exactly this full has older changes behind it, and a hint says so.`,
|
|
63
65
|
required: false,
|
|
64
66
|
default: 50
|
|
65
67
|
},
|
|
@@ -88,27 +90,30 @@ Examples:
|
|
|
88
90
|
"customer-id": { type: "string", description: "Google Ads customer ID", required: false },
|
|
89
91
|
days: { type: "string", description: `Lookback days (default ${DEFAULT_CHANGE_DAYS})`, required: false },
|
|
90
92
|
scope: { type: "string", description: "detail (30 days) or summary (90 days)", required: false },
|
|
91
|
-
"resource-type": { type: "string", description:
|
|
92
|
-
limit: { type: "string", description:
|
|
93
|
+
"resource-type": { type: "string", description: `One of ${CHANGE_RESOURCE_TYPES.join(", ")}`, required: false },
|
|
94
|
+
limit: { type: "string", description: `Max results (default 50, max ${CHANGES_MAX_LIMIT})`, required: false },
|
|
93
95
|
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false },
|
|
94
96
|
output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" }
|
|
95
97
|
},
|
|
96
98
|
run: async ({ args }) => {
|
|
97
99
|
const customerId = await resolveCustomerId(args);
|
|
100
|
+
const limit = args.limit ? Number(args.limit) : 50;
|
|
101
|
+
const resourceType = args["resource-type"];
|
|
98
102
|
const window = resolveChangesWindow({
|
|
99
103
|
days: args.days ? Number(args.days) : void 0,
|
|
100
|
-
scope: args.scope
|
|
104
|
+
scope: args.scope,
|
|
105
|
+
limit,
|
|
106
|
+
resourceType
|
|
101
107
|
});
|
|
102
108
|
if (!window.ok) {
|
|
103
109
|
writeJsonEnvelope({ ok: false, error: { ...window.error, retryable: false } });
|
|
104
110
|
process.exit(1);
|
|
105
111
|
return;
|
|
106
112
|
}
|
|
107
|
-
const limit = args.limit ? Number(args.limit) : 50;
|
|
108
113
|
const body = { customerId, days: window.days, scope: window.scope, limit };
|
|
109
114
|
const managerId = getManagerIdForCustomer(customerId);
|
|
110
115
|
if (managerId) body.managerId = managerId;
|
|
111
|
-
if (
|
|
116
|
+
if (resourceType) body.resourceType = resourceType;
|
|
112
117
|
if (args["no-cache"]) body.skipCache = true;
|
|
113
118
|
try {
|
|
114
119
|
const data = await apiPost("/api/ads/google/changes", body);
|
|
@@ -140,4 +145,4 @@ Examples:
|
|
|
140
145
|
export {
|
|
141
146
|
changesCommand
|
|
142
147
|
};
|
|
143
|
-
//# sourceMappingURL=changes-
|
|
148
|
+
//# sourceMappingURL=changes-MVCX3GLE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/google/changes.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { ApiError, apiPost } from \"../../../client.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { getManagerIdForCustomer } from \"../cache.ts\";\nimport { getFieldDescriptions } from \"../field-descriptions.ts\";\nimport { resolveCustomerId, writeAdsJson, writeAdsOutput, writeJsonEnvelope } from \"../output.ts\";\nimport {\n CHANGE_RESOURCE_TYPES,\n CHANGE_SCOPE_MAX_DAYS,\n CHANGES_MAX_LIMIT,\n cappedChangesHint,\n DEFAULT_CHANGE_DAYS,\n resolveChangesWindow,\n} from \"./changes-window.ts\";\nimport { parseApiError } from \"./error-parser.ts\";\n\nregisterSchema({\n command: \"ads.google.changes\",\n description:\n \"Read the account's change history. --scope detail (default) shows what changed and to what value, back 30 days; --scope summary shows which resources changed, back 90 days.\",\n args: {\n \"customer-id\": {\n type: \"string\",\n description: \"Google Ads customer ID (10 digits, no dashes). Falls back to BAKER_GOOGLE_ADS_CUSTOMER_ID env var.\",\n required: false,\n },\n days: {\n type: \"string\",\n description: `Lookback days (default: ${DEFAULT_CHANGE_DAYS}). Max ${CHANGE_SCOPE_MAX_DAYS.detail} with --scope detail, ${CHANGE_SCOPE_MAX_DAYS.summary} with --scope summary. Google keeps nothing older behind any API.`,\n required: false,\n default: DEFAULT_CHANGE_DAYS,\n },\n scope: {\n type: \"string\",\n description: `detail|summary (default: detail). detail = old/new values plus who made the change, ${CHANGE_SCOPE_MAX_DAYS.detail} days. summary = which resources were added, changed or removed, ${CHANGE_SCOPE_MAX_DAYS.summary} days, without values.`,\n required: false,\n default: \"detail\",\n },\n \"resource-type\": {\n type: \"string\",\n description: `Filter by type: ${CHANGE_RESOURCE_TYPES.join(\", \")}. CAMPAIGN_CRITERION covers campaign-level negatives, location and audience exclusions.`,\n required: false,\n },\n limit: {\n type: \"string\",\n description: `Max change events (default: 50, max: ${CHANGES_MAX_LIMIT}). A read that comes back exactly this full has older changes behind it, and a hint says so.`,\n required: false,\n default: 50,\n },\n output: { type: \"string\", description: \"Format: json|csv|jsonl|md\", required: false, default: \"json\" },\n \"no-cache\": { type: \"boolean\", description: \"Skip cache, hit API directly\", required: false },\n },\n});\n\nexport const changesCommand = defineCommand({\n meta: {\n name: \"changes\",\n description: `Read the change history of a Google Ads account.\n\nGoogle keeps account history in two layers, and neither reaches past 90 days:\n --scope detail (default) what changed, old → new value, who changed it — last ${CHANGE_SCOPE_MAX_DAYS.detail} days\n --scope summary which resources were added, changed or removed — last ${CHANGE_SCOPE_MAX_DAYS.summary} days\n\nFor anything older, infer it from performance instead — a monthly spend trend per\ncampaign shows what started or stopped, just not who did it.\n\nExamples:\n baker ads google changes --customer-id 1234567890\n baker ads google changes --customer-id 1234567890 --days 14 --resource-type CAMPAIGN\n baker ads google changes --customer-id 1234567890 --days 60 --scope summary`,\n },\n args: {\n \"customer-id\": { type: \"string\", description: \"Google Ads customer ID\", required: false },\n days: { type: \"string\", description: `Lookback days (default ${DEFAULT_CHANGE_DAYS})`, required: false },\n scope: { type: \"string\", description: \"detail (30 days) or summary (90 days)\", required: false },\n \"resource-type\": { type: \"string\", description: `One of ${CHANGE_RESOURCE_TYPES.join(\", \")}`, required: false },\n limit: { type: \"string\", description: `Max results (default 50, max ${CHANGES_MAX_LIMIT})`, required: false },\n \"no-cache\": { type: \"boolean\", description: \"Skip cache, hit API directly\", required: false },\n output: { type: \"string\", description: \"Format: json|csv|jsonl|md\", required: false, default: \"json\" },\n },\n run: async ({ args }) => {\n const customerId = await resolveCustomerId(args);\n\n const limit = args.limit ? Number(args.limit) : 50;\n const resourceType = args[\"resource-type\"] as string | undefined;\n const window = resolveChangesWindow({\n days: args.days ? Number(args.days) : undefined,\n scope: args.scope as string | undefined,\n limit,\n resourceType,\n });\n if (!window.ok) {\n writeJsonEnvelope({ ok: false, error: { ...window.error, retryable: false } });\n process.exit(1);\n return;\n }\n\n const body: Record<string, unknown> = { customerId, days: window.days, scope: window.scope, limit };\n const managerId = getManagerIdForCustomer(customerId);\n if (managerId) body.managerId = managerId;\n if (resourceType) body.resourceType = resourceType;\n if (args[\"no-cache\"]) body.skipCache = true;\n\n try {\n const data = await apiPost<Array<Record<string, unknown>>>(\"/api/ads/google/changes\", body);\n const format = (args.output as string) || \"json\";\n const capped = cappedChangesHint(data, limit, window.days);\n\n if (format !== \"json\") {\n writeAdsOutput(data, format, undefined, capped ? [capped] : []);\n return;\n }\n\n const first = data[0];\n const fields = first ? Object.keys(first) : [];\n const fieldDescs = getFieldDescriptions(fields);\n writeJsonEnvelope({\n ok: true,\n data,\n fields: fieldDescs,\n hints: capped ? [capped, ...window.hints] : window.hints,\n });\n } catch (err) {\n if (err instanceof ApiError) {\n writeAdsJson(parseApiError(err.message, \"\", customerId, err.code));\n process.exit(1);\n }\n writeAdsJson({ ok: false, error: { code: \"NETWORK_ERROR\", message: \"Unexpected error\" } });\n process.exit(1);\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -19,8 +19,8 @@ var FIELD_DESCRIPTIONS = {
|
|
|
19
19
|
"campaign.maximize_conversion_value.target_roas": "Target ROAS as a ratio when held inside a Maximize Conversion Value strategy",
|
|
20
20
|
"campaign.target_cpc.target_cpc_micros": "Target CPC in micros on a Demand Gen Target CPC strategy. Governed by the same August 2026 change as Target CPA/ROAS: on a budget-limited campaign it is what delivery moves toward, not a ceiling.",
|
|
21
21
|
"ad_group.target_cpc_micros": "Ad-group override of the campaign's Demand Gen target CPC, in micros",
|
|
22
|
-
"campaign.
|
|
23
|
-
"campaign.
|
|
22
|
+
"campaign.start_date_time": "Campaign start, in the account's time zone (YYYY-MM-DD HH:MM:SS)",
|
|
23
|
+
"campaign.end_date_time": "Campaign end, in the account's time zone (YYYY-MM-DD HH:MM:SS); blank if ongoing",
|
|
24
24
|
// Campaign budget
|
|
25
25
|
"campaign_budget.amount_micros": "Daily budget in micros (\xF7 1,000,000 for actual currency)",
|
|
26
26
|
// Ad group
|
|
@@ -131,4 +131,4 @@ function getFieldDescriptions(fields) {
|
|
|
131
131
|
export {
|
|
132
132
|
getFieldDescriptions
|
|
133
133
|
};
|
|
134
|
-
//# sourceMappingURL=chunk-
|
|
134
|
+
//# sourceMappingURL=chunk-2L24FULD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/ads/field-descriptions.ts"],"sourcesContent":["const FIELD_DESCRIPTIONS: Record<string, string> = {\n // Customer\n \"customer.id\": \"Google Ads account ID\",\n \"customer.descriptive_name\": \"Account display name\",\n \"customer.currency_code\": \"Account currency (e.g. USD, EUR)\",\n \"customer.time_zone\": \"Account timezone (e.g. America/New_York)\",\n\n // Campaign\n \"campaign.id\": \"Unique campaign identifier\",\n \"campaign.name\": \"Campaign display name\",\n \"campaign.status\": \"ENABLED, PAUSED, or REMOVED\",\n \"campaign.advertising_channel_type\": \"Campaign type: SEARCH, DISPLAY, SHOPPING, VIDEO, PERFORMANCE_MAX, DEMAND_GEN\",\n \"campaign.bidding_strategy_type\": \"Bidding strategy (TARGET_CPA, TARGET_ROAS, MAXIMIZE_CONVERSIONS, etc.)\",\n \"campaign.primary_status\":\n \"Whether the campaign can serve: ELIGIBLE, PAUSED, REMOVED, ENDED, PENDING, MISCONFIGURED, LIMITED, LEARNING, NOT_ELIGIBLE. Unlike the keyword equivalent, LIMITED is a real value here — but Google publishes no reason-to-status mapping, so decide 'Limited by budget' from primary_status_reasons, not from this field.\",\n \"campaign.primary_status_reasons\":\n \"Why the campaign is limited or not serving (repeated field — an array). BUDGET_CONSTRAINED is 'Limited by budget'; BUDGET_MISCONFIGURED is a broken budget setting, not a cap. Since 17 Aug 2026 a budget-limited campaign on a target-based strategy delivers toward its target instead of toward its recent actual cost, so BUDGET_CONSTRAINED is the flag that says a target above actual now costs money. BIDDING_STRATEGY_LEARNING means the bidding system is still adjusting to a change.\",\n \"campaign.target_cpa.target_cpa_micros\": \"Target CPA in micros on a standalone Target CPA strategy\",\n \"campaign.maximize_conversions.target_cpa_micros\":\n \"Target CPA in micros when the target is held inside a Maximize Conversions strategy — the shape Google uses on Search\",\n \"campaign.target_roas.target_roas\": \"Target ROAS as a ratio (2.5 = 250%) on a standalone Target ROAS strategy\",\n \"campaign.maximize_conversion_value.target_roas\":\n \"Target ROAS as a ratio when held inside a Maximize Conversion Value strategy\",\n \"campaign.target_cpc.target_cpc_micros\":\n \"Target CPC in micros on a Demand Gen Target CPC strategy. Governed by the same August 2026 change as Target CPA/ROAS: on a budget-limited campaign it is what delivery moves toward, not a ceiling.\",\n \"ad_group.target_cpc_micros\": \"Ad-group override of the campaign's Demand Gen target CPC, in micros\",\n \"campaign.start_date_time\": \"Campaign start, in the account's time zone (YYYY-MM-DD HH:MM:SS)\",\n \"campaign.end_date_time\": \"Campaign end, in the account's time zone (YYYY-MM-DD HH:MM:SS); blank if ongoing\",\n\n // Campaign budget\n \"campaign_budget.amount_micros\": \"Daily budget in micros (÷ 1,000,000 for actual currency)\",\n\n // Ad group\n \"ad_group.id\": \"Unique ad group identifier\",\n \"ad_group.name\": \"Ad group display name\",\n \"ad_group.status\": \"ENABLED, PAUSED, or REMOVED\",\n \"ad_group.type\": \"Ad group type (SEARCH_STANDARD, DISPLAY_STANDARD, etc.)\",\n\n // Ad group ad\n \"ad_group_ad.ad.id\": \"Unique ad identifier\",\n \"ad_group_ad.ad.final_urls\": \"Landing page URLs (array)\",\n \"ad_group_ad.ad.type\": \"Ad format (RESPONSIVE_SEARCH_AD, etc.)\",\n \"ad_group_ad.status\": \"ENABLED, PAUSED, or REMOVED\",\n \"ad_group_ad.ad.responsive_search_ad.headlines\": \"Ad headline variations (array)\",\n \"ad_group_ad.ad.responsive_search_ad.descriptions\": \"Ad description variations (array)\",\n\n // Keywords\n \"ad_group_criterion.criterion_id\":\n \"Keyword criterion id — derived from text + match type, so every copy of the same keyword across ad groups shares it. Pair with ad_group.id to identify one copy (writes take customers/<cid>/adGroupCriteria/<adGroupId>~<criterionId>)\",\n \"ad_group_criterion.keyword.text\": \"The keyword text\",\n \"ad_group_criterion.keyword.match_type\": \"EXACT, PHRASE, or BROAD\",\n \"ad_group_criterion.status\": \"ENABLED, PAUSED, or REMOVED\",\n \"ad_group_criterion.quality_info.quality_score\": \"Quality score 1-10 (higher is better)\",\n \"ad_group_criterion.quality_info.creative_quality_score\":\n \"Ad relevance bucket: ABOVE_AVERAGE, AVERAGE, BELOW_AVERAGE\",\n \"ad_group_criterion.quality_info.post_click_quality_score\":\n \"Landing page experience bucket: ABOVE_AVERAGE, AVERAGE, BELOW_AVERAGE\",\n \"ad_group_criterion.quality_info.search_predicted_ctr\":\n \"Expected click-through rate bucket: ABOVE_AVERAGE, AVERAGE, BELOW_AVERAGE\",\n \"ad_group_criterion.primary_status\":\n \"Whether the keyword can serve: ELIGIBLE, PAUSED, REMOVED, PENDING, NOT_ELIGIBLE. There is no LIMITED value — Google Ads' 'Eligible (Limited)' is ELIGIBLE plus a limiting entry in primary_status_reasons, so read both.\",\n \"ad_group_criterion.primary_status_reasons\":\n \"Why the keyword is in that status (array). AD_GROUP_CRITERION_BELOW_FIRST_PAGE_BID and AD_GROUP_CRITERION_LOW_QUALITY are the two that render as '(Limited)'; the CAMPAIGN_*/AD_GROUP_* entries just restate a paused or removed parent.\",\n \"ad_group_criterion.system_serving_status\": \"ELIGIBLE or RARELY_SERVED (too few searches to show)\",\n \"ad_group_criterion.approval_status\": \"Ad-approval state: APPROVED, DISAPPROVED, PENDING_REVIEW, UNDER_REVIEW\",\n \"ad_group_criterion.disapproval_reasons\": \"Policy reasons the keyword was disapproved (array)\",\n \"ad_group_criterion.cpc_bid_micros\": \"Max CPC bid set on this keyword, in micros (÷ 1,000,000)\",\n \"ad_group_criterion.effective_cpc_bid_micros\":\n \"Max CPC actually in force, in micros (÷ 1,000,000) — the keyword's own bid, or the ad group's when the keyword has none\",\n \"ad_group_criterion.effective_cpc_bid_source\":\n \"Where the effective max CPC comes from: ADGROUP, CRITERION, or CAMPAIGN_BIDDING_STRATEGY\",\n \"ad_group_criterion.position_estimates.first_page_cpc_micros\":\n \"Bid estimated to reach the first page of results, in micros (÷ 1,000,000). The number in Google Ads' 'Below first page bid (€3.63)' label — compare it against effective_cpc_bid_micros.\",\n \"ad_group_criterion.position_estimates.top_of_page_cpc_micros\":\n \"Bid estimated to reach the top of the first page, in micros (÷ 1,000,000)\",\n \"ad_group_criterion.position_estimates.first_position_cpc_micros\":\n \"Bid estimated to reach the first ad position, in micros (÷ 1,000,000)\",\n\n // Search terms\n \"search_term_view.search_term\": \"Actual user search query that triggered the ad\",\n \"search_term_view.status\": \"Whether the search term is added, excluded, or none\",\n\n // Metrics\n \"metrics.impressions\": \"Times ads were shown (integer)\",\n \"metrics.clicks\": \"Total clicks (integer)\",\n \"metrics.cost_micros\":\n \"Total cost in micros (÷ 1,000,000 for actual currency). Use 'currency' command for account currency.\",\n \"metrics.cost\": \"Total cost in actual currency (already converted from micros)\",\n \"metrics.conversions\": \"Conversion count (can be fractional from attribution models)\",\n \"metrics.conversions_value\": \"Revenue from conversions in actual currency\",\n \"metrics.all_conversions\": \"All conversions including view-through\",\n \"metrics.all_conversions_value\": \"Total attributed revenue including view-through\",\n \"metrics.ctr\": \"Click-through rate as decimal (0.05 = 5%)\",\n \"metrics.average_cpc\": \"Average cost per click in micros (÷ 1,000,000)\",\n \"metrics.average_cpm\": \"Average cost per 1000 impressions in micros (÷ 1,000,000)\",\n \"metrics.search_impression_share\": \"Impression share as decimal (0.0–1.0)\",\n \"metrics.search_budget_lost_impression_share\":\n \"Share of impressions lost because the budget ran out, as a decimal (0.0–1.0). The corroborating signal for a 'Limited by budget' campaign — a high value here alongside a target above actual cost per conversion is the combination that now raises spend.\",\n \"metrics.cost_per_conversion\":\n \"Actual cost per conversion in micros (÷ 1,000,000) — compare against the campaign's target\",\n \"metrics.interaction_rate\": \"Interaction rate as decimal\",\n \"metrics.video_views\": \"Total video views (integer)\",\n \"metrics.video_view_rate\": \"Video view rate as decimal\",\n\n // Segments\n \"segments.date\": \"Date (YYYY-MM-DD format)\",\n \"segments.device\": \"DESKTOP, MOBILE, TABLET, or OTHER\",\n \"segments.day_of_week\": \"Day of week (MONDAY, TUESDAY, etc.)\",\n \"segments.ad_network_type\": \"Network: SEARCH, SEARCH_PARTNERS, CONTENT, YOUTUBE_SEARCH, etc.\",\n \"segments.product_title\": \"Shopping product title\",\n \"segments.product_item_id\": \"Shopping product ID\",\n \"segments.product_brand\": \"Shopping product brand\",\n \"segments.product_type_l1\": \"Shopping product type (level 1)\",\n\n // Assets\n \"asset.type\": \"Asset type: IMAGE, YOUTUBE_VIDEO, TEXT, LEAD_FORM, etc.\",\n \"asset.text_asset.text\": \"Text asset content\",\n \"asset.image_asset.full_size.url\": \"Full-size image URL\",\n \"asset.youtube_video_asset.youtube_video_id\": \"YouTube video ID\",\n \"asset.youtube_video_asset.youtube_video_title\": \"YouTube video title\",\n \"asset_group.name\": \"Asset group display name\",\n \"asset_group.status\": \"ENABLED, PAUSED, or REMOVED\",\n \"asset_group_asset.field_type\": \"Where the asset is used (HEADLINE, DESCRIPTION, LOGO, etc.)\",\n \"asset_group_asset.primary_status\":\n \"Whether the asset serves: ELIGIBLE, LIMITED, NOT_ELIGIBLE, PAUSED, REMOVED, PENDING\",\n \"asset_group_asset.primary_status_reasons\":\n \"Why the asset is not fully serving (policy, pending review, paused parent …)\",\n\n // Change events (field-level detail, last 30 days)\n \"change_event.change_date_time\": \"When the change occurred (ISO 8601)\",\n \"change_event.change_resource_type\": \"What was changed: CAMPAIGN, AD_GROUP, AD, etc.\",\n \"change_event.resource_change_operation\": \"CREATE, UPDATE, or REMOVE\",\n \"change_event.user_email\": \"Email of user who made the change\",\n\n // Change status (which resources changed, last 90 days — no values, no user)\n \"change_status.last_change_date_time\": \"When this resource last changed (ISO 8601)\",\n \"change_status.resource_type\": \"What changed: CAMPAIGN, AD_GROUP, AD_GROUP_AD, AD_GROUP_CRITERION, etc.\",\n \"change_status.resource_status\": \"ADDED, CHANGED, or REMOVED — not the old or new value\",\n \"change_status.resource_name\": \"Identifier of the changed resource; query it to read its current values\",\n \"change_status.campaign\": \"Resource name of the campaign the change belongs to\",\n \"change_status.ad_group\": \"Resource name of the ad group the change belongs to\",\n \"change_status.ad_group_ad\": \"Resource name of the changed ad\",\n \"change_status.ad_group_criterion\": \"Resource name of the changed keyword or criterion\",\n \"change_status.campaign_criterion\": \"Resource name of the changed campaign-level criterion\",\n\n // Landing pages\n \"landing_page_view.unexpanded_final_url\": \"Landing page URL\",\n\n // Geo\n \"geo_target_constant.name\": \"Geographic location name\",\n \"geo_target_constant.resource_name\": \"Geo target resource identifier\",\n};\n\nexport function getFieldDescriptions(fields: string[]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const field of fields) {\n const desc = FIELD_DESCRIPTIONS[field];\n if (desc) {\n result[field] = desc;\n }\n }\n return result;\n}\n"],"mappings":"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","names":[]}
|