@koda-sl/baker-cli 0.5.1 → 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.
- package/README.md +655 -162
- package/dist/cli.js +7 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/ads/cache.d.ts +8 -0
- package/dist/commands/ads/cache.d.ts.map +1 -0
- package/dist/commands/ads/cache.js +79 -0
- package/dist/commands/ads/cache.js.map +1 -0
- package/dist/commands/ads/cache.test.d.ts +2 -0
- package/dist/commands/ads/cache.test.d.ts.map +1 -0
- package/dist/commands/ads/cache.test.js +44 -0
- package/dist/commands/ads/cache.test.js.map +1 -0
- package/dist/commands/ads/field-descriptions.d.ts +2 -0
- package/dist/commands/ads/field-descriptions.d.ts.map +1 -0
- package/dist/commands/ads/field-descriptions.js +91 -0
- package/dist/commands/ads/field-descriptions.js.map +1 -0
- package/dist/commands/ads/google/accounts.d.ts +14 -0
- package/dist/commands/ads/google/accounts.d.ts.map +1 -0
- package/dist/commands/ads/google/accounts.js +72 -0
- package/dist/commands/ads/google/accounts.js.map +1 -0
- package/dist/commands/ads/google/changes.d.ts +29 -0
- package/dist/commands/ads/google/changes.d.ts.map +1 -0
- package/dist/commands/ads/google/changes.js +77 -0
- package/dist/commands/ads/google/changes.js.map +1 -0
- package/dist/commands/ads/google/correction-table.d.ts +3 -0
- package/dist/commands/ads/google/correction-table.d.ts.map +1 -0
- package/dist/commands/ads/google/correction-table.js +332 -0
- package/dist/commands/ads/google/correction-table.js.map +1 -0
- package/dist/commands/ads/google/currency.d.ts +13 -0
- package/dist/commands/ads/google/currency.d.ts.map +1 -0
- package/dist/commands/ads/google/currency.js +62 -0
- package/dist/commands/ads/google/currency.js.map +1 -0
- package/dist/commands/ads/google/error-parser.d.ts +3 -0
- package/dist/commands/ads/google/error-parser.d.ts.map +1 -0
- package/dist/commands/ads/google/error-parser.js +89 -0
- package/dist/commands/ads/google/error-parser.js.map +1 -0
- package/dist/commands/ads/google/error-parser.test.d.ts +2 -0
- package/dist/commands/ads/google/error-parser.test.d.ts.map +1 -0
- package/dist/commands/ads/google/error-parser.test.js +48 -0
- package/dist/commands/ads/google/error-parser.test.js.map +1 -0
- package/dist/commands/ads/google/index.d.ts +2 -0
- package/dist/commands/ads/google/index.d.ts.map +1 -0
- package/dist/commands/ads/google/index.js +30 -0
- package/dist/commands/ads/google/index.js.map +1 -0
- package/dist/commands/ads/google/keywords/discover.d.ts +49 -0
- package/dist/commands/ads/google/keywords/discover.d.ts.map +1 -0
- package/dist/commands/ads/google/keywords/discover.js +137 -0
- package/dist/commands/ads/google/keywords/discover.js.map +1 -0
- package/dist/commands/ads/google/keywords/index.d.ts +2 -0
- package/dist/commands/ads/google/keywords/index.d.ts.map +1 -0
- package/dist/commands/ads/google/keywords/index.js +18 -0
- package/dist/commands/ads/google/keywords/index.js.map +1 -0
- package/dist/commands/ads/google/keywords/metrics.d.ts +34 -0
- package/dist/commands/ads/google/keywords/metrics.d.ts.map +1 -0
- package/dist/commands/ads/google/keywords/metrics.js +109 -0
- package/dist/commands/ads/google/keywords/metrics.js.map +1 -0
- package/dist/commands/ads/google/preflight.d.ts +3 -0
- package/dist/commands/ads/google/preflight.d.ts.map +1 -0
- package/dist/commands/ads/google/preflight.js +115 -0
- package/dist/commands/ads/google/preflight.js.map +1 -0
- package/dist/commands/ads/google/preflight.test.d.ts +2 -0
- package/dist/commands/ads/google/preflight.test.d.ts.map +1 -0
- package/dist/commands/ads/google/preflight.test.js +50 -0
- package/dist/commands/ads/google/preflight.test.js.map +1 -0
- package/dist/commands/ads/google/presets.d.ts +12 -0
- package/dist/commands/ads/google/presets.d.ts.map +1 -0
- package/dist/commands/ads/google/presets.js +71 -0
- package/dist/commands/ads/google/presets.js.map +1 -0
- package/dist/commands/ads/google/presets.test.d.ts +2 -0
- package/dist/commands/ads/google/presets.test.d.ts.map +1 -0
- package/dist/commands/ads/google/presets.test.js +79 -0
- package/dist/commands/ads/google/presets.test.js.map +1 -0
- package/dist/commands/ads/google/query.d.ts +69 -0
- package/dist/commands/ads/google/query.d.ts.map +1 -0
- package/dist/commands/ads/google/query.js +305 -0
- package/dist/commands/ads/google/query.js.map +1 -0
- package/dist/commands/ads/index.d.ts +2 -0
- package/dist/commands/ads/index.d.ts.map +1 -0
- package/dist/commands/ads/index.js +19 -0
- package/dist/commands/ads/index.js.map +1 -0
- package/dist/commands/ads/output.d.ts +17 -0
- package/dist/commands/ads/output.d.ts.map +1 -0
- package/dist/commands/ads/output.js +78 -0
- package/dist/commands/ads/output.js.map +1 -0
- package/dist/commands/ads/output.test.d.ts +2 -0
- package/dist/commands/ads/output.test.d.ts.map +1 -0
- package/dist/commands/ads/output.test.js +100 -0
- package/dist/commands/ads/output.test.js.map +1 -0
- package/dist/commands/ads/types.d.ts +69 -0
- package/dist/commands/ads/types.d.ts.map +1 -0
- package/dist/commands/ads/types.js +2 -0
- package/dist/commands/ads/types.js.map +1 -0
- package/dist/commands/research/advertisers.d.ts +29 -0
- package/dist/commands/research/advertisers.d.ts.map +1 -0
- package/dist/commands/research/advertisers.js +71 -0
- package/dist/commands/research/advertisers.js.map +1 -0
- package/dist/commands/research/index.d.ts +2 -0
- package/dist/commands/research/index.d.ts.map +1 -0
- package/dist/commands/research/index.js +34 -0
- package/dist/commands/research/index.js.map +1 -0
- package/dist/commands/research/intent.d.ts +19 -0
- package/dist/commands/research/intent.d.ts.map +1 -0
- package/dist/commands/research/intent.js +67 -0
- package/dist/commands/research/intent.js.map +1 -0
- package/dist/commands/research/keyword-gap.d.ts +44 -0
- package/dist/commands/research/keyword-gap.d.ts.map +1 -0
- package/dist/commands/research/keyword-gap.js +92 -0
- package/dist/commands/research/keyword-gap.js.map +1 -0
- package/dist/commands/research/keywords-for-site.d.ts +39 -0
- package/dist/commands/research/keywords-for-site.d.ts.map +1 -0
- package/dist/commands/research/keywords-for-site.js +79 -0
- package/dist/commands/research/keywords-for-site.js.map +1 -0
- package/dist/commands/research/lighthouse.d.ts +19 -0
- package/dist/commands/research/lighthouse.d.ts.map +1 -0
- package/dist/commands/research/lighthouse.js +50 -0
- package/dist/commands/research/lighthouse.js.map +1 -0
- package/dist/commands/research/output.d.ts +26 -0
- package/dist/commands/research/output.d.ts.map +1 -0
- package/dist/commands/research/output.js +80 -0
- package/dist/commands/research/output.js.map +1 -0
- package/dist/env.d.ts +1 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +5 -1
- package/dist/env.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const GAQL_DATE_RANGE_RE = /^(?:TODAY|YESTERDAY|LAST_7_DAYS|LAST_14_DAYS|LAST_30_DAYS|LAST_90_DAYS|THIS_MONTH|LAST_MONTH|THIS_QUARTER|LAST_QUARTER|THIS_YEAR|LAST_YEAR|ALL_TIME|BETWEEN\s+'[0-9]{4}-[0-9]{2}-[0-9]{2}'\s+AND\s+'[0-9]{4}-[0-9]{2}-[0-9]{2}')$/i;
|
|
2
|
+
export function isValidDateRange(value) {
|
|
3
|
+
return GAQL_DATE_RANGE_RE.test(value.trim());
|
|
4
|
+
}
|
|
5
|
+
export const PRESETS = [
|
|
6
|
+
{
|
|
7
|
+
name: "campaign-performance",
|
|
8
|
+
description: "Campaign-level metrics overview",
|
|
9
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, campaign.status, campaign.advertising_channel_type, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.conversions_value, metrics.ctr, metrics.average_cpc FROM campaign WHERE segments.date DURING {dateRange} AND campaign.status != 'REMOVED' ORDER BY metrics.cost_micros DESC LIMIT {limit}`,
|
|
10
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
11
|
+
defaultLimit: 200,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "keyword-analysis",
|
|
15
|
+
description: "Keyword performance with match type and quality",
|
|
16
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, ad_group.name, ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.ctr FROM keyword_view WHERE segments.date DURING {dateRange} AND campaign.status = 'ENABLED' ORDER BY metrics.impressions DESC LIMIT {limit}`,
|
|
17
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
18
|
+
defaultLimit: 200,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "search-terms",
|
|
22
|
+
description: "Actual user search queries triggering ads",
|
|
23
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, ad_group.name, search_term_view.search_term, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions FROM search_term_view WHERE segments.date DURING {dateRange} AND campaign.status = 'ENABLED' ORDER BY metrics.impressions DESC LIMIT {limit}`,
|
|
24
|
+
defaultDateRange: "LAST_7_DAYS",
|
|
25
|
+
defaultLimit: 200,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "ad-copy-performance",
|
|
29
|
+
description: "Ad headline and description effectiveness",
|
|
30
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, ad_group_ad.ad.responsive_search_ad.headlines, ad_group_ad.ad.responsive_search_ad.descriptions, ad_group_ad.ad.final_urls, metrics.impressions, metrics.clicks, metrics.conversions, metrics.ctr FROM ad_group_ad WHERE segments.date DURING {dateRange} AND ad_group_ad.status = 'ENABLED' ORDER BY metrics.impressions DESC LIMIT {limit}`,
|
|
31
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
32
|
+
defaultLimit: 200,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "asset-performance",
|
|
36
|
+
description: "Performance Max asset performance labels",
|
|
37
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, asset_group.name, asset_group_asset.field_type, asset_group_asset.performance_label, asset.type, asset.text_asset.text, asset.image_asset.full_size.url FROM asset_group_asset WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX' AND segments.date DURING {dateRange} LIMIT {limit}`,
|
|
38
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
39
|
+
defaultLimit: 200,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "shopping-products",
|
|
43
|
+
description: "Product-level shopping performance metrics",
|
|
44
|
+
gaqlTemplate: `SELECT campaign.id, campaign.name, segments.product_title, segments.product_item_id, segments.product_brand, segments.product_type_l1, metrics.clicks, metrics.impressions, metrics.cost_micros, metrics.conversions FROM shopping_performance_view WHERE segments.date DURING {dateRange} ORDER BY metrics.cost_micros DESC LIMIT {limit}`,
|
|
45
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
46
|
+
defaultLimit: 200,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "account-summary",
|
|
50
|
+
description: "Account-level totals for a date range",
|
|
51
|
+
gaqlTemplate: `SELECT customer.id, customer.descriptive_name, metrics.impressions, metrics.clicks, metrics.cost_micros, metrics.conversions, metrics.conversions_value FROM customer WHERE segments.date DURING {dateRange} LIMIT 1`,
|
|
52
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
53
|
+
defaultLimit: 1,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
export function getPreset(name) {
|
|
57
|
+
return PRESETS.find((p) => p.name === name);
|
|
58
|
+
}
|
|
59
|
+
export function expandPreset(preset, params) {
|
|
60
|
+
const dateRange = params.dateRange ?? preset.defaultDateRange;
|
|
61
|
+
const limit = params.limit ?? preset.defaultLimit;
|
|
62
|
+
if (!isValidDateRange(dateRange)) {
|
|
63
|
+
return {
|
|
64
|
+
query: "",
|
|
65
|
+
dateRangeError: `Invalid date range: "${dateRange}". Use a GAQL date literal (e.g. LAST_30_DAYS, TODAY) or BETWEEN 'YYYY-MM-DD' AND 'YYYY-MM-DD'.`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const query = preset.gaqlTemplate.replace(/\{dateRange\}/g, dateRange).replace(/\{limit\}/g, String(limit));
|
|
69
|
+
return { query };
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/presets.ts"],"names":[],"mappings":"AAEA,MAAM,kBAAkB,GACtB,oOAAoO,CAAC;AAEvO,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAuB;IACzC;QACE,IAAI,EAAE,sBAAsB;QAC5B,WAAW,EAAE,iCAAiC;QAC9C,YAAY,EAAE,yWAAyW;QACvX,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,GAAG;KAClB;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,iDAAiD;QAC9D,YAAY,EAAE,+VAA+V;QAC7W,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,GAAG;KAClB;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,2CAA2C;QACxD,YAAY,EAAE,4SAA4S;QAC1T,gBAAgB,EAAE,aAAa;QAC/B,YAAY,EAAE,GAAG;KAClB;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,2CAA2C;QACxD,YAAY,EAAE,iXAAiX;QAC/X,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,GAAG;KAClB;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,0CAA0C;QACvD,YAAY,EAAE,kUAAkU;QAChV,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,GAAG;KAClB;IACD;QACE,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,4CAA4C;QACzD,YAAY,EAAE,4UAA4U;QAC1V,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,GAAG;KAClB;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,uCAAuC;QACpD,YAAY,EAAE,sNAAsN;QACpO,gBAAgB,EAAE,cAAc;QAChC,YAAY,EAAE,CAAC;KAChB;CACF,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,MAAwB,EACxB,MAA8C;IAE9C,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,gBAAgB,CAAC;IAC9D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,YAAY,CAAC;IAElD,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;QACjC,OAAO;YACL,KAAK,EAAE,EAAE;YACT,cAAc,EAAE,wBAAwB,SAAS,iGAAiG;SACnJ,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5G,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.test.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/presets.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { expandPreset, getPreset, isValidDateRange } from "./presets.js";
|
|
3
|
+
describe("getPreset", () => {
|
|
4
|
+
it("returns a known preset by name", () => {
|
|
5
|
+
const preset = getPreset("campaign-performance");
|
|
6
|
+
expect(preset).toBeDefined();
|
|
7
|
+
expect(preset?.name).toBe("campaign-performance");
|
|
8
|
+
});
|
|
9
|
+
it("returns undefined for an unknown preset", () => {
|
|
10
|
+
expect(getPreset("nonexistent-preset")).toBeUndefined();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
describe("isValidDateRange", () => {
|
|
14
|
+
it("accepts GAQL date literals", () => {
|
|
15
|
+
for (const v of ["TODAY", "YESTERDAY", "LAST_7_DAYS", "LAST_30_DAYS", "LAST_90_DAYS", "THIS_MONTH", "ALL_TIME"]) {
|
|
16
|
+
expect(isValidDateRange(v)).toBe(true);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
it("accepts BETWEEN with valid dates", () => {
|
|
20
|
+
expect(isValidDateRange("BETWEEN '2024-01-01' AND '2024-12-31'")).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
it("is case-insensitive", () => {
|
|
23
|
+
expect(isValidDateRange("last_7_days")).toBe(true);
|
|
24
|
+
expect(isValidDateRange("between '2024-01-01' and '2024-06-01'")).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
it("rejects arbitrary strings", () => {
|
|
27
|
+
expect(isValidDateRange("DROP TABLE; --")).toBe(false);
|
|
28
|
+
expect(isValidDateRange("LAST_7_DAYS; SELECT *")).toBe(false);
|
|
29
|
+
expect(isValidDateRange("")).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("expandPreset", () => {
|
|
33
|
+
const preset = {
|
|
34
|
+
name: "test-preset",
|
|
35
|
+
description: "A test preset",
|
|
36
|
+
gaqlTemplate: "SELECT * FROM campaign WHERE segments.date DURING {dateRange} LIMIT {limit}",
|
|
37
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
38
|
+
defaultLimit: 100,
|
|
39
|
+
};
|
|
40
|
+
it("replaces {dateRange} and {limit} placeholders", () => {
|
|
41
|
+
const result = expandPreset(preset, { dateRange: "TODAY", limit: 50 });
|
|
42
|
+
expect(result.query).toBe("SELECT * FROM campaign WHERE segments.date DURING TODAY LIMIT 50");
|
|
43
|
+
expect(result.dateRangeError).toBeUndefined();
|
|
44
|
+
});
|
|
45
|
+
it("uses default dateRange when not provided", () => {
|
|
46
|
+
const result = expandPreset(preset, { limit: 10 });
|
|
47
|
+
expect(result.query).toContain("DURING LAST_30_DAYS");
|
|
48
|
+
});
|
|
49
|
+
it("uses default limit when not provided", () => {
|
|
50
|
+
const result = expandPreset(preset, { dateRange: "LAST_7_DAYS" });
|
|
51
|
+
expect(result.query).toContain("LIMIT 100");
|
|
52
|
+
});
|
|
53
|
+
it("uses all defaults when params are empty", () => {
|
|
54
|
+
const result = expandPreset(preset, {});
|
|
55
|
+
expect(result.query).toBe("SELECT * FROM campaign WHERE segments.date DURING LAST_30_DAYS LIMIT 100");
|
|
56
|
+
});
|
|
57
|
+
it("replaces multiple occurrences of the same placeholder", () => {
|
|
58
|
+
const multiPlaceholder = {
|
|
59
|
+
name: "multi",
|
|
60
|
+
description: "Multiple placeholders",
|
|
61
|
+
gaqlTemplate: "{dateRange} and {dateRange} LIMIT {limit}",
|
|
62
|
+
defaultDateRange: "LAST_30_DAYS",
|
|
63
|
+
defaultLimit: 50,
|
|
64
|
+
};
|
|
65
|
+
const result = expandPreset(multiPlaceholder, { dateRange: "TODAY" });
|
|
66
|
+
expect(result.query).toBe("TODAY and TODAY LIMIT 50");
|
|
67
|
+
});
|
|
68
|
+
it("returns dateRangeError for invalid date range", () => {
|
|
69
|
+
const result = expandPreset(preset, { dateRange: "DROP TABLE; --" });
|
|
70
|
+
expect(result.dateRangeError).toBeDefined();
|
|
71
|
+
expect(result.query).toBe("");
|
|
72
|
+
});
|
|
73
|
+
it("accepts BETWEEN date ranges", () => {
|
|
74
|
+
const result = expandPreset(preset, { dateRange: "BETWEEN '2024-01-01' AND '2024-06-30'" });
|
|
75
|
+
expect(result.dateRangeError).toBeUndefined();
|
|
76
|
+
expect(result.query).toContain("BETWEEN '2024-01-01' AND '2024-06-30'");
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=presets.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.test.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/presets.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export declare const queryCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly query: {
|
|
3
|
+
readonly type: "positional";
|
|
4
|
+
readonly description: "GAQL query string";
|
|
5
|
+
readonly required: false;
|
|
6
|
+
};
|
|
7
|
+
readonly "customer-id": {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "Google Ads customer ID (10 digits, no dashes)";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
readonly preset: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly description: "Named query preset";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
};
|
|
17
|
+
readonly "date-range": {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
readonly description: "Date range override for presets";
|
|
20
|
+
readonly required: false;
|
|
21
|
+
};
|
|
22
|
+
readonly limit: {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
readonly description: "Max rows (default 200)";
|
|
25
|
+
readonly required: false;
|
|
26
|
+
};
|
|
27
|
+
readonly "list-presets": {
|
|
28
|
+
readonly type: "boolean";
|
|
29
|
+
readonly description: "List available presets";
|
|
30
|
+
readonly required: false;
|
|
31
|
+
};
|
|
32
|
+
readonly cursor: {
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
readonly description: "Pagination cursor";
|
|
35
|
+
readonly required: false;
|
|
36
|
+
};
|
|
37
|
+
readonly all: {
|
|
38
|
+
readonly type: "boolean";
|
|
39
|
+
readonly description: "Auto-paginate all results";
|
|
40
|
+
readonly required: false;
|
|
41
|
+
};
|
|
42
|
+
readonly out: {
|
|
43
|
+
readonly type: "string";
|
|
44
|
+
readonly description: "File path for output";
|
|
45
|
+
readonly required: false;
|
|
46
|
+
};
|
|
47
|
+
readonly append: {
|
|
48
|
+
readonly type: "boolean";
|
|
49
|
+
readonly description: "Append to file";
|
|
50
|
+
readonly required: false;
|
|
51
|
+
};
|
|
52
|
+
readonly output: {
|
|
53
|
+
readonly type: "string";
|
|
54
|
+
readonly description: "Format: json|csv|jsonl|md";
|
|
55
|
+
readonly required: false;
|
|
56
|
+
readonly default: "json";
|
|
57
|
+
};
|
|
58
|
+
readonly "no-cache": {
|
|
59
|
+
readonly type: "boolean";
|
|
60
|
+
readonly description: "Skip cache";
|
|
61
|
+
readonly required: false;
|
|
62
|
+
};
|
|
63
|
+
readonly "clear-cache": {
|
|
64
|
+
readonly type: "boolean";
|
|
65
|
+
readonly description: "Clear cache";
|
|
66
|
+
readonly required: false;
|
|
67
|
+
};
|
|
68
|
+
}>;
|
|
69
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../../src/commands/ads/google/query.ts"],"names":[],"mappings":"AAySA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6DvB,CAAC"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
import { ApiError, apiPost } from "../../../client.js";
|
|
5
|
+
import { registerSchema } from "../../../schemas.js";
|
|
6
|
+
import { buildQueryCacheKey, cacheGet, cacheSet, getManagerIdForCustomer, getQueryTtl } from "../cache.js";
|
|
7
|
+
import { getFieldDescriptions } from "../field-descriptions.js";
|
|
8
|
+
import { resolveCustomerId, toCsvRow, writeAdsJson } from "../output.js";
|
|
9
|
+
import { parseApiError } from "./error-parser.js";
|
|
10
|
+
import { validatePreflight } from "./preflight.js";
|
|
11
|
+
import { expandPreset, getPreset, PRESETS } from "./presets.js";
|
|
12
|
+
registerSchema({
|
|
13
|
+
command: "ads.google.query",
|
|
14
|
+
description: "Run a GAQL (Google Ads Query Language) query. The most powerful command — supports any valid SELECT statement. Use --preset for common queries without writing GAQL.",
|
|
15
|
+
args: {
|
|
16
|
+
query: { type: "string", description: "GAQL SELECT query string", required: false },
|
|
17
|
+
"customer-id": {
|
|
18
|
+
type: "string",
|
|
19
|
+
description: "Google Ads customer ID (10 digits, no dashes). Falls back to BAKER_GOOGLE_ADS_CUSTOMER_ID env var.",
|
|
20
|
+
required: false,
|
|
21
|
+
},
|
|
22
|
+
preset: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Named query preset (campaign-performance, keyword-analysis, search-terms, ad-copy-performance, asset-performance, shopping-products, account-summary)",
|
|
25
|
+
required: false,
|
|
26
|
+
},
|
|
27
|
+
"date-range": {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Date range for presets (LAST_7_DAYS, LAST_30_DAYS, LAST_90_DAYS, or BETWEEN 'X' AND 'Y')",
|
|
30
|
+
required: false,
|
|
31
|
+
},
|
|
32
|
+
limit: { type: "number", description: "Max rows (default 200)", required: false, default: 200 },
|
|
33
|
+
"list-presets": { type: "boolean", description: "List all available query presets", required: false },
|
|
34
|
+
cursor: { type: "string", description: "Pagination cursor from previous response", required: false },
|
|
35
|
+
all: {
|
|
36
|
+
type: "boolean",
|
|
37
|
+
description: "Auto-paginate all results (use with --out for large datasets)",
|
|
38
|
+
required: false,
|
|
39
|
+
},
|
|
40
|
+
out: {
|
|
41
|
+
type: "string",
|
|
42
|
+
description: "Write data to file (format from extension: .csv, .jsonl, .json)",
|
|
43
|
+
required: false,
|
|
44
|
+
},
|
|
45
|
+
append: { type: "boolean", description: "Append to existing file (skip CSV headers)", required: false },
|
|
46
|
+
output: {
|
|
47
|
+
type: "string",
|
|
48
|
+
description: "Output format: json|csv|jsonl|md",
|
|
49
|
+
required: false,
|
|
50
|
+
default: "json",
|
|
51
|
+
enum: ["json", "csv", "jsonl", "md"],
|
|
52
|
+
},
|
|
53
|
+
"no-cache": { type: "boolean", description: "Skip cache, hit API directly", required: false },
|
|
54
|
+
"clear-cache": { type: "boolean", description: "Clear cached data", required: false },
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
function extractFields(rows) {
|
|
58
|
+
if (rows.length === 0)
|
|
59
|
+
return [];
|
|
60
|
+
const first = rows[0];
|
|
61
|
+
return first ? Object.keys(first) : [];
|
|
62
|
+
}
|
|
63
|
+
function writeRowsToFile(filePath, rows, fields, append) {
|
|
64
|
+
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
65
|
+
if (ext === "csv") {
|
|
66
|
+
if (!append || !existsSync(filePath)) {
|
|
67
|
+
writeFileSync(filePath, `${toCsvRow(fields)}\n`, "utf-8");
|
|
68
|
+
}
|
|
69
|
+
const csvRows = rows.map((row) => toCsvRow(fields.map((f) => String(row[f] ?? ""))));
|
|
70
|
+
appendFileSync(filePath, `${csvRows.join("\n")}\n`, "utf-8");
|
|
71
|
+
}
|
|
72
|
+
else if (ext === "jsonl") {
|
|
73
|
+
const lines = rows.map((row) => JSON.stringify(row));
|
|
74
|
+
if (append && existsSync(filePath)) {
|
|
75
|
+
appendFileSync(filePath, `${lines.join("\n")}\n`, "utf-8");
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
writeFileSync(filePath, `${lines.join("\n")}\n`, "utf-8");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (append && existsSync(filePath)) {
|
|
82
|
+
const existing = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
83
|
+
writeFileSync(filePath, JSON.stringify([...existing, ...rows], null, 2), "utf-8");
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
writeFileSync(filePath, JSON.stringify(rows, null, 2), "utf-8");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function outputResults(rows, fieldDescs, warnings, args, cached, nextCursor) {
|
|
90
|
+
const format = args.output || "json";
|
|
91
|
+
const fields = Object.keys(rows[0] ?? {});
|
|
92
|
+
if (format === "csv") {
|
|
93
|
+
process.stdout.write(`${toCsvRow(fields)}\n`);
|
|
94
|
+
for (const row of rows) {
|
|
95
|
+
process.stdout.write(`${toCsvRow(fields.map((f) => String(row[f] ?? "")))}\n`);
|
|
96
|
+
}
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (format === "jsonl") {
|
|
100
|
+
for (const row of rows) {
|
|
101
|
+
process.stdout.write(`${JSON.stringify(row)}\n`);
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (format === "md") {
|
|
106
|
+
process.stdout.write(`| ${fields.join(" | ")} |\n`);
|
|
107
|
+
process.stdout.write(`| ${fields.map(() => "---").join(" | ")} |\n`);
|
|
108
|
+
for (const row of rows) {
|
|
109
|
+
process.stdout.write(`| ${fields.map((f) => String(row[f] ?? "")).join(" | ")} |\n`);
|
|
110
|
+
}
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const envelope = { ok: true, data: rows, fields: fieldDescs };
|
|
114
|
+
if (nextCursor) {
|
|
115
|
+
envelope.pagination = { hasMore: true, cursor: nextCursor };
|
|
116
|
+
}
|
|
117
|
+
if (warnings.length > 0) {
|
|
118
|
+
envelope.warnings = warnings;
|
|
119
|
+
}
|
|
120
|
+
if (cached) {
|
|
121
|
+
envelope.cached = true;
|
|
122
|
+
}
|
|
123
|
+
writeAdsJson(envelope);
|
|
124
|
+
}
|
|
125
|
+
function resolveGaql(args, limit) {
|
|
126
|
+
if (args.preset) {
|
|
127
|
+
const preset = getPreset(args.preset);
|
|
128
|
+
if (!preset) {
|
|
129
|
+
const available = PRESETS.map((p) => p.name).join(", ");
|
|
130
|
+
writeAdsJson({
|
|
131
|
+
ok: false,
|
|
132
|
+
error: { code: "VALIDATION_ERROR", message: `Unknown preset: "${args.preset}". Available: ${available}` },
|
|
133
|
+
});
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const expanded = expandPreset(preset, { dateRange: args["date-range"], limit });
|
|
137
|
+
if (expanded.dateRangeError) {
|
|
138
|
+
writeAdsJson({
|
|
139
|
+
ok: false,
|
|
140
|
+
error: { code: "VALIDATION_ERROR", message: expanded.dateRangeError },
|
|
141
|
+
});
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return expanded.query;
|
|
145
|
+
}
|
|
146
|
+
const gaql = args.query ?? "";
|
|
147
|
+
if (!gaql) {
|
|
148
|
+
writeAdsJson({
|
|
149
|
+
ok: false,
|
|
150
|
+
error: {
|
|
151
|
+
code: "VALIDATION_ERROR",
|
|
152
|
+
message: "Provide a GAQL query or use --preset. Run --list-presets to see options.",
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
return gaql;
|
|
158
|
+
}
|
|
159
|
+
async function fetchAllPages(body, args) {
|
|
160
|
+
let allRows = [];
|
|
161
|
+
let pageToken = args.cursor;
|
|
162
|
+
let totalRowsWritten = 0;
|
|
163
|
+
do {
|
|
164
|
+
const requestBody = { ...body };
|
|
165
|
+
if (pageToken)
|
|
166
|
+
requestBody.pageToken = pageToken;
|
|
167
|
+
const response = await apiPost("/api/ads/google/query", requestBody);
|
|
168
|
+
const rows = response.rows ?? [];
|
|
169
|
+
pageToken = response.pageToken;
|
|
170
|
+
if (args.out) {
|
|
171
|
+
const filePath = resolve(args.out);
|
|
172
|
+
const shouldAppend = args.append || totalRowsWritten > 0;
|
|
173
|
+
writeRowsToFile(filePath, rows, extractFields(rows), shouldAppend);
|
|
174
|
+
totalRowsWritten += rows.length;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
allRows = allRows.concat(rows);
|
|
178
|
+
}
|
|
179
|
+
if (!args.all)
|
|
180
|
+
break;
|
|
181
|
+
} while (pageToken);
|
|
182
|
+
return { allRows, lastPageToken: pageToken, totalRowsWritten };
|
|
183
|
+
}
|
|
184
|
+
async function executeQuery(finalQuery, args, customerId, limit, warnings, useCache, cacheKey) {
|
|
185
|
+
const body = { customerId, query: finalQuery, pageSize: limit };
|
|
186
|
+
const managerId = getManagerIdForCustomer(customerId);
|
|
187
|
+
if (managerId)
|
|
188
|
+
body.managerId = managerId;
|
|
189
|
+
if (args.cursor)
|
|
190
|
+
body.pageToken = args.cursor;
|
|
191
|
+
const { allRows, lastPageToken, totalRowsWritten } = await fetchAllPages(body, args);
|
|
192
|
+
if (args.out) {
|
|
193
|
+
const summary = { ok: true, fields: {}, file: resolve(args.out), rows: totalRowsWritten };
|
|
194
|
+
writeAdsJson(summary);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (useCache && allRows.length > 0) {
|
|
198
|
+
const fields = extractFields(allRows);
|
|
199
|
+
cacheSet("queries", cacheKey, allRows, getQueryTtl(finalQuery), getFieldDescriptions(fields));
|
|
200
|
+
}
|
|
201
|
+
const fields = extractFields(allRows);
|
|
202
|
+
outputResults(allRows, getFieldDescriptions(fields), warnings, args, false, lastPageToken);
|
|
203
|
+
}
|
|
204
|
+
function validateArgs(args) {
|
|
205
|
+
const customerId = resolveCustomerId(args);
|
|
206
|
+
const limit = args.limit ? Number(args.limit) : 200;
|
|
207
|
+
const gaql = resolveGaql(args, limit);
|
|
208
|
+
if (!gaql) {
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
const preflight = validatePreflight(gaql, customerId, limit);
|
|
212
|
+
if (!preflight.valid && preflight.error) {
|
|
213
|
+
writeAdsJson(preflight.error);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
const finalQuery = preflight.correctedQuery ?? gaql;
|
|
217
|
+
return {
|
|
218
|
+
customerId,
|
|
219
|
+
limit,
|
|
220
|
+
finalQuery,
|
|
221
|
+
warnings: preflight.warnings,
|
|
222
|
+
useCache: !args["no-cache"],
|
|
223
|
+
cacheKey: buildQueryCacheKey(customerId, finalQuery),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function handleQueryError(err, finalQuery, customerId) {
|
|
227
|
+
if (err instanceof ApiError) {
|
|
228
|
+
const envelope = parseApiError(err.message, finalQuery, customerId);
|
|
229
|
+
envelope.error.gaqlExecuted = finalQuery;
|
|
230
|
+
writeAdsJson(envelope);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
writeAdsJson({
|
|
234
|
+
ok: false,
|
|
235
|
+
error: {
|
|
236
|
+
code: "NETWORK_ERROR",
|
|
237
|
+
message: err instanceof Error ? err.message : "Unexpected error",
|
|
238
|
+
fix: { action: "wait_and_retry", explanation: "Network error — check connectivity and retry" },
|
|
239
|
+
retryable: true,
|
|
240
|
+
gaqlExecuted: finalQuery,
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
export const queryCommand = defineCommand({
|
|
246
|
+
meta: {
|
|
247
|
+
name: "query",
|
|
248
|
+
description: `Run GAQL queries against Google Ads. Supports raw GAQL, presets, pagination, file export, and caching.
|
|
249
|
+
|
|
250
|
+
Examples:
|
|
251
|
+
baker ads google query "SELECT campaign.name, metrics.clicks FROM campaign WHERE segments.date DURING LAST_7_DAYS" --customer-id 1234567890
|
|
252
|
+
baker ads google query --preset campaign-performance --customer-id 1234567890
|
|
253
|
+
baker ads google query --preset search-terms --customer-id 1234567890 --date-range LAST_7_DAYS --out results.csv
|
|
254
|
+
baker ads google query --list-presets`,
|
|
255
|
+
},
|
|
256
|
+
args: {
|
|
257
|
+
query: { type: "positional", description: "GAQL query string", required: false },
|
|
258
|
+
"customer-id": { type: "string", description: "Google Ads customer ID (10 digits, no dashes)", required: false },
|
|
259
|
+
preset: { type: "string", description: "Named query preset", required: false },
|
|
260
|
+
"date-range": { type: "string", description: "Date range override for presets", required: false },
|
|
261
|
+
limit: { type: "string", description: "Max rows (default 200)", required: false },
|
|
262
|
+
"list-presets": { type: "boolean", description: "List available presets", required: false },
|
|
263
|
+
cursor: { type: "string", description: "Pagination cursor", required: false },
|
|
264
|
+
all: { type: "boolean", description: "Auto-paginate all results", required: false },
|
|
265
|
+
out: { type: "string", description: "File path for output", required: false },
|
|
266
|
+
append: { type: "boolean", description: "Append to file", required: false },
|
|
267
|
+
output: { type: "string", description: "Format: json|csv|jsonl|md", required: false, default: "json" },
|
|
268
|
+
"no-cache": { type: "boolean", description: "Skip cache", required: false },
|
|
269
|
+
"clear-cache": { type: "boolean", description: "Clear cache", required: false },
|
|
270
|
+
},
|
|
271
|
+
run: async ({ args }) => {
|
|
272
|
+
if (args["list-presets"]) {
|
|
273
|
+
writeAdsJson({
|
|
274
|
+
ok: true,
|
|
275
|
+
data: PRESETS.map((p) => ({ name: p.name, description: p.description, defaultDateRange: p.defaultDateRange })),
|
|
276
|
+
});
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (args["clear-cache"]) {
|
|
280
|
+
const { cacheClear } = await import("../cache.js");
|
|
281
|
+
cacheClear();
|
|
282
|
+
writeAdsJson({ ok: true, data: { message: "Cache cleared" } });
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
const validated = validateArgs(args);
|
|
286
|
+
if (!validated)
|
|
287
|
+
return;
|
|
288
|
+
const { customerId, limit, finalQuery, warnings, useCache, cacheKey } = validated;
|
|
289
|
+
if (useCache) {
|
|
290
|
+
const cached = cacheGet("queries", cacheKey);
|
|
291
|
+
if (cached) {
|
|
292
|
+
const fields = extractFields(cached.data);
|
|
293
|
+
outputResults(cached.data, cached.fields ?? getFieldDescriptions(fields), warnings, args, true);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
await executeQuery(finalQuery, args, customerId, limit, warnings, useCache, cacheKey);
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
handleQueryError(err, finalQuery, customerId);
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../../../src/commands/ads/google/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,qDAerB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { googleCommand } from "./google/index.js";
|
|
3
|
+
export const adsCommand = defineCommand({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "ads",
|
|
6
|
+
description: `Ad platform commands. Currently supports Google Ads. More platforms coming soon.
|
|
7
|
+
|
|
8
|
+
Platforms:
|
|
9
|
+
google — Google Ads (GAQL queries, keywords, accounts)
|
|
10
|
+
|
|
11
|
+
Examples:
|
|
12
|
+
baker ads google accounts
|
|
13
|
+
baker ads google query --preset campaign-performance --customer-id 1234567890`,
|
|
14
|
+
},
|
|
15
|
+
subCommands: {
|
|
16
|
+
google: googleCommand,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/ads/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;IACtC,IAAI,EAAE;QACJ,IAAI,EAAE,KAAK;QACX,WAAW,EAAE;;;;;;;gFAO+D;KAC7E;IACD,WAAW,EAAE;QACX,MAAM,EAAE,aAAa;KACtB;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AdsErrorEnvelope, AdsFileSummary, AdsSuccessEnvelope } from "./types.ts";
|
|
2
|
+
type AdsOutput = AdsSuccessEnvelope<unknown> | AdsErrorEnvelope | AdsFileSummary | {
|
|
3
|
+
ok: true;
|
|
4
|
+
data: unknown;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
error: {
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare function writeAdsJson(envelope: AdsOutput): void;
|
|
13
|
+
export declare function toCsvRow(values: string[]): string;
|
|
14
|
+
export declare function writeAdsOutput(data: Array<Record<string, unknown>>, format: string, fields?: string[]): void;
|
|
15
|
+
export declare function resolveCustomerId(args: Record<string, unknown>): string;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/output.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvF,KAAK,SAAS,GACV,kBAAkB,CAAC,OAAO,CAAC,GAC3B,gBAAgB,GAChB,cAAc,GACd;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC3B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAE5D,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,GAAG,IAAI,CAEtD;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CASjD;AAqCD,wBAAgB,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAc5G;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAevE"}
|