@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.
- package/README.md +655 -162
- package/dist/cli.js +9 -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/commands/testimonials/get.d.ts +30 -0
- package/dist/commands/testimonials/get.d.ts.map +1 -0
- package/dist/commands/testimonials/get.js +42 -0
- package/dist/commands/testimonials/get.js.map +1 -0
- package/dist/commands/testimonials/index.d.ts +2 -0
- package/dist/commands/testimonials/index.d.ts.map +1 -0
- package/dist/commands/testimonials/index.js +22 -0
- package/dist/commands/testimonials/index.js.map +1 -0
- package/dist/commands/testimonials/list.d.ts +60 -0
- package/dist/commands/testimonials/list.d.ts.map +1 -0
- package/dist/commands/testimonials/list.js +69 -0
- package/dist/commands/testimonials/list.js.map +1 -0
- package/dist/commands/testimonials/search.d.ts +40 -0
- package/dist/commands/testimonials/search.d.ts.map +1 -0
- package/dist/commands/testimonials/search.js +59 -0
- package/dist/commands/testimonials/search.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/dist/output.d.ts +1 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +37 -0
- package/dist/output.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { getEnv } from "../../env.js";
|
|
2
|
+
export function writeAdsJson(envelope) {
|
|
3
|
+
process.stdout.write(`${JSON.stringify(envelope, null, 2)}\n`);
|
|
4
|
+
}
|
|
5
|
+
export function toCsvRow(values) {
|
|
6
|
+
return values
|
|
7
|
+
.map((v) => {
|
|
8
|
+
if (v.includes(",") || v.includes('"') || v.includes("\n")) {
|
|
9
|
+
return `"${v.replace(/"/g, '""')}"`;
|
|
10
|
+
}
|
|
11
|
+
return v;
|
|
12
|
+
})
|
|
13
|
+
.join(",");
|
|
14
|
+
}
|
|
15
|
+
function flattenRow(row) {
|
|
16
|
+
const flat = {};
|
|
17
|
+
for (const [key, val] of Object.entries(row)) {
|
|
18
|
+
flat[key] = typeof val === "object" && val !== null ? JSON.stringify(val) : String(val ?? "");
|
|
19
|
+
}
|
|
20
|
+
return flat;
|
|
21
|
+
}
|
|
22
|
+
function writeAdsCsv(data, fields) {
|
|
23
|
+
if (data.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
const cols = fields ?? Object.keys(data[0] ?? {});
|
|
26
|
+
process.stdout.write(`${toCsvRow(cols)}\n`);
|
|
27
|
+
for (const row of data) {
|
|
28
|
+
const flat = flattenRow(row);
|
|
29
|
+
process.stdout.write(`${toCsvRow(cols.map((f) => flat[f] ?? ""))}\n`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function writeAdsJsonl(data) {
|
|
33
|
+
for (const row of data) {
|
|
34
|
+
process.stdout.write(`${JSON.stringify(row)}\n`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function writeAdsMd(data, fields) {
|
|
38
|
+
if (data.length === 0)
|
|
39
|
+
return;
|
|
40
|
+
const cols = fields ?? Object.keys(data[0] ?? {});
|
|
41
|
+
process.stdout.write(`| ${cols.join(" | ")} |\n`);
|
|
42
|
+
process.stdout.write(`| ${cols.map(() => "---").join(" | ")} |\n`);
|
|
43
|
+
for (const row of data) {
|
|
44
|
+
const flat = flattenRow(row);
|
|
45
|
+
process.stdout.write(`| ${cols.map((f) => flat[f] ?? "").join(" | ")} |\n`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function writeAdsOutput(data, format, fields) {
|
|
49
|
+
switch (format) {
|
|
50
|
+
case "csv":
|
|
51
|
+
writeAdsCsv(data, fields);
|
|
52
|
+
break;
|
|
53
|
+
case "jsonl":
|
|
54
|
+
writeAdsJsonl(data);
|
|
55
|
+
break;
|
|
56
|
+
case "md":
|
|
57
|
+
writeAdsMd(data, fields);
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
writeAdsJson({ ok: true, data });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function resolveCustomerId(args) {
|
|
64
|
+
const fromArgs = args["customer-id"];
|
|
65
|
+
const customerId = fromArgs || getEnv().BAKER_GOOGLE_ADS_CUSTOMER_ID;
|
|
66
|
+
if (!customerId || !/^\d{10}$/.test(customerId)) {
|
|
67
|
+
writeAdsJson({
|
|
68
|
+
ok: false,
|
|
69
|
+
error: {
|
|
70
|
+
code: "INVALID_CUSTOMER_ID",
|
|
71
|
+
message: "Customer ID must be exactly 10 digits without dashes. Pass --customer-id or set BAKER_GOOGLE_ADS_CUSTOMER_ID.",
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
return customerId;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/commands/ads/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAUtC,MAAM,UAAU,YAAY,CAAC,QAAmB;IAC9C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAgB;IACvC,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;QACtC,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,GAA4B;IAC9C,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,IAAoC,EAAE,MAAiB;IAC1E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACxE,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAoC;IACzD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,IAAoC,EAAE,MAAiB;IACzE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACnE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAoC,EAAE,MAAc,EAAE,MAAiB;IACpG,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,KAAK;YACR,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC1B,MAAM;QACR,KAAK,OAAO;YACV,aAAa,CAAC,IAAI,CAAC,CAAC;YACpB,MAAM;QACR,KAAK,IAAI;YACP,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACzB,MAAM;QACR;YACE,YAAY,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAA6B;IAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAuB,CAAC;IAC3D,MAAM,UAAU,GAAG,QAAQ,IAAI,MAAM,EAAE,CAAC,4BAA4B,CAAC;IACrE,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,YAAY,CAAC;YACX,EAAE,EAAE,KAAK;YACT,KAAK,EAAE;gBACL,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EACL,+GAA+G;aAClH;SACF,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.test.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/output.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { toCsvRow, writeAdsJson, writeAdsOutput } from "./output.js";
|
|
3
|
+
describe("toCsvRow", () => {
|
|
4
|
+
it("joins simple values with commas", () => {
|
|
5
|
+
expect(toCsvRow(["a", "b", "c"])).toBe("a,b,c");
|
|
6
|
+
});
|
|
7
|
+
it("wraps values containing commas in double quotes", () => {
|
|
8
|
+
expect(toCsvRow(["hello, world", "plain"])).toBe('"hello, world",plain');
|
|
9
|
+
});
|
|
10
|
+
it("wraps values containing double quotes and escapes them", () => {
|
|
11
|
+
expect(toCsvRow(['say "hi"'])).toBe('"say ""hi"""');
|
|
12
|
+
});
|
|
13
|
+
it("wraps values containing newlines in double quotes", () => {
|
|
14
|
+
expect(toCsvRow(["line1\nline2"])).toBe('"line1\nline2"');
|
|
15
|
+
});
|
|
16
|
+
it("handles empty values", () => {
|
|
17
|
+
expect(toCsvRow(["", "a", ""])).toBe(",a,");
|
|
18
|
+
});
|
|
19
|
+
it("handles a single value", () => {
|
|
20
|
+
expect(toCsvRow(["only"])).toBe("only");
|
|
21
|
+
});
|
|
22
|
+
it("handles values with both commas and quotes", () => {
|
|
23
|
+
expect(toCsvRow(['value "with", special'])).toBe('"value ""with"", special"');
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
describe("writeAdsJson", () => {
|
|
27
|
+
let writeSpy;
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
writeSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true);
|
|
30
|
+
});
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
writeSpy.mockRestore();
|
|
33
|
+
});
|
|
34
|
+
it("outputs JSON with trailing newline", () => {
|
|
35
|
+
writeAdsJson({ ok: true, data: { message: "test" } });
|
|
36
|
+
expect(writeSpy).toHaveBeenCalledTimes(1);
|
|
37
|
+
const output = writeSpy.mock.calls[0]?.[0];
|
|
38
|
+
expect(output.endsWith("\n")).toBe(true);
|
|
39
|
+
expect(JSON.parse(output)).toEqual({ ok: true, data: { message: "test" } });
|
|
40
|
+
});
|
|
41
|
+
it("pretty-prints with 2-space indentation", () => {
|
|
42
|
+
writeAdsJson({ ok: true, data: [1] });
|
|
43
|
+
const output = writeSpy.mock.calls[0]?.[0];
|
|
44
|
+
expect(output).toContain(" ");
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe("writeAdsOutput", () => {
|
|
48
|
+
let writeSpy;
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
writeSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true);
|
|
51
|
+
});
|
|
52
|
+
afterEach(() => {
|
|
53
|
+
writeSpy.mockRestore();
|
|
54
|
+
});
|
|
55
|
+
it("outputs CSV with header row and data rows", () => {
|
|
56
|
+
writeAdsOutput([{ name: "Campaign A", clicks: 100 }], "csv");
|
|
57
|
+
const output = writeSpy.mock.calls.map((c) => c[0]).join("");
|
|
58
|
+
const lines = output.trim().split("\n");
|
|
59
|
+
expect(lines[0]).toBe("name,clicks");
|
|
60
|
+
expect(lines[1]).toBe("Campaign A,100");
|
|
61
|
+
});
|
|
62
|
+
it("outputs CSV with specified field order", () => {
|
|
63
|
+
writeAdsOutput([{ name: "Campaign A", clicks: 100 }], "csv", ["clicks", "name"]);
|
|
64
|
+
const output = writeSpy.mock.calls.map((c) => c[0]).join("");
|
|
65
|
+
const lines = output.trim().split("\n");
|
|
66
|
+
expect(lines[0]).toBe("clicks,name");
|
|
67
|
+
expect(lines[1]).toBe("100,Campaign A");
|
|
68
|
+
});
|
|
69
|
+
it("outputs JSONL with one JSON object per line", () => {
|
|
70
|
+
writeAdsOutput([{ id: 1 }, { id: 2 }], "jsonl");
|
|
71
|
+
const output = writeSpy.mock.calls.map((c) => c[0]).join("");
|
|
72
|
+
const lines = output.trim().split("\n");
|
|
73
|
+
expect(JSON.parse(lines[0] ?? "")).toEqual({ id: 1 });
|
|
74
|
+
expect(JSON.parse(lines[1] ?? "")).toEqual({ id: 2 });
|
|
75
|
+
});
|
|
76
|
+
it("outputs markdown table format", () => {
|
|
77
|
+
writeAdsOutput([{ name: "Test", value: "42" }], "md");
|
|
78
|
+
const output = writeSpy.mock.calls.map((c) => c[0]).join("");
|
|
79
|
+
expect(output).toContain("| name | value |");
|
|
80
|
+
expect(output).toContain("| --- | --- |");
|
|
81
|
+
expect(output).toContain("| Test | 42 |");
|
|
82
|
+
});
|
|
83
|
+
it("falls back to JSON for unknown format", () => {
|
|
84
|
+
writeAdsOutput([{ id: 1 }], "unknown");
|
|
85
|
+
const output = writeSpy.mock.calls.map((c) => c[0]).join("");
|
|
86
|
+
const parsed = JSON.parse(output);
|
|
87
|
+
expect(parsed.ok).toBe(true);
|
|
88
|
+
expect(parsed.data).toEqual([{ id: 1 }]);
|
|
89
|
+
});
|
|
90
|
+
it("handles empty data arrays for CSV", () => {
|
|
91
|
+
writeAdsOutput([], "csv");
|
|
92
|
+
expect(writeSpy).not.toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
it("flattens nested objects to JSON strings in CSV", () => {
|
|
95
|
+
writeAdsOutput([{ name: "A", details: { foo: "bar" } }], "csv");
|
|
96
|
+
const output = writeSpy.mock.calls.map((c) => c[0]).join("");
|
|
97
|
+
expect(output).toContain('"{""foo"":""bar""}"');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=output.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.test.js","sourceRoot":"","sources":["../../../src/commands/ads/output.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
type FixAction = "retry_with_modified_query" | "retry_with_flag" | "use_different_resource" | "add_required_field" | "change_operator" | "narrow_date_range" | "split_query" | "authenticate" | "wait_and_retry" | "reject";
|
|
2
|
+
export interface QueryFix {
|
|
3
|
+
action: FixAction;
|
|
4
|
+
correctedCommand?: string;
|
|
5
|
+
explanation: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AdsWarning {
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AdsSuccessEnvelope<T> {
|
|
12
|
+
ok: true;
|
|
13
|
+
data: T;
|
|
14
|
+
fields?: Record<string, string>;
|
|
15
|
+
pagination?: {
|
|
16
|
+
hasMore: boolean;
|
|
17
|
+
cursor: string;
|
|
18
|
+
};
|
|
19
|
+
warnings?: AdsWarning[];
|
|
20
|
+
cached?: true;
|
|
21
|
+
}
|
|
22
|
+
export interface AdsErrorEnvelope {
|
|
23
|
+
ok: false;
|
|
24
|
+
error: {
|
|
25
|
+
code: string;
|
|
26
|
+
message: string;
|
|
27
|
+
fix: QueryFix;
|
|
28
|
+
retryable: boolean;
|
|
29
|
+
retryAfterMs?: number;
|
|
30
|
+
gaqlExecuted?: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface AdsFileSummary {
|
|
34
|
+
ok: true;
|
|
35
|
+
fields: Record<string, string>;
|
|
36
|
+
file: string;
|
|
37
|
+
rows: number;
|
|
38
|
+
cached?: true;
|
|
39
|
+
}
|
|
40
|
+
export interface CorrectionContext {
|
|
41
|
+
originalQuery: string;
|
|
42
|
+
customerId: string;
|
|
43
|
+
apiErrorMessage?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface CorrectionRule {
|
|
46
|
+
matchQuery?: RegExp;
|
|
47
|
+
matchApiError?: RegExp;
|
|
48
|
+
fix: (ctx: CorrectionContext) => QueryFix;
|
|
49
|
+
}
|
|
50
|
+
export interface PreflightResult {
|
|
51
|
+
valid: boolean;
|
|
52
|
+
error?: AdsErrorEnvelope;
|
|
53
|
+
correctedQuery?: string;
|
|
54
|
+
warnings: AdsWarning[];
|
|
55
|
+
}
|
|
56
|
+
export interface CacheEntry<T> {
|
|
57
|
+
expiresAt: number;
|
|
58
|
+
data: T;
|
|
59
|
+
fields?: Record<string, string>;
|
|
60
|
+
}
|
|
61
|
+
export interface PresetDefinition {
|
|
62
|
+
name: string;
|
|
63
|
+
description: string;
|
|
64
|
+
gaqlTemplate: string;
|
|
65
|
+
defaultDateRange: string;
|
|
66
|
+
defaultLimit: number;
|
|
67
|
+
}
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/commands/ads/types.ts"],"names":[],"mappings":"AAAA,KAAK,SAAS,GACV,2BAA2B,GAC3B,iBAAiB,GACjB,wBAAwB,GACxB,oBAAoB,GACpB,iBAAiB,GACjB,mBAAmB,GACnB,aAAa,GACb,cAAc,GACd,gBAAgB,GAChB,QAAQ,CAAC;AAEb,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,QAAQ,CAAC;QACd,SAAS,EAAE,OAAO,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,IAAI,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,QAAQ,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/commands/ads/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare const advertisersCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly keyword: {
|
|
3
|
+
readonly type: "positional";
|
|
4
|
+
readonly description: "Keyword to search";
|
|
5
|
+
readonly required: true;
|
|
6
|
+
};
|
|
7
|
+
readonly location: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "Country code or location code (default: us)";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
readonly language: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly description: "Language code or name (default: en)";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
};
|
|
17
|
+
readonly limit: {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
readonly description: "Max results (default: 20, max: 100)";
|
|
20
|
+
readonly required: false;
|
|
21
|
+
};
|
|
22
|
+
readonly output: {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
readonly description: "Format: json|csv|md|jsonl";
|
|
25
|
+
readonly required: false;
|
|
26
|
+
readonly default: "json";
|
|
27
|
+
};
|
|
28
|
+
}>;
|
|
29
|
+
//# sourceMappingURL=advertisers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advertisers.d.ts","sourceRoot":"","sources":["../../../src/commands/research/advertisers.ts"],"names":[],"mappings":"AAyCA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyC7B,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiPost } from "../../client.js";
|
|
3
|
+
import { registerSchema } from "../../schemas.js";
|
|
4
|
+
import { handleResearchError, writeResearchJson, writeResearchOutput } from "./output.js";
|
|
5
|
+
registerSchema({
|
|
6
|
+
command: "research.advertisers",
|
|
7
|
+
description: "Find domains competing for a keyword in Google SERPs. Shows who's competing for the same search term with their visibility and estimated traffic.",
|
|
8
|
+
args: {
|
|
9
|
+
keyword: { type: "string", description: "Keyword to search (positional)", required: true },
|
|
10
|
+
location: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Country code (us, uk, es, de...) or DataForSEO location code. Default: us",
|
|
13
|
+
required: false,
|
|
14
|
+
},
|
|
15
|
+
language: {
|
|
16
|
+
type: "string",
|
|
17
|
+
description: "Language code or name (en, es, spanish...). Default: en",
|
|
18
|
+
required: false,
|
|
19
|
+
},
|
|
20
|
+
limit: { type: "string", description: "Max results (default: 20, max: 100)", required: false },
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
const FIELDS = {
|
|
24
|
+
domain: "Competing domain",
|
|
25
|
+
avg_position: "Average SERP position (1 = top)",
|
|
26
|
+
rating: "Domain relevance rating (0-100)",
|
|
27
|
+
etv: "Estimated traffic value (USD)",
|
|
28
|
+
visibility: "SERP visibility score (0-1)",
|
|
29
|
+
};
|
|
30
|
+
export const advertisersCommand = defineCommand({
|
|
31
|
+
meta: {
|
|
32
|
+
name: "advertisers",
|
|
33
|
+
description: `Find domains competing for a keyword in Google SERPs.
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
baker research advertisers "running shoes"
|
|
37
|
+
baker research advertisers "crm software" --location uk --limit 10
|
|
38
|
+
baker research advertisers "zapatos" --location es --language spanish`,
|
|
39
|
+
},
|
|
40
|
+
args: {
|
|
41
|
+
keyword: { type: "positional", description: "Keyword to search", required: true },
|
|
42
|
+
location: { type: "string", description: "Country code or location code (default: us)", required: false },
|
|
43
|
+
language: { type: "string", description: "Language code or name (default: en)", required: false },
|
|
44
|
+
limit: { type: "string", description: "Max results (default: 20, max: 100)", required: false },
|
|
45
|
+
output: { type: "string", description: "Format: json|csv|md|jsonl", required: false, default: "json" },
|
|
46
|
+
},
|
|
47
|
+
run: async ({ args }) => {
|
|
48
|
+
const keyword = args.keyword;
|
|
49
|
+
const location = args.location || undefined;
|
|
50
|
+
const language = args.language || undefined;
|
|
51
|
+
const limit = args.limit ? Number(args.limit) : undefined;
|
|
52
|
+
try {
|
|
53
|
+
const data = await apiPost("/api/research/advertisers", {
|
|
54
|
+
keyword,
|
|
55
|
+
location,
|
|
56
|
+
language,
|
|
57
|
+
limit,
|
|
58
|
+
});
|
|
59
|
+
const format = args.output || "json";
|
|
60
|
+
if (format !== "json") {
|
|
61
|
+
writeResearchOutput(data, format);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
writeResearchJson({ ok: true, data, fields: FIELDS });
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
handleResearchError(err);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=advertisers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advertisers.js","sourceRoot":"","sources":["../../../src/commands/research/advertisers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,eAAe,qDA0B1B,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { advertisersCommand } from "./advertisers.js";
|
|
3
|
+
import { intentCommand } from "./intent.js";
|
|
4
|
+
import { keywordGapCommand } from "./keyword-gap.js";
|
|
5
|
+
import { keywordsForSiteCommand } from "./keywords-for-site.js";
|
|
6
|
+
import { lighthouseCommand } from "./lighthouse.js";
|
|
7
|
+
export const researchCommand = defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "research",
|
|
10
|
+
description: `Competitive intelligence commands powered by DataForSEO. Shows market/competitor data — who's bidding on keywords, search intent, competitor keyword lists, keyword gaps, and landing page performance.
|
|
11
|
+
|
|
12
|
+
Commands:
|
|
13
|
+
advertisers — Who's bidding on a keyword?
|
|
14
|
+
intent — Google Search intent classification
|
|
15
|
+
keywords-for-site — Keywords a domain bids on
|
|
16
|
+
keyword-gap — Keywords they have that we don't
|
|
17
|
+
lighthouse — Landing page performance audit
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
baker research advertisers "running shoes"
|
|
21
|
+
baker research intent "buy running shoes,best running shoes 2026"
|
|
22
|
+
baker research keywords-for-site "competitor.com"
|
|
23
|
+
baker research keyword-gap "them.com" "us.com"
|
|
24
|
+
baker research lighthouse "https://example.com/landing"`,
|
|
25
|
+
},
|
|
26
|
+
subCommands: {
|
|
27
|
+
advertisers: advertisersCommand,
|
|
28
|
+
intent: intentCommand,
|
|
29
|
+
"keywords-for-site": keywordsForSiteCommand,
|
|
30
|
+
"keyword-gap": keywordGapCommand,
|
|
31
|
+
lighthouse: lighthouseCommand,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/research/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC;IAC3C,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE;;;;;;;;;;;;;;0DAcyC;KACvD;IACD,WAAW,EAAE;QACX,WAAW,EAAE,kBAAkB;QAC/B,MAAM,EAAE,aAAa;QACrB,mBAAmB,EAAE,sBAAsB;QAC3C,aAAa,EAAE,iBAAiB;QAChC,UAAU,EAAE,iBAAiB;KAC9B;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const intentCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly keywords: {
|
|
3
|
+
readonly type: "positional";
|
|
4
|
+
readonly description: "Comma-separated keywords";
|
|
5
|
+
readonly required: true;
|
|
6
|
+
};
|
|
7
|
+
readonly language: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "Language code or name (default: en)";
|
|
10
|
+
readonly required: false;
|
|
11
|
+
};
|
|
12
|
+
readonly output: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly description: "Format: json|csv|md|jsonl";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
readonly default: "json";
|
|
17
|
+
};
|
|
18
|
+
}>;
|
|
19
|
+
//# sourceMappingURL=intent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.d.ts","sourceRoot":"","sources":["../../../src/commands/research/intent.ts"],"names":[],"mappings":"AA+BA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;EA+CxB,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { apiPost } from "../../client.js";
|
|
3
|
+
import { registerSchema } from "../../schemas.js";
|
|
4
|
+
import { handleResearchError, writeResearchJson, writeResearchOutput } from "./output.js";
|
|
5
|
+
registerSchema({
|
|
6
|
+
command: "research.intent",
|
|
7
|
+
description: "Classify Google Search intent for keywords. Determines if someone searching is looking to buy, research, or navigate.",
|
|
8
|
+
args: {
|
|
9
|
+
keywords: {
|
|
10
|
+
type: "string",
|
|
11
|
+
description: "Comma-separated keywords (min 3 chars each, max 1000 keywords)",
|
|
12
|
+
required: true,
|
|
13
|
+
},
|
|
14
|
+
language: { type: "string", description: "Language code or name (default: en)", required: false },
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
const FIELDS = {
|
|
18
|
+
keyword: "The keyword analyzed",
|
|
19
|
+
intent: "Primary Google Search intent: informational, navigational, commercial, transactional",
|
|
20
|
+
probability: "Confidence score 0.0-1.0",
|
|
21
|
+
};
|
|
22
|
+
export const intentCommand = defineCommand({
|
|
23
|
+
meta: {
|
|
24
|
+
name: "intent",
|
|
25
|
+
description: `Classify Google Search intent for keywords. Returns intent type and confidence.
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
baker research intent "buy running shoes,best running shoes 2026,how to tie running shoes"
|
|
29
|
+
baker research intent "crm software" --language spanish`,
|
|
30
|
+
},
|
|
31
|
+
args: {
|
|
32
|
+
keywords: { type: "positional", description: "Comma-separated keywords", required: true },
|
|
33
|
+
language: { type: "string", description: "Language code or name (default: en)", required: false },
|
|
34
|
+
output: { type: "string", description: "Format: json|csv|md|jsonl", required: false, default: "json" },
|
|
35
|
+
},
|
|
36
|
+
run: async ({ args }) => {
|
|
37
|
+
const rawKeywords = args.keywords;
|
|
38
|
+
const keywords = rawKeywords
|
|
39
|
+
.split(",")
|
|
40
|
+
.map((k) => k.trim())
|
|
41
|
+
.filter((k) => k.length >= 3);
|
|
42
|
+
if (keywords.length === 0) {
|
|
43
|
+
writeResearchJson({
|
|
44
|
+
ok: false,
|
|
45
|
+
error: { code: "VALIDATION_ERROR", message: "Provide at least one keyword (min 3 chars each)" },
|
|
46
|
+
});
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const language = args.language || undefined;
|
|
50
|
+
try {
|
|
51
|
+
const data = await apiPost("/api/research/intent", {
|
|
52
|
+
keywords,
|
|
53
|
+
language,
|
|
54
|
+
});
|
|
55
|
+
const format = args.output || "json";
|
|
56
|
+
if (format !== "json") {
|
|
57
|
+
writeResearchOutput(data, format);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
writeResearchJson({ ok: true, data, fields: FIELDS });
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
handleResearchError(err);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../../src/commands/research/intent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE1F,cAAc,CAAC;IACb,OAAO,EAAE,iBAAiB;IAC1B,WAAW,EACT,uHAAuH;IACzH,IAAI,EAAE;QACJ,QAAQ,EAAE;YACR,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,gEAAgE;YAC7E,QAAQ,EAAE,IAAI;SACf;QACD,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qCAAqC,EAAE,QAAQ,EAAE,KAAK,EAAE;KAClG;CACF,CAAC,CAAC;AAQH,MAAM,MAAM,GAA2B;IACrC,OAAO,EAAE,sBAAsB;IAC/B,MAAM,EAAE,sFAAsF;IAC9F,WAAW,EAAE,0BAA0B;CACxC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC;IACzC,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE;;;;0DAIyC;KACvD;IACD,IAAI,EAAE;QACJ,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,0BAA0B,EAAE,QAAQ,EAAE,IAAI,EAAE;QACzF,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,qCAAqC,EAAE,QAAQ,EAAE,KAAK,EAAE;QACjG,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE;KACvG;IACD,GAAG,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAkB,CAAC;QAC5C,MAAM,QAAQ,GAAG,WAAW;aACzB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAEhC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,iBAAiB,CAAC;gBAChB,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,iDAAiD,EAAE;aAChG,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,QAAQ,GAAI,IAAI,CAAC,QAAmB,IAAI,SAAS,CAAC;QAExD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAiB,sBAAsB,EAAE;gBACjE,QAAQ;gBACR,QAAQ;aACT,CAAC,CAAC;YAEH,MAAM,MAAM,GAAI,IAAI,CAAC,MAAiB,IAAI,MAAM,CAAC;YACjD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;gBACtB,mBAAmB,CAAC,IAAiD,EAAE,MAAM,CAAC,CAAC;gBAC/E,OAAO;YACT,CAAC;YACD,iBAAiB,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare const keywordGapCommand: import("citty").CommandDef<{
|
|
2
|
+
readonly competitor: {
|
|
3
|
+
readonly type: "positional";
|
|
4
|
+
readonly description: "Competitor domain";
|
|
5
|
+
readonly required: true;
|
|
6
|
+
};
|
|
7
|
+
readonly ours: {
|
|
8
|
+
readonly type: "positional";
|
|
9
|
+
readonly description: "Your domain";
|
|
10
|
+
readonly required: true;
|
|
11
|
+
};
|
|
12
|
+
readonly location: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly description: "Country code or location code (default: us)";
|
|
15
|
+
readonly required: false;
|
|
16
|
+
};
|
|
17
|
+
readonly language: {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
readonly description: "Language code or name (default: en)";
|
|
20
|
+
readonly required: false;
|
|
21
|
+
};
|
|
22
|
+
readonly type: {
|
|
23
|
+
readonly type: "string";
|
|
24
|
+
readonly description: "Filter: paid, organic, all (default: all)";
|
|
25
|
+
readonly required: false;
|
|
26
|
+
};
|
|
27
|
+
readonly limit: {
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
readonly description: "Max results per page (default: 50, max: 1000)";
|
|
30
|
+
readonly required: false;
|
|
31
|
+
};
|
|
32
|
+
readonly offset: {
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
readonly description: "Pagination offset (default: 0)";
|
|
35
|
+
readonly required: false;
|
|
36
|
+
};
|
|
37
|
+
readonly output: {
|
|
38
|
+
readonly type: "string";
|
|
39
|
+
readonly description: "Format: json|csv|md|jsonl";
|
|
40
|
+
readonly required: false;
|
|
41
|
+
readonly default: "json";
|
|
42
|
+
};
|
|
43
|
+
}>;
|
|
44
|
+
//# sourceMappingURL=keyword-gap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyword-gap.d.ts","sourceRoot":"","sources":["../../../src/commands/research/keyword-gap.ts"],"names":[],"mappings":"AAsCA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiE5B,CAAC"}
|