@koda-sl/baker-cli 0.5.0 → 0.9.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.
Files changed (144) hide show
  1. package/README.md +655 -162
  2. package/dist/cli.js +9 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/ads/cache.d.ts +8 -0
  5. package/dist/commands/ads/cache.d.ts.map +1 -0
  6. package/dist/commands/ads/cache.js +79 -0
  7. package/dist/commands/ads/cache.js.map +1 -0
  8. package/dist/commands/ads/cache.test.d.ts +2 -0
  9. package/dist/commands/ads/cache.test.d.ts.map +1 -0
  10. package/dist/commands/ads/cache.test.js +44 -0
  11. package/dist/commands/ads/cache.test.js.map +1 -0
  12. package/dist/commands/ads/field-descriptions.d.ts +2 -0
  13. package/dist/commands/ads/field-descriptions.d.ts.map +1 -0
  14. package/dist/commands/ads/field-descriptions.js +91 -0
  15. package/dist/commands/ads/field-descriptions.js.map +1 -0
  16. package/dist/commands/ads/google/accounts.d.ts +14 -0
  17. package/dist/commands/ads/google/accounts.d.ts.map +1 -0
  18. package/dist/commands/ads/google/accounts.js +72 -0
  19. package/dist/commands/ads/google/accounts.js.map +1 -0
  20. package/dist/commands/ads/google/changes.d.ts +29 -0
  21. package/dist/commands/ads/google/changes.d.ts.map +1 -0
  22. package/dist/commands/ads/google/changes.js +77 -0
  23. package/dist/commands/ads/google/changes.js.map +1 -0
  24. package/dist/commands/ads/google/correction-table.d.ts +3 -0
  25. package/dist/commands/ads/google/correction-table.d.ts.map +1 -0
  26. package/dist/commands/ads/google/correction-table.js +332 -0
  27. package/dist/commands/ads/google/correction-table.js.map +1 -0
  28. package/dist/commands/ads/google/currency.d.ts +13 -0
  29. package/dist/commands/ads/google/currency.d.ts.map +1 -0
  30. package/dist/commands/ads/google/currency.js +62 -0
  31. package/dist/commands/ads/google/currency.js.map +1 -0
  32. package/dist/commands/ads/google/error-parser.d.ts +3 -0
  33. package/dist/commands/ads/google/error-parser.d.ts.map +1 -0
  34. package/dist/commands/ads/google/error-parser.js +89 -0
  35. package/dist/commands/ads/google/error-parser.js.map +1 -0
  36. package/dist/commands/ads/google/error-parser.test.d.ts +2 -0
  37. package/dist/commands/ads/google/error-parser.test.d.ts.map +1 -0
  38. package/dist/commands/ads/google/error-parser.test.js +48 -0
  39. package/dist/commands/ads/google/error-parser.test.js.map +1 -0
  40. package/dist/commands/ads/google/index.d.ts +2 -0
  41. package/dist/commands/ads/google/index.d.ts.map +1 -0
  42. package/dist/commands/ads/google/index.js +30 -0
  43. package/dist/commands/ads/google/index.js.map +1 -0
  44. package/dist/commands/ads/google/keywords/discover.d.ts +49 -0
  45. package/dist/commands/ads/google/keywords/discover.d.ts.map +1 -0
  46. package/dist/commands/ads/google/keywords/discover.js +137 -0
  47. package/dist/commands/ads/google/keywords/discover.js.map +1 -0
  48. package/dist/commands/ads/google/keywords/index.d.ts +2 -0
  49. package/dist/commands/ads/google/keywords/index.d.ts.map +1 -0
  50. package/dist/commands/ads/google/keywords/index.js +18 -0
  51. package/dist/commands/ads/google/keywords/index.js.map +1 -0
  52. package/dist/commands/ads/google/keywords/metrics.d.ts +34 -0
  53. package/dist/commands/ads/google/keywords/metrics.d.ts.map +1 -0
  54. package/dist/commands/ads/google/keywords/metrics.js +109 -0
  55. package/dist/commands/ads/google/keywords/metrics.js.map +1 -0
  56. package/dist/commands/ads/google/preflight.d.ts +3 -0
  57. package/dist/commands/ads/google/preflight.d.ts.map +1 -0
  58. package/dist/commands/ads/google/preflight.js +115 -0
  59. package/dist/commands/ads/google/preflight.js.map +1 -0
  60. package/dist/commands/ads/google/preflight.test.d.ts +2 -0
  61. package/dist/commands/ads/google/preflight.test.d.ts.map +1 -0
  62. package/dist/commands/ads/google/preflight.test.js +50 -0
  63. package/dist/commands/ads/google/preflight.test.js.map +1 -0
  64. package/dist/commands/ads/google/presets.d.ts +12 -0
  65. package/dist/commands/ads/google/presets.d.ts.map +1 -0
  66. package/dist/commands/ads/google/presets.js +71 -0
  67. package/dist/commands/ads/google/presets.js.map +1 -0
  68. package/dist/commands/ads/google/presets.test.d.ts +2 -0
  69. package/dist/commands/ads/google/presets.test.d.ts.map +1 -0
  70. package/dist/commands/ads/google/presets.test.js +79 -0
  71. package/dist/commands/ads/google/presets.test.js.map +1 -0
  72. package/dist/commands/ads/google/query.d.ts +69 -0
  73. package/dist/commands/ads/google/query.d.ts.map +1 -0
  74. package/dist/commands/ads/google/query.js +305 -0
  75. package/dist/commands/ads/google/query.js.map +1 -0
  76. package/dist/commands/ads/index.d.ts +2 -0
  77. package/dist/commands/ads/index.d.ts.map +1 -0
  78. package/dist/commands/ads/index.js +19 -0
  79. package/dist/commands/ads/index.js.map +1 -0
  80. package/dist/commands/ads/output.d.ts +17 -0
  81. package/dist/commands/ads/output.d.ts.map +1 -0
  82. package/dist/commands/ads/output.js +78 -0
  83. package/dist/commands/ads/output.js.map +1 -0
  84. package/dist/commands/ads/output.test.d.ts +2 -0
  85. package/dist/commands/ads/output.test.d.ts.map +1 -0
  86. package/dist/commands/ads/output.test.js +100 -0
  87. package/dist/commands/ads/output.test.js.map +1 -0
  88. package/dist/commands/ads/types.d.ts +69 -0
  89. package/dist/commands/ads/types.d.ts.map +1 -0
  90. package/dist/commands/ads/types.js +2 -0
  91. package/dist/commands/ads/types.js.map +1 -0
  92. package/dist/commands/research/advertisers.d.ts +29 -0
  93. package/dist/commands/research/advertisers.d.ts.map +1 -0
  94. package/dist/commands/research/advertisers.js +71 -0
  95. package/dist/commands/research/advertisers.js.map +1 -0
  96. package/dist/commands/research/index.d.ts +2 -0
  97. package/dist/commands/research/index.d.ts.map +1 -0
  98. package/dist/commands/research/index.js +34 -0
  99. package/dist/commands/research/index.js.map +1 -0
  100. package/dist/commands/research/intent.d.ts +19 -0
  101. package/dist/commands/research/intent.d.ts.map +1 -0
  102. package/dist/commands/research/intent.js +67 -0
  103. package/dist/commands/research/intent.js.map +1 -0
  104. package/dist/commands/research/keyword-gap.d.ts +44 -0
  105. package/dist/commands/research/keyword-gap.d.ts.map +1 -0
  106. package/dist/commands/research/keyword-gap.js +92 -0
  107. package/dist/commands/research/keyword-gap.js.map +1 -0
  108. package/dist/commands/research/keywords-for-site.d.ts +39 -0
  109. package/dist/commands/research/keywords-for-site.d.ts.map +1 -0
  110. package/dist/commands/research/keywords-for-site.js +79 -0
  111. package/dist/commands/research/keywords-for-site.js.map +1 -0
  112. package/dist/commands/research/lighthouse.d.ts +19 -0
  113. package/dist/commands/research/lighthouse.d.ts.map +1 -0
  114. package/dist/commands/research/lighthouse.js +50 -0
  115. package/dist/commands/research/lighthouse.js.map +1 -0
  116. package/dist/commands/research/output.d.ts +26 -0
  117. package/dist/commands/research/output.d.ts.map +1 -0
  118. package/dist/commands/research/output.js +80 -0
  119. package/dist/commands/research/output.js.map +1 -0
  120. package/dist/commands/testimonials/get.d.ts +30 -0
  121. package/dist/commands/testimonials/get.d.ts.map +1 -0
  122. package/dist/commands/testimonials/get.js +42 -0
  123. package/dist/commands/testimonials/get.js.map +1 -0
  124. package/dist/commands/testimonials/index.d.ts +2 -0
  125. package/dist/commands/testimonials/index.d.ts.map +1 -0
  126. package/dist/commands/testimonials/index.js +22 -0
  127. package/dist/commands/testimonials/index.js.map +1 -0
  128. package/dist/commands/testimonials/list.d.ts +60 -0
  129. package/dist/commands/testimonials/list.d.ts.map +1 -0
  130. package/dist/commands/testimonials/list.js +69 -0
  131. package/dist/commands/testimonials/list.js.map +1 -0
  132. package/dist/commands/testimonials/search.d.ts +40 -0
  133. package/dist/commands/testimonials/search.d.ts.map +1 -0
  134. package/dist/commands/testimonials/search.js +59 -0
  135. package/dist/commands/testimonials/search.js.map +1 -0
  136. package/dist/env.d.ts +1 -0
  137. package/dist/env.d.ts.map +1 -1
  138. package/dist/env.js +5 -1
  139. package/dist/env.js.map +1 -1
  140. package/dist/output.d.ts +1 -0
  141. package/dist/output.d.ts.map +1 -1
  142. package/dist/output.js +37 -0
  143. package/dist/output.js.map +1 -1
  144. package/package.json +1 -1
@@ -0,0 +1,332 @@
1
+ function buildCommand(query, ctx) {
2
+ return `baker ads google query "${query}" --customer-id ${ctx.customerId}`;
3
+ }
4
+ export const CORRECTION_RULES = [
5
+ // 1. keyword.text → ad_group_criterion.keyword.text
6
+ {
7
+ matchQuery: /\bkeyword\.text\b/,
8
+ matchApiError: /keyword\.text/i,
9
+ fix: (ctx) => {
10
+ const corrected = ctx.originalQuery.replace(/\bkeyword\.text\b/g, "ad_group_criterion.keyword.text");
11
+ return {
12
+ action: "retry_with_modified_query",
13
+ correctedCommand: buildCommand(corrected, ctx),
14
+ explanation: "Use ad_group_criterion.keyword.text — keywords are accessed through the criterion resource",
15
+ };
16
+ },
17
+ },
18
+ // 2. keyword.match_type → ad_group_criterion.keyword.match_type
19
+ {
20
+ matchQuery: /\bkeyword\.match_type\b/,
21
+ matchApiError: /keyword\.match_type/i,
22
+ fix: (ctx) => {
23
+ const corrected = ctx.originalQuery.replace(/\bkeyword\.match_type\b/g, "ad_group_criterion.keyword.match_type");
24
+ return {
25
+ action: "retry_with_modified_query",
26
+ correctedCommand: buildCommand(corrected, ctx),
27
+ explanation: "Use ad_group_criterion.keyword.match_type for keyword match type",
28
+ };
29
+ },
30
+ },
31
+ // 3. campaign_budget.* queried FROM campaign
32
+ {
33
+ matchQuery: /campaign_budget\.\w+.*FROM\s+campaign\b/i,
34
+ matchApiError: /campaign_budget.*not.*valid.*campaign|cannot.*select.*campaign_budget/i,
35
+ fix: (ctx) => {
36
+ const corrected = ctx.originalQuery.replace(/FROM\s+campaign\b/i, "FROM campaign_budget");
37
+ return {
38
+ action: "use_different_resource",
39
+ correctedCommand: buildCommand(corrected, ctx),
40
+ explanation: "campaign_budget fields must be queried FROM campaign_budget, not FROM campaign",
41
+ };
42
+ },
43
+ },
44
+ // 4. CONTAINS → LIKE
45
+ {
46
+ matchQuery: /CONTAINS\s*\(/i,
47
+ matchApiError: /CONTAINS.*not.*supported|invalid.*operator.*CONTAINS/i,
48
+ fix: (ctx) => {
49
+ const match = ctx.originalQuery.match(/CONTAINS\s*\(\s*([^,]+),\s*'([^']+)'\s*\)/i);
50
+ if (match) {
51
+ const field = match[1]?.trim();
52
+ const value = match[2] ?? "";
53
+ const corrected = ctx.originalQuery.replace(/CONTAINS\s*\(\s*[^,]+,\s*'[^']+'\s*\)/i, `${field} LIKE '%${value}%'`);
54
+ return {
55
+ action: "change_operator",
56
+ correctedCommand: buildCommand(corrected, ctx),
57
+ explanation: "GAQL uses LIKE '%value%' for substring matching, not CONTAINS()",
58
+ };
59
+ }
60
+ return {
61
+ action: "change_operator",
62
+ explanation: "Replace CONTAINS(field, 'value') with field LIKE '%value%'",
63
+ };
64
+ },
65
+ },
66
+ // 5. Missing campaign.id in ad_group queries
67
+ {
68
+ matchQuery: /FROM\s+ad_group\b/i,
69
+ matchApiError: /campaign\.id.*required|must.*include.*campaign\.id/i,
70
+ fix: (ctx) => {
71
+ const corrected = ctx.originalQuery.replace(/SELECT\s+/i, "SELECT campaign.id, ");
72
+ return {
73
+ action: "add_required_field",
74
+ correctedCommand: buildCommand(corrected, ctx),
75
+ explanation: "Ad group queries require campaign.id in SELECT for parent context",
76
+ };
77
+ },
78
+ },
79
+ // 6. Missing campaign.id in keyword_view queries
80
+ {
81
+ matchQuery: /FROM\s+keyword_view\b/i,
82
+ matchApiError: /campaign\.id.*required.*keyword/i,
83
+ fix: (ctx) => {
84
+ const corrected = ctx.originalQuery.replace(/SELECT\s+/i, "SELECT campaign.id, ");
85
+ return {
86
+ action: "add_required_field",
87
+ correctedCommand: buildCommand(corrected, ctx),
88
+ explanation: "Keyword view queries require campaign.id in SELECT",
89
+ };
90
+ },
91
+ },
92
+ // 7. shopping_performance_view.product_* → segments.product_*
93
+ {
94
+ matchQuery: /shopping_performance_view\.product_\w+/,
95
+ matchApiError: /shopping_performance_view\.product/i,
96
+ fix: (ctx) => {
97
+ const corrected = ctx.originalQuery.replace(/shopping_performance_view\.product_(\w+)/g, "segments.product_$1");
98
+ return {
99
+ action: "retry_with_modified_query",
100
+ correctedCommand: buildCommand(corrected, ctx),
101
+ explanation: "Product fields are segments (segments.product_*), not fields on shopping_performance_view",
102
+ };
103
+ },
104
+ },
105
+ // 8. Open-ended date range
106
+ {
107
+ matchQuery: /segments\.date\s*>=\s*'(\d{4}-\d{2}-\d{2})'/i,
108
+ matchApiError: /date.*range.*must.*finite|open.*ended/i,
109
+ fix: (ctx) => {
110
+ const match = ctx.originalQuery.match(/segments\.date\s*>=\s*'(\d{4}-\d{2}-\d{2})'/i);
111
+ const startDate = match?.[1] ?? "2024-01-01";
112
+ const today = new Date().toISOString().slice(0, 10);
113
+ const corrected = ctx.originalQuery.replace(/segments\.date\s*>=\s*'(\d{4}-\d{2}-\d{2})'/i, `segments.date BETWEEN '${startDate}' AND '${today}'`);
114
+ return {
115
+ action: "narrow_date_range",
116
+ correctedCommand: buildCommand(corrected, ctx),
117
+ explanation: "Use BETWEEN with explicit end date — open-ended ranges are not supported",
118
+ };
119
+ },
120
+ },
121
+ // 9. Missing LIMIT
122
+ {
123
+ matchQuery: /^(?!.*\bLIMIT\b)/is,
124
+ fix: (ctx) => {
125
+ const corrected = `${ctx.originalQuery.trimEnd()} LIMIT 200`;
126
+ return {
127
+ action: "retry_with_modified_query",
128
+ correctedCommand: buildCommand(corrected, ctx),
129
+ explanation: "Added LIMIT 200 to prevent excessive data transfer",
130
+ };
131
+ },
132
+ },
133
+ // 10. Not accessible / login-customer-id required
134
+ {
135
+ matchApiError: /not.*accessible|login.customer.id|CUSTOMER_NOT_FOUND|not.*found.*customer/i,
136
+ fix: (ctx) => ({
137
+ action: "reject",
138
+ correctedCommand: buildCommand(ctx.originalQuery, ctx),
139
+ explanation: "Account not accessible. Run 'baker ads google accounts' to refresh the accounts cache, then retry.",
140
+ }),
141
+ },
142
+ // 11. Campaign type by name matching
143
+ {
144
+ matchQuery: /campaign\.name\s*LIKE\s*'%\s*(shopping|pmax|search|display|video)\s*%'/i,
145
+ fix: (ctx) => {
146
+ const match = ctx.originalQuery.match(/campaign\.name\s*LIKE\s*'%\s*(shopping|pmax|search|display|video)\s*%'/i);
147
+ const typeMap = {
148
+ shopping: "SHOPPING",
149
+ pmax: "PERFORMANCE_MAX",
150
+ search: "SEARCH",
151
+ display: "DISPLAY",
152
+ video: "VIDEO",
153
+ };
154
+ const channelType = typeMap[match?.[1]?.toLowerCase() ?? ""] ?? "SEARCH";
155
+ const corrected = ctx.originalQuery.replace(/campaign\.name\s*LIKE\s*'%[^']*%'/i, `campaign.advertising_channel_type = '${channelType}'`);
156
+ return {
157
+ action: "retry_with_modified_query",
158
+ correctedCommand: buildCommand(corrected, ctx),
159
+ explanation: "Filter by campaign.advertising_channel_type enum, not by name pattern",
160
+ };
161
+ },
162
+ },
163
+ // 12. Incompatible fields
164
+ {
165
+ matchApiError: /incompatible|mutually.*exclusive|cannot.*select.*together/i,
166
+ fix: () => ({
167
+ action: "split_query",
168
+ explanation: "These fields cannot be in the same query — split into separate queries and join client-side",
169
+ }),
170
+ },
171
+ // 13. campaign.status = 'ACTIVE' → 'ENABLED'
172
+ {
173
+ matchQuery: /campaign\.status\s*=\s*'ACTIVE'/i,
174
+ fix: (ctx) => {
175
+ const corrected = ctx.originalQuery.replace(/campaign\.status\s*=\s*'ACTIVE'/gi, "campaign.status = 'ENABLED'");
176
+ return {
177
+ action: "retry_with_modified_query",
178
+ correctedCommand: buildCommand(corrected, ctx),
179
+ explanation: "Campaign status uses ENABLED, not ACTIVE",
180
+ };
181
+ },
182
+ },
183
+ // 14. ad_group.status = 'ACTIVE' → 'ENABLED'
184
+ {
185
+ matchQuery: /ad_group\.status\s*=\s*'ACTIVE'/i,
186
+ fix: (ctx) => {
187
+ const corrected = ctx.originalQuery.replace(/ad_group\.status\s*=\s*'ACTIVE'/gi, "ad_group.status = 'ENABLED'");
188
+ return {
189
+ action: "retry_with_modified_query",
190
+ correctedCommand: buildCommand(corrected, ctx),
191
+ explanation: "Ad group status uses ENABLED, not ACTIVE",
192
+ };
193
+ },
194
+ },
195
+ // 15. ad.final_urls → ad_group_ad.ad.final_urls
196
+ {
197
+ matchQuery: /\bad\.final_urls\b(?!.*ad_group_ad)/,
198
+ matchApiError: /ad\.final_urls/i,
199
+ fix: (ctx) => {
200
+ const corrected = ctx.originalQuery.replace(/\bad\.final_urls\b/g, "ad_group_ad.ad.final_urls");
201
+ return {
202
+ action: "retry_with_modified_query",
203
+ correctedCommand: buildCommand(corrected, ctx),
204
+ explanation: "Use the full path: ad_group_ad.ad.final_urls",
205
+ };
206
+ },
207
+ },
208
+ // 16. Rate limit / quota
209
+ {
210
+ matchApiError: /RESOURCE_EXHAUSTED|quota.*exceeded|rate.*limit/i,
211
+ fix: () => ({
212
+ action: "wait_and_retry",
213
+ explanation: "API quota exceeded — wait 30 seconds before retrying",
214
+ }),
215
+ },
216
+ // 17. WHERE on metrics
217
+ {
218
+ matchApiError: /cannot.*filter.*metric|WHERE.*metrics|prohibited.*where/i,
219
+ fix: () => ({
220
+ action: "reject",
221
+ explanation: "Cannot filter on metrics in WHERE clause — remove the metrics filter and filter results client-side",
222
+ }),
223
+ },
224
+ // 18. ORDER BY field not in SELECT
225
+ {
226
+ matchApiError: /order.*by.*field.*not.*selected|must.*select.*field.*order/i,
227
+ fix: (ctx) => {
228
+ const orderMatch = ctx.originalQuery.match(/ORDER\s+BY\s+([\w.]+)/i);
229
+ const field = orderMatch?.[1] ?? "field";
230
+ const corrected = ctx.originalQuery.replace(/SELECT\s+/i, `SELECT ${field}, `);
231
+ return {
232
+ action: "add_required_field",
233
+ correctedCommand: buildCommand(corrected, ctx),
234
+ explanation: `Add ${field} to SELECT — ORDER BY fields must be selected`,
235
+ };
236
+ },
237
+ },
238
+ // 19. Results include REMOVED entities
239
+ {
240
+ matchApiError: /REMOVED.*entities|status.*filter/i,
241
+ fix: (ctx) => {
242
+ const resourceMatch = ctx.originalQuery.match(/FROM\s+(\w+)/i);
243
+ const resource = resourceMatch?.[1] ?? "campaign";
244
+ const hasWhere = /WHERE/i.test(ctx.originalQuery);
245
+ const suffix = hasWhere ? ` AND ${resource}.status != 'REMOVED'` : ` WHERE ${resource}.status != 'REMOVED'`;
246
+ const limitMatch = ctx.originalQuery.match(/(\s+LIMIT\s+\d+)/i);
247
+ let corrected;
248
+ if (limitMatch) {
249
+ corrected = ctx.originalQuery.replace(/(\s+LIMIT\s+\d+)/i, `${suffix}$1`);
250
+ }
251
+ else {
252
+ corrected = ctx.originalQuery.trimEnd() + suffix;
253
+ }
254
+ return {
255
+ action: "retry_with_modified_query",
256
+ correctedCommand: buildCommand(corrected, ctx),
257
+ explanation: `Add status filter to exclude REMOVED ${resource}s`,
258
+ };
259
+ },
260
+ },
261
+ // 20. change_event without date constraint
262
+ {
263
+ matchQuery: /FROM\s+change_event\b(?!.*change_date_time)/i,
264
+ matchApiError: /change_event.*date|date.*required.*change/i,
265
+ fix: (ctx) => {
266
+ const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
267
+ const hasWhere = /WHERE/i.test(ctx.originalQuery);
268
+ const suffix = hasWhere
269
+ ? ` AND change_event.change_date_time >= '${sevenDaysAgo}'`
270
+ : ` WHERE change_event.change_date_time >= '${sevenDaysAgo}'`;
271
+ const corrected = ctx.originalQuery.trimEnd() + suffix;
272
+ return {
273
+ action: "add_required_field",
274
+ correctedCommand: buildCommand(corrected, ctx),
275
+ explanation: "change_event queries require a date constraint on change_date_time",
276
+ };
277
+ },
278
+ },
279
+ // 21. resource_name = 'customers/X/Y/Z' → resource.id = Z
280
+ {
281
+ matchQuery: /(\w+)\.resource_name\s*=\s*'customers\/\d+\/\w+\/(\d+)'/i,
282
+ fix: (ctx) => {
283
+ const match = ctx.originalQuery.match(/(\w+)\.resource_name\s*=\s*'customers\/\d+\/\w+\/(\d+)'/i);
284
+ const resource = match?.[1] ?? "campaign";
285
+ const id = match?.[2] ?? "ID";
286
+ const corrected = ctx.originalQuery.replace(/(\w+)\.resource_name\s*=\s*'customers\/\d+\/\w+\/(\d+)'/i, `${resource}.id = ${id}`);
287
+ return {
288
+ action: "retry_with_modified_query",
289
+ correctedCommand: buildCommand(corrected, ctx),
290
+ explanation: `Simpler: use ${resource}.id = ${id} instead of resource_name path`,
291
+ };
292
+ },
293
+ },
294
+ // 22. segments.click_type incompatibility
295
+ {
296
+ matchApiError: /click_type.*incompatible|cannot.*click_type/i,
297
+ fix: (ctx) => {
298
+ const corrected = ctx.originalQuery.replace(/,?\s*segments\.click_type/g, "");
299
+ return {
300
+ action: "split_query",
301
+ correctedCommand: buildCommand(corrected, ctx),
302
+ explanation: "segments.click_type is incompatible with other segments — remove it or query separately",
303
+ };
304
+ },
305
+ },
306
+ // 23. Bare resource in SELECT
307
+ {
308
+ matchApiError: /cannot.*select.*bare.*resource|invalid.*field/i,
309
+ fix: () => ({
310
+ action: "retry_with_modified_query",
311
+ explanation: "Cannot SELECT a bare resource name — use resource.id, resource.name, or resource.resource_name",
312
+ }),
313
+ },
314
+ // 24. Authentication error
315
+ {
316
+ matchApiError: /unauthenticated|authentication.*required|invalid.*credentials/i,
317
+ fix: () => ({
318
+ action: "authenticate",
319
+ explanation: "Google Ads authentication failed — reconnect Google Ads in dashboard settings",
320
+ }),
321
+ },
322
+ // 25. Timeout / deadline exceeded
323
+ {
324
+ matchApiError: /timeout|deadline.*exceeded|DEADLINE_EXCEEDED/i,
325
+ fix: (ctx) => ({
326
+ action: "retry_with_modified_query",
327
+ correctedCommand: buildCommand(ctx.originalQuery, ctx),
328
+ explanation: "Query timed out — narrow the date range, add more WHERE filters, or reduce LIMIT",
329
+ }),
330
+ },
331
+ ];
332
+ //# sourceMappingURL=correction-table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"correction-table.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/correction-table.ts"],"names":[],"mappings":"AAEA,SAAS,YAAY,CAAC,KAAa,EAAE,GAAsB;IACzD,OAAO,2BAA2B,KAAK,mBAAmB,GAAG,CAAC,UAAU,EAAE,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAqB;IAChD,oDAAoD;IACpD;QACE,UAAU,EAAE,mBAAmB;QAC/B,aAAa,EAAE,gBAAgB;QAC/B,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,oBAAoB,EAAE,iCAAiC,CAAC,CAAC;YACrG,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,4FAA4F;aAC1G,CAAC;QACJ,CAAC;KACF;IAED,gEAAgE;IAChE;QACE,UAAU,EAAE,yBAAyB;QACrC,aAAa,EAAE,sBAAsB;QACrC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,0BAA0B,EAAE,uCAAuC,CAAC,CAAC;YACjH,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,kEAAkE;aAChF,CAAC;QACJ,CAAC;KACF;IAED,6CAA6C;IAC7C;QACE,UAAU,EAAE,0CAA0C;QACtD,aAAa,EAAE,wEAAwE;QACvF,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,oBAAoB,EAAE,sBAAsB,CAAC,CAAC;YAC1F,OAAO;gBACL,MAAM,EAAE,wBAAwB;gBAChC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,gFAAgF;aAC9F,CAAC;QACJ,CAAC;KACF;IAED,qBAAqB;IACrB;QACE,UAAU,EAAE,gBAAgB;QAC5B,aAAa,EAAE,uDAAuD;QACtE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YACpF,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;gBAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CACzC,wCAAwC,EACxC,GAAG,KAAK,WAAW,KAAK,IAAI,CAC7B,CAAC;gBACF,OAAO;oBACL,MAAM,EAAE,iBAAiB;oBACzB,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;oBAC9C,WAAW,EAAE,iEAAiE;iBAC/E,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,iBAAiB;gBACzB,WAAW,EAAE,4DAA4D;aAC1E,CAAC;QACJ,CAAC;KACF;IAED,6CAA6C;IAC7C;QACE,UAAU,EAAE,oBAAoB;QAChC,aAAa,EAAE,qDAAqD;QACpE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC;YAClF,OAAO;gBACL,MAAM,EAAE,oBAAoB;gBAC5B,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,mEAAmE;aACjF,CAAC;QACJ,CAAC;KACF;IAED,iDAAiD;IACjD;QACE,UAAU,EAAE,wBAAwB;QACpC,aAAa,EAAE,kCAAkC;QACjD,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC;YAClF,OAAO;gBACL,MAAM,EAAE,oBAAoB;gBAC5B,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,oDAAoD;aAClE,CAAC;QACJ,CAAC;KACF;IAED,8DAA8D;IAC9D;QACE,UAAU,EAAE,wCAAwC;QACpD,aAAa,EAAE,qCAAqC;QACpD,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,2CAA2C,EAAE,qBAAqB,CAAC,CAAC;YAChH,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,2FAA2F;aACzG,CAAC;QACJ,CAAC;KACF;IAED,2BAA2B;IAC3B;QACE,UAAU,EAAE,8CAA8C;QAC1D,aAAa,EAAE,wCAAwC;QACvD,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YACtF,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC;YAC7C,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CACzC,8CAA8C,EAC9C,0BAA0B,SAAS,UAAU,KAAK,GAAG,CACtD,CAAC;YACF,OAAO;gBACL,MAAM,EAAE,mBAAmB;gBAC3B,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,0EAA0E;aACxF,CAAC;QACJ,CAAC;KACF;IAED,mBAAmB;IACnB;QACE,UAAU,EAAE,oBAAoB;QAChC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,EAAE,YAAY,CAAC;YAC7D,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,oDAAoD;aAClE,CAAC;QACJ,CAAC;KACF;IAED,kDAAkD;IAClD;QACE,aAAa,EAAE,4EAA4E;QAC3F,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACb,MAAM,EAAE,QAAQ;YAChB,gBAAgB,EAAE,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC;YACtD,WAAW,EAAE,oGAAoG;SAClH,CAAC;KACH;IAED,qCAAqC;IACrC;QACE,UAAU,EAAE,yEAAyE;QACrF,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;YACjH,MAAM,OAAO,GAA2B;gBACtC,QAAQ,EAAE,UAAU;gBACpB,IAAI,EAAE,iBAAiB;gBACvB,MAAM,EAAE,QAAQ;gBAChB,OAAO,EAAE,SAAS;gBAClB,KAAK,EAAE,OAAO;aACf,CAAC;YACF,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,IAAI,QAAQ,CAAC;YACzE,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CACzC,oCAAoC,EACpC,wCAAwC,WAAW,GAAG,CACvD,CAAC;YACF,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,uEAAuE;aACrF,CAAC;QACJ,CAAC;KACF;IAED,0BAA0B;IAC1B;QACE,aAAa,EAAE,4DAA4D;QAC3E,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACV,MAAM,EAAE,aAAa;YACrB,WAAW,EAAE,6FAA6F;SAC3G,CAAC;KACH;IAED,6CAA6C;IAC7C;QACE,UAAU,EAAE,kCAAkC;QAC9C,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,mCAAmC,EAAE,6BAA6B,CAAC,CAAC;YAChH,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,0CAA0C;aACxD,CAAC;QACJ,CAAC;KACF;IAED,6CAA6C;IAC7C;QACE,UAAU,EAAE,kCAAkC;QAC9C,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,mCAAmC,EAAE,6BAA6B,CAAC,CAAC;YAChH,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,0CAA0C;aACxD,CAAC;QACJ,CAAC;KACF;IAED,gDAAgD;IAChD;QACE,UAAU,EAAE,qCAAqC;QACjD,aAAa,EAAE,iBAAiB;QAChC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,qBAAqB,EAAE,2BAA2B,CAAC,CAAC;YAChG,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,8CAA8C;aAC5D,CAAC;QACJ,CAAC;KACF;IAED,yBAAyB;IACzB;QACE,aAAa,EAAE,iDAAiD;QAChE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACV,MAAM,EAAE,gBAAgB;YACxB,WAAW,EAAE,sDAAsD;SACpE,CAAC;KACH;IAED,uBAAuB;IACvB;QACE,aAAa,EAAE,0DAA0D;QACzE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACV,MAAM,EAAE,QAAQ;YAChB,WAAW,EACT,qGAAqG;SACxG,CAAC;KACH;IAED,mCAAmC;IACnC;QACE,aAAa,EAAE,6DAA6D;QAC5E,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC;YACzC,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC;YAC/E,OAAO;gBACL,MAAM,EAAE,oBAAoB;gBAC5B,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,OAAO,KAAK,+CAA+C;aACzE,CAAC;QACJ,CAAC;KACF;IAED,uCAAuC;IACvC;QACE,aAAa,EAAE,mCAAmC;QAClD,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;YAC/D,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC;YAClD,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,QAAQ,sBAAsB,CAAC,CAAC,CAAC,UAAU,QAAQ,sBAAsB,CAAC;YAC5G,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAChE,IAAI,SAAiB,CAAC;YACtB,IAAI,UAAU,EAAE,CAAC;gBACf,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC;YAC5E,CAAC;iBAAM,CAAC;gBACN,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC;YACnD,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,wCAAwC,QAAQ,GAAG;aACjE,CAAC;QACJ,CAAC;KACF;IAED,2CAA2C;IAC3C;QACE,UAAU,EAAE,8CAA8C;QAC1D,aAAa,EAAE,4CAA4C;QAC3D,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/F,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,QAAQ;gBACrB,CAAC,CAAC,0CAA0C,YAAY,GAAG;gBAC3D,CAAC,CAAC,4CAA4C,YAAY,GAAG,CAAC;YAChE,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC;YACvD,OAAO;gBACL,MAAM,EAAE,oBAAoB;gBAC5B,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,oEAAoE;aAClF,CAAC;QACJ,CAAC;KACF;IAED,0DAA0D;IAC1D;QACE,UAAU,EAAE,0DAA0D;QACtE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAClG,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC;YAC1C,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;YAC9B,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CACzC,0DAA0D,EAC1D,GAAG,QAAQ,SAAS,EAAE,EAAE,CACzB,CAAC;YACF,OAAO;gBACL,MAAM,EAAE,2BAA2B;gBACnC,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,gBAAgB,QAAQ,SAAS,EAAE,gCAAgC;aACjF,CAAC;QACJ,CAAC;KACF;IAED,0CAA0C;IAC1C;QACE,aAAa,EAAE,8CAA8C;QAC7D,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;YACX,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,CAAC;YAC9E,OAAO;gBACL,MAAM,EAAE,aAAa;gBACrB,gBAAgB,EAAE,YAAY,CAAC,SAAS,EAAE,GAAG,CAAC;gBAC9C,WAAW,EAAE,yFAAyF;aACvG,CAAC;QACJ,CAAC;KACF;IAED,8BAA8B;IAC9B;QACE,aAAa,EAAE,gDAAgD;QAC/D,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACV,MAAM,EAAE,2BAA2B;YACnC,WAAW,EAAE,gGAAgG;SAC9G,CAAC;KACH;IAED,2BAA2B;IAC3B;QACE,aAAa,EAAE,gEAAgE;QAC/E,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACV,MAAM,EAAE,cAAc;YACtB,WAAW,EAAE,+EAA+E;SAC7F,CAAC;KACH;IAED,kCAAkC;IAClC;QACE,aAAa,EAAE,+CAA+C;QAC9D,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACb,MAAM,EAAE,2BAA2B;YACnC,gBAAgB,EAAE,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC;YACtD,WAAW,EAAE,kFAAkF;SAChG,CAAC;KACH;CACF,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare const currencyCommand: import("citty").CommandDef<{
2
+ readonly "customer-id": {
3
+ readonly type: "string";
4
+ readonly description: "Google Ads customer ID (10 digits)";
5
+ readonly required: false;
6
+ };
7
+ readonly "no-cache": {
8
+ readonly type: "boolean";
9
+ readonly description: "Skip cache";
10
+ readonly required: false;
11
+ };
12
+ }>;
13
+ //# sourceMappingURL=currency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/currency.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,eAAe;;;;;;;;;;;EA+C1B,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { defineCommand } from "citty";
2
+ import { ApiError, apiGet } from "../../../client.js";
3
+ import { registerSchema } from "../../../schemas.js";
4
+ import { cacheGet, cacheSet, getManagerIdForCustomer } from "../cache.js";
5
+ import { resolveCustomerId, writeAdsJson } from "../output.js";
6
+ import { parseApiError } from "./error-parser.js";
7
+ registerSchema({
8
+ command: "ads.google.currency",
9
+ description: "Get the currency code for a Google Ads account. Returns currency_code, customer_id, account_name, and access_type. Call this before interpreting cost_micros values.",
10
+ args: {
11
+ "customer-id": {
12
+ type: "string",
13
+ description: "Google Ads customer ID (10 digits, no dashes). Falls back to BAKER_GOOGLE_ADS_CUSTOMER_ID env var.",
14
+ required: false,
15
+ },
16
+ },
17
+ });
18
+ export const currencyCommand = defineCommand({
19
+ meta: {
20
+ name: "currency",
21
+ description: `Get account currency code. Use this to interpret metrics.cost_micros values.
22
+
23
+ Examples:
24
+ baker ads google currency --customer-id 1234567890`,
25
+ },
26
+ args: {
27
+ "customer-id": { type: "string", description: "Google Ads customer ID (10 digits)", required: false },
28
+ "no-cache": { type: "boolean", description: "Skip cache", required: false },
29
+ },
30
+ run: async ({ args }) => {
31
+ const customerId = resolveCustomerId(args);
32
+ const useCache = !args["no-cache"];
33
+ const cacheKey = `currency:${customerId}`;
34
+ if (useCache) {
35
+ const cached = cacheGet("accounts", cacheKey);
36
+ if (cached) {
37
+ writeAdsJson({ ok: true, data: cached.data, cached: true });
38
+ return;
39
+ }
40
+ }
41
+ try {
42
+ const params = { "customer-id": customerId };
43
+ const managerId = getManagerIdForCustomer(customerId);
44
+ if (managerId)
45
+ params["manager-id"] = managerId;
46
+ const data = await apiGet("/api/ads/google/currency", params);
47
+ if (useCache) {
48
+ cacheSet("accounts", cacheKey, data, 24 * 60 * 60 * 1000);
49
+ }
50
+ writeAdsJson({ ok: true, data });
51
+ }
52
+ catch (err) {
53
+ if (err instanceof ApiError) {
54
+ writeAdsJson(parseApiError(err.message, "", customerId));
55
+ process.exit(1);
56
+ }
57
+ writeAdsJson({ ok: false, error: { code: "NETWORK_ERROR", message: "Unexpected error" } });
58
+ process.exit(1);
59
+ }
60
+ },
61
+ });
62
+ //# sourceMappingURL=currency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/currency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AdsErrorEnvelope } from "../types.ts";
2
+ export declare function parseApiError(errorMessage: string, originalQuery: string, customerId: string): AdsErrorEnvelope;
3
+ //# sourceMappingURL=error-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-parser.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/error-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAqB,MAAM,aAAa,CAAC;AA0BvE,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,CA0D/G"}
@@ -0,0 +1,89 @@
1
+ import { CORRECTION_RULES } from "./correction-table.js";
2
+ function mapErrorCode(message) {
3
+ if (/field.*not.*found|unrecognized.*field|not.*valid.*field/i.test(message))
4
+ return "FIELD_NOT_FOUND";
5
+ if (/not.*valid.*resource|cannot.*select.*from/i.test(message))
6
+ return "WRONG_RESOURCE";
7
+ if (/operator|CONTAINS|LIKE/i.test(message))
8
+ return "INVALID_OPERATOR";
9
+ if (/login.customer.id|not.*accessible|CUSTOMER_NOT_FOUND/i.test(message))
10
+ return "MISSING_MANAGER_ID";
11
+ if (/incompatible|mutually.*exclusive/i.test(message))
12
+ return "INCOMPATIBLE_FIELDS";
13
+ if (/unauthenticated|authentication/i.test(message))
14
+ return "AUTH_ERROR";
15
+ if (/permission/i.test(message))
16
+ return "PERMISSION_DENIED";
17
+ if (/RESOURCE_EXHAUSTED|quota|rate.*limit/i.test(message))
18
+ return "QUOTA_EXCEEDED";
19
+ if (/timeout|DEADLINE_EXCEEDED/i.test(message))
20
+ return "TIMEOUT";
21
+ return "API_ERROR";
22
+ }
23
+ function isRetryable(code) {
24
+ return code === "QUOTA_EXCEEDED" || code === "TIMEOUT";
25
+ }
26
+ function getRetryDelay(code) {
27
+ if (code === "QUOTA_EXCEEDED")
28
+ return 30000;
29
+ if (code === "TIMEOUT")
30
+ return 5000;
31
+ return undefined;
32
+ }
33
+ export function parseApiError(errorMessage, originalQuery, customerId) {
34
+ const ctx = {
35
+ originalQuery,
36
+ customerId,
37
+ apiErrorMessage: errorMessage,
38
+ };
39
+ // Try API error patterns first
40
+ for (const rule of CORRECTION_RULES) {
41
+ if (rule.matchApiError?.test(errorMessage)) {
42
+ const fix = rule.fix(ctx);
43
+ const code = mapErrorCode(errorMessage);
44
+ return {
45
+ ok: false,
46
+ error: {
47
+ code,
48
+ message: errorMessage,
49
+ fix,
50
+ retryable: isRetryable(code),
51
+ retryAfterMs: getRetryDelay(code),
52
+ },
53
+ };
54
+ }
55
+ }
56
+ // Try query patterns (API might reject what preflight missed)
57
+ for (const rule of CORRECTION_RULES) {
58
+ if (rule.matchQuery?.test(originalQuery)) {
59
+ const fix = rule.fix(ctx);
60
+ const code = mapErrorCode(errorMessage);
61
+ return {
62
+ ok: false,
63
+ error: {
64
+ code,
65
+ message: errorMessage,
66
+ fix,
67
+ retryable: isRetryable(code),
68
+ retryAfterMs: getRetryDelay(code),
69
+ },
70
+ };
71
+ }
72
+ }
73
+ // Fallback: unknown error
74
+ const code = mapErrorCode(errorMessage);
75
+ return {
76
+ ok: false,
77
+ error: {
78
+ code,
79
+ message: errorMessage,
80
+ fix: {
81
+ action: "reject",
82
+ explanation: "Unrecognized error — verify query syntax against Google Ads GAQL reference",
83
+ },
84
+ retryable: isRetryable(code),
85
+ retryAfterMs: getRetryDelay(code),
86
+ },
87
+ };
88
+ }
89
+ //# sourceMappingURL=error-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-parser.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/error-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=error-parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-parser.test.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/error-parser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { parseApiError } from "./error-parser.js";
3
+ const QUERY = "SELECT campaign.name FROM campaign LIMIT 10";
4
+ const CID = "123-456-7890";
5
+ describe("parseApiError", () => {
6
+ it("maps field-not-found errors to FIELD_NOT_FOUND", () => {
7
+ const result = parseApiError("field 'campaign.foo' not found in resource", QUERY, CID);
8
+ expect(result.ok).toBe(false);
9
+ expect(result.error.code).toBe("FIELD_NOT_FOUND");
10
+ });
11
+ it("maps authentication errors to AUTH_ERROR", () => {
12
+ const result = parseApiError("Request is unauthenticated", QUERY, CID);
13
+ expect(result.ok).toBe(false);
14
+ expect(result.error.code).toBe("AUTH_ERROR");
15
+ });
16
+ it("maps quota exceeded to QUOTA_EXCEEDED with retry", () => {
17
+ const result = parseApiError("RESOURCE_EXHAUSTED: quota exceeded for project", QUERY, CID);
18
+ expect(result.ok).toBe(false);
19
+ expect(result.error.code).toBe("QUOTA_EXCEEDED");
20
+ expect(result.error.retryable).toBe(true);
21
+ expect(result.error.retryAfterMs).toBe(30000);
22
+ });
23
+ it("maps timeout to TIMEOUT with retry", () => {
24
+ const result = parseApiError("DEADLINE_EXCEEDED: timeout after 60s", QUERY, CID);
25
+ expect(result.ok).toBe(false);
26
+ expect(result.error.code).toBe("TIMEOUT");
27
+ expect(result.error.retryable).toBe(true);
28
+ expect(result.error.retryAfterMs).toBe(5000);
29
+ });
30
+ it("maps unknown errors to API_ERROR with retryable false", () => {
31
+ const result = parseApiError("Something completely unexpected happened", QUERY, CID);
32
+ expect(result.ok).toBe(false);
33
+ expect(result.error.code).toBe("API_ERROR");
34
+ expect(result.error.retryable).toBe(false);
35
+ });
36
+ it("matches correction rules for keyword.text in error message", () => {
37
+ const query = "SELECT keyword.text FROM keyword_view LIMIT 10";
38
+ const result = parseApiError("keyword.text is not a valid field", query, CID);
39
+ expect(result.error.fix.action).toBe("retry_with_modified_query");
40
+ expect(result.error.fix.correctedCommand).toMatch(/ad_group_criterion\.keyword\.text/);
41
+ });
42
+ it("maps permission denied errors to PERMISSION_DENIED", () => {
43
+ const result = parseApiError("The caller does not have permission to access this resource", QUERY, CID);
44
+ expect(result.ok).toBe(false);
45
+ expect(result.error.code).toBe("PERMISSION_DENIED");
46
+ });
47
+ });
48
+ //# sourceMappingURL=error-parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-parser.test.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/error-parser.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const googleCommand: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa,qDAsBxB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { defineCommand } from "citty";
2
+ import { accountsCommand } from "./accounts.js";
3
+ import { changesCommand } from "./changes.js";
4
+ import { currencyCommand } from "./currency.js";
5
+ import { keywordsCommand } from "./keywords/index.js";
6
+ import { queryCommand } from "./query.js";
7
+ export const googleCommand = defineCommand({
8
+ meta: {
9
+ name: "google",
10
+ description: `Google Ads commands. Query campaigns, keywords, search terms, and more via GAQL.
11
+
12
+ Start here:
13
+ baker ads google accounts — list accessible accounts
14
+ baker ads google query --list-presets — see available query templates
15
+
16
+ Examples:
17
+ baker ads google query "SELECT campaign.name, metrics.clicks FROM campaign WHERE segments.date DURING LAST_7_DAYS" --customer-id 1234567890
18
+ baker ads google query --preset campaign-performance --customer-id 1234567890
19
+ baker ads google currency --customer-id 1234567890
20
+ baker ads google keywords discover --customer-id 1234567890 --seeds "running shoes"`,
21
+ },
22
+ subCommands: {
23
+ accounts: accountsCommand,
24
+ currency: currencyCommand,
25
+ changes: changesCommand,
26
+ query: queryCommand,
27
+ keywords: keywordsCommand,
28
+ },
29
+ });
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE;;;;;;;;;;sFAUqE;KACnF;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,cAAc;QACvB,KAAK,EAAE,YAAY;QACnB,QAAQ,EAAE,eAAe;KAC1B;CACF,CAAC,CAAC"}