@canonry/canonry 4.143.0 → 4.145.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/assets/assets/{AuditHistoryPanel--kNrRAQm.js → AuditHistoryPanel-CV9g5mLR.js} +1 -1
- package/assets/assets/{BacklinksPage-CtW1w9lh.js → BacklinksPage-RTcYKA5I.js} +1 -1
- package/assets/assets/{ChartPrimitives-C-nMEqdu.js → ChartPrimitives-BMR0Dqnf.js} +1 -1
- package/assets/assets/{HistoryPage-CAPJDSbc.js → HistoryPage-DAN9QO6x.js} +1 -1
- package/assets/assets/ProjectPage-aFV2nddp.js +9 -0
- package/assets/assets/{RunRow-aDzTzGSK.js → RunRow-WDCIS9MJ.js} +1 -1
- package/assets/assets/{RunsPage-Dy9oWMBK.js → RunsPage-D3Zxd6oc.js} +1 -1
- package/assets/assets/SettingsPage-DcCFVeA7.js +1 -0
- package/assets/assets/{TrafficPage-B4ADqeKG.js → TrafficPage-D0tPBu5O.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-CFcoL_PR.js → TrafficSourceDetailPage-CtyEE9eJ.js} +1 -1
- package/assets/assets/{arrow-left-DV9xcX1v.js → arrow-left-hBxXIGS1.js} +1 -1
- package/assets/assets/{extract-error-message-DXtgw8Q8.js → extract-error-message-DRu89RHb.js} +1 -1
- package/assets/assets/index-ANFzZ3nU.css +1 -0
- package/assets/assets/index-DSOfEiTH.js +213 -0
- package/assets/assets/{trash-2-DMV6uGU1.js → trash-2-DP0ukgbl.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-KUPTGRME.js → chunk-EFBTZ6ZT.js} +4653 -3599
- package/dist/{chunk-VN3CI6K6.js → chunk-GTBCGJNT.js} +7436 -2479
- package/dist/{chunk-3G5B3IMZ.js → chunk-MBLATP5L.js} +1303 -71
- package/dist/{chunk-TJ6SDLXL.js → chunk-XNAJXSZ2.js} +346 -97
- package/dist/cli.js +409 -149
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-V6JYDYGF.js → intelligence-service-DVMEVHAG.js} +2 -2
- package/dist/mcp.js +5 -5
- package/package.json +10 -10
- package/assets/assets/ProjectPage-79R3wJW6.js +0 -9
- package/assets/assets/SettingsPage-DTAs1BrZ.js +0 -1
- package/assets/assets/index-CYA3jd24.css +0 -1
- package/assets/assets/index-H2iFFrr1.js +0 -213
package/dist/cli.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackCliCommandFinished,
|
|
32
32
|
trackEvent
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-XNAJXSZ2.js";
|
|
34
34
|
import {
|
|
35
35
|
CliError,
|
|
36
36
|
EXIT_SYSTEM_ERROR,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
saveConfig,
|
|
48
48
|
saveConfigPatch,
|
|
49
49
|
usageError
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-MBLATP5L.js";
|
|
51
51
|
import {
|
|
52
52
|
apiKeys,
|
|
53
53
|
createClient,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
projects,
|
|
56
56
|
queries,
|
|
57
57
|
renderReportHtml
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-GTBCGJNT.js";
|
|
59
59
|
import {
|
|
60
60
|
AdsDeliverySnapshotStatuses,
|
|
61
61
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -74,6 +74,8 @@ import {
|
|
|
74
74
|
RunStatuses,
|
|
75
75
|
TrafficEventKinds,
|
|
76
76
|
TrafficSeriesGranularities,
|
|
77
|
+
USER_PASSWORD_MIN_LENGTH,
|
|
78
|
+
UserRoles,
|
|
77
79
|
adsActivateTreeRequestSchema,
|
|
78
80
|
adsActivationGrantCreateRequestSchema,
|
|
79
81
|
adsAdCreateRequestSchema,
|
|
@@ -104,7 +106,7 @@ import {
|
|
|
104
106
|
providerQuotaPolicySchema,
|
|
105
107
|
resolveProviderInput,
|
|
106
108
|
winnabilityClassSchema
|
|
107
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-EFBTZ6ZT.js";
|
|
108
110
|
|
|
109
111
|
// src/cli.ts
|
|
110
112
|
import { pathToFileURL } from "url";
|
|
@@ -7549,13 +7551,224 @@ var KEYS_CLI_COMMANDS = [
|
|
|
7549
7551
|
}
|
|
7550
7552
|
];
|
|
7551
7553
|
|
|
7554
|
+
// src/cli-prompt.ts
|
|
7555
|
+
import readline from "readline";
|
|
7556
|
+
async function promptHiddenInput(question) {
|
|
7557
|
+
const input = process.stdin;
|
|
7558
|
+
const output = process.stdout;
|
|
7559
|
+
if (!input.isTTY) {
|
|
7560
|
+
const rl2 = readline.createInterface({ input, output });
|
|
7561
|
+
try {
|
|
7562
|
+
return await new Promise((resolve) => {
|
|
7563
|
+
rl2.question(question, resolve);
|
|
7564
|
+
});
|
|
7565
|
+
} finally {
|
|
7566
|
+
rl2.close();
|
|
7567
|
+
}
|
|
7568
|
+
}
|
|
7569
|
+
const rl = readline.createInterface({ input, output, terminal: true });
|
|
7570
|
+
const mutable = rl;
|
|
7571
|
+
const originalWrite = mutable._writeToOutput?.bind(rl);
|
|
7572
|
+
let muted = false;
|
|
7573
|
+
mutable._writeToOutput = (chunk) => {
|
|
7574
|
+
if (muted) {
|
|
7575
|
+
output.write("");
|
|
7576
|
+
return;
|
|
7577
|
+
}
|
|
7578
|
+
originalWrite?.(chunk);
|
|
7579
|
+
};
|
|
7580
|
+
try {
|
|
7581
|
+
return await new Promise((resolve) => {
|
|
7582
|
+
rl.question(question, (answer) => {
|
|
7583
|
+
output.write("\n");
|
|
7584
|
+
resolve(answer);
|
|
7585
|
+
});
|
|
7586
|
+
muted = true;
|
|
7587
|
+
});
|
|
7588
|
+
} finally {
|
|
7589
|
+
muted = false;
|
|
7590
|
+
if (originalWrite) mutable._writeToOutput = originalWrite;
|
|
7591
|
+
rl.close();
|
|
7592
|
+
}
|
|
7593
|
+
}
|
|
7594
|
+
async function readAllStdin() {
|
|
7595
|
+
const chunks = [];
|
|
7596
|
+
for await (const chunk of process.stdin) {
|
|
7597
|
+
chunks.push(Buffer.from(chunk));
|
|
7598
|
+
}
|
|
7599
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
7600
|
+
}
|
|
7601
|
+
|
|
7602
|
+
// src/commands/users.ts
|
|
7603
|
+
function getClient13() {
|
|
7604
|
+
return createApiClient();
|
|
7605
|
+
}
|
|
7606
|
+
var ROLE_NAMES = Object.values(UserRoles);
|
|
7607
|
+
function parseRole(role) {
|
|
7608
|
+
const normalized = role.trim().toLowerCase();
|
|
7609
|
+
if (ROLE_NAMES.includes(normalized)) return normalized;
|
|
7610
|
+
throw new CliError({
|
|
7611
|
+
code: "CLI_USAGE_ERROR",
|
|
7612
|
+
message: `Unknown role "${role}" \u2014 choose ${ROLE_NAMES.join(" or ")}`,
|
|
7613
|
+
displayMessage: `Error: unknown role "${role}". Choose ${ROLE_NAMES.join(" or ")}.`
|
|
7614
|
+
});
|
|
7615
|
+
}
|
|
7616
|
+
async function listUsers(format) {
|
|
7617
|
+
const client = getClient13();
|
|
7618
|
+
const { users } = await client.listUsers();
|
|
7619
|
+
if (format === "json") {
|
|
7620
|
+
console.log(JSON.stringify({ users }, null, 2));
|
|
7621
|
+
return;
|
|
7622
|
+
} else if (format === "jsonl") {
|
|
7623
|
+
emitJsonl(users);
|
|
7624
|
+
return;
|
|
7625
|
+
}
|
|
7626
|
+
if (users.length === 0) {
|
|
7627
|
+
console.log("No accounts yet \u2014 the dashboard opens without a sign-in.");
|
|
7628
|
+
console.log("Create the first one with: canonry user create --name <name> --role admin");
|
|
7629
|
+
return;
|
|
7630
|
+
}
|
|
7631
|
+
console.log(`${"NAME".padEnd(24)} ${"ROLE".padEnd(8)} ${"CREATED".padEnd(12)} LAST SIGN-IN`);
|
|
7632
|
+
for (const user of users) {
|
|
7633
|
+
const lastLogin = user.lastLoginAt ? formatIsoDate(user.lastLoginAt) : "never";
|
|
7634
|
+
console.log(
|
|
7635
|
+
`${user.name.padEnd(24)} ${user.role.padEnd(8)} ${formatIsoDate(user.createdAt).padEnd(12)} ${lastLogin}`
|
|
7636
|
+
);
|
|
7637
|
+
}
|
|
7638
|
+
}
|
|
7639
|
+
async function createUser(opts) {
|
|
7640
|
+
const role = parseRole(opts.role);
|
|
7641
|
+
const password = opts.passwordStdin ? (await (opts.readStdin ?? readAllStdin)()).replace(/\r?\n$/, "") : await askForPassword();
|
|
7642
|
+
if (password.length < USER_PASSWORD_MIN_LENGTH) {
|
|
7643
|
+
throw new CliError({
|
|
7644
|
+
code: "CLI_USAGE_ERROR",
|
|
7645
|
+
message: "Password too short",
|
|
7646
|
+
displayMessage: `Error: the password must be at least ${USER_PASSWORD_MIN_LENGTH} characters.`
|
|
7647
|
+
});
|
|
7648
|
+
}
|
|
7649
|
+
const client = getClient13();
|
|
7650
|
+
const wasFirst = await isFirstAccount(client);
|
|
7651
|
+
const created = await client.createUser({ name: opts.name, role, password });
|
|
7652
|
+
if (isMachineFormat(opts.format)) {
|
|
7653
|
+
console.log(JSON.stringify(created, null, 2));
|
|
7654
|
+
return;
|
|
7655
|
+
}
|
|
7656
|
+
printCreated(created, wasFirst);
|
|
7657
|
+
}
|
|
7658
|
+
async function askForPassword() {
|
|
7659
|
+
const first = await promptHiddenInput("Password: ");
|
|
7660
|
+
const second = await promptHiddenInput("Confirm password: ");
|
|
7661
|
+
if (first !== second) {
|
|
7662
|
+
throw new CliError({
|
|
7663
|
+
code: "CLI_USAGE_ERROR",
|
|
7664
|
+
message: "Passwords do not match",
|
|
7665
|
+
displayMessage: "Error: the two passwords do not match. Nothing was created."
|
|
7666
|
+
});
|
|
7667
|
+
}
|
|
7668
|
+
return first;
|
|
7669
|
+
}
|
|
7670
|
+
async function isFirstAccount(client) {
|
|
7671
|
+
try {
|
|
7672
|
+
const { users } = await client.listUsers();
|
|
7673
|
+
return users.length === 0;
|
|
7674
|
+
} catch {
|
|
7675
|
+
return false;
|
|
7676
|
+
}
|
|
7677
|
+
}
|
|
7678
|
+
function printCreated(created, wasFirst) {
|
|
7679
|
+
console.log(`Account "${created.name}" created with ${created.role} access.
|
|
7680
|
+
`);
|
|
7681
|
+
if (wasFirst) {
|
|
7682
|
+
console.log("This is the first account on this install, so the dashboard now asks");
|
|
7683
|
+
console.log("everyone to sign in. API keys are unaffected and keep working as before.\n");
|
|
7684
|
+
}
|
|
7685
|
+
if (created.role === UserRoles.viewer) {
|
|
7686
|
+
console.log("A viewer can read everything and change nothing.");
|
|
7687
|
+
} else {
|
|
7688
|
+
console.log("An administrator can do everything the install could already do.");
|
|
7689
|
+
}
|
|
7690
|
+
}
|
|
7691
|
+
async function deleteUser(name, format) {
|
|
7692
|
+
const client = getClient13();
|
|
7693
|
+
const result = await client.deleteUser(name);
|
|
7694
|
+
if (isMachineFormat(format)) {
|
|
7695
|
+
console.log(JSON.stringify(result, null, 2));
|
|
7696
|
+
return;
|
|
7697
|
+
}
|
|
7698
|
+
console.log(`Account "${result.name}" deleted. Any browser signed in as them is signed out now.`);
|
|
7699
|
+
}
|
|
7700
|
+
|
|
7701
|
+
// src/cli-commands/users.ts
|
|
7702
|
+
var CREATE_USAGE = "canonry user create --name <name> --role <admin|viewer> [--password-stdin] [--format json]";
|
|
7703
|
+
var USERS_CLI_COMMANDS = [
|
|
7704
|
+
{
|
|
7705
|
+
path: ["user", "list"],
|
|
7706
|
+
usage: "canonry user list [--format json|jsonl]",
|
|
7707
|
+
run: async (input) => {
|
|
7708
|
+
await listUsers(input.format);
|
|
7709
|
+
}
|
|
7710
|
+
},
|
|
7711
|
+
{
|
|
7712
|
+
path: ["user", "create"],
|
|
7713
|
+
usage: CREATE_USAGE,
|
|
7714
|
+
options: {
|
|
7715
|
+
name: stringOption(),
|
|
7716
|
+
role: stringOption(),
|
|
7717
|
+
// There is deliberately no `--password` flag: a password given on the
|
|
7718
|
+
// command line lands in the shell history and the process list.
|
|
7719
|
+
"password-stdin": { type: "boolean" }
|
|
7720
|
+
},
|
|
7721
|
+
run: async (input) => {
|
|
7722
|
+
const name = requireStringOption(input, "name", {
|
|
7723
|
+
command: "user.create",
|
|
7724
|
+
usage: CREATE_USAGE,
|
|
7725
|
+
message: "--name is required"
|
|
7726
|
+
});
|
|
7727
|
+
const role = requireStringOption(input, "role", {
|
|
7728
|
+
command: "user.create",
|
|
7729
|
+
usage: CREATE_USAGE,
|
|
7730
|
+
message: "--role is required (admin or viewer)"
|
|
7731
|
+
});
|
|
7732
|
+
await createUser({
|
|
7733
|
+
name,
|
|
7734
|
+
role,
|
|
7735
|
+
passwordStdin: getBoolean(input.values, "password-stdin"),
|
|
7736
|
+
format: input.format
|
|
7737
|
+
});
|
|
7738
|
+
}
|
|
7739
|
+
},
|
|
7740
|
+
{
|
|
7741
|
+
path: ["user", "delete"],
|
|
7742
|
+
usage: "canonry user delete <name> [--format json]",
|
|
7743
|
+
run: async (input) => {
|
|
7744
|
+
const name = requirePositional(input, 0, {
|
|
7745
|
+
command: "user.delete",
|
|
7746
|
+
usage: "canonry user delete <name> [--format json]",
|
|
7747
|
+
message: "Account name is required"
|
|
7748
|
+
});
|
|
7749
|
+
await deleteUser(name, input.format);
|
|
7750
|
+
}
|
|
7751
|
+
},
|
|
7752
|
+
{
|
|
7753
|
+
path: ["user"],
|
|
7754
|
+
usage: "canonry user <list|create|delete>",
|
|
7755
|
+
run: async (input) => {
|
|
7756
|
+
unknownSubcommand(input.positionals[0], {
|
|
7757
|
+
command: "user",
|
|
7758
|
+
usage: "canonry user <list|create|delete>",
|
|
7759
|
+
available: ["list", "create", "delete"]
|
|
7760
|
+
});
|
|
7761
|
+
}
|
|
7762
|
+
}
|
|
7763
|
+
];
|
|
7764
|
+
|
|
7552
7765
|
// src/commands/keyword.ts
|
|
7553
7766
|
import fs4 from "fs";
|
|
7554
|
-
function
|
|
7767
|
+
function getClient14() {
|
|
7555
7768
|
return createApiClient();
|
|
7556
7769
|
}
|
|
7557
7770
|
async function addKeywords(project, keywords, format) {
|
|
7558
|
-
const client =
|
|
7771
|
+
const client = getClient14();
|
|
7559
7772
|
await client.appendKeywords(project, keywords);
|
|
7560
7773
|
if (isMachineFormat(format)) {
|
|
7561
7774
|
console.log(JSON.stringify({
|
|
@@ -7568,7 +7781,7 @@ async function addKeywords(project, keywords, format) {
|
|
|
7568
7781
|
console.log(`Added ${keywords.length} key phrase(s) to "${project}".`);
|
|
7569
7782
|
}
|
|
7570
7783
|
async function replaceKeywords(project, keywords, format) {
|
|
7571
|
-
const client =
|
|
7784
|
+
const client = getClient14();
|
|
7572
7785
|
await client.putKeywords(project, keywords);
|
|
7573
7786
|
if (isMachineFormat(format)) {
|
|
7574
7787
|
console.log(JSON.stringify({
|
|
@@ -7581,7 +7794,7 @@ async function replaceKeywords(project, keywords, format) {
|
|
|
7581
7794
|
console.log(`Set ${keywords.length} key phrase(s) for "${project}".`);
|
|
7582
7795
|
}
|
|
7583
7796
|
async function removeKeywords(project, keywords, format) {
|
|
7584
|
-
const client =
|
|
7797
|
+
const client = getClient14();
|
|
7585
7798
|
const existing = await client.listKeywords(project);
|
|
7586
7799
|
const existingSet = new Set(existing.map((k) => k.keyword));
|
|
7587
7800
|
const removedKeywords = keywords.filter((k) => existingSet.has(k));
|
|
@@ -7598,7 +7811,7 @@ async function removeKeywords(project, keywords, format) {
|
|
|
7598
7811
|
console.log(`Removed ${removedKeywords.length} key phrase(s) from "${project}".`);
|
|
7599
7812
|
}
|
|
7600
7813
|
async function listKeywords(project, format) {
|
|
7601
|
-
const client =
|
|
7814
|
+
const client = getClient14();
|
|
7602
7815
|
const kws = await client.listKeywords(project);
|
|
7603
7816
|
if (format === "json") {
|
|
7604
7817
|
console.log(JSON.stringify(kws, null, 2));
|
|
@@ -7644,7 +7857,7 @@ async function importKeywords(project, filePath, format) {
|
|
|
7644
7857
|
console.log("No key phrases found in file.");
|
|
7645
7858
|
return;
|
|
7646
7859
|
}
|
|
7647
|
-
const client =
|
|
7860
|
+
const client = getClient14();
|
|
7648
7861
|
await client.appendKeywords(project, keywords);
|
|
7649
7862
|
if (isMachineFormat(format)) {
|
|
7650
7863
|
console.log(JSON.stringify({
|
|
@@ -7658,7 +7871,7 @@ async function importKeywords(project, filePath, format) {
|
|
|
7658
7871
|
console.log(`Imported ${keywords.length} key phrase(s) to "${project}".`);
|
|
7659
7872
|
}
|
|
7660
7873
|
async function generateKeywords(project, provider, opts) {
|
|
7661
|
-
const client =
|
|
7874
|
+
const client = getClient14();
|
|
7662
7875
|
const result = await client.generateKeywords(project, provider, opts.count);
|
|
7663
7876
|
const saved = Boolean(opts.save && result.keywords.length > 0);
|
|
7664
7877
|
if (!isMachineFormat(opts.format)) {
|
|
@@ -7831,11 +8044,11 @@ var KEYWORD_CLI_COMMANDS = [
|
|
|
7831
8044
|
|
|
7832
8045
|
// src/commands/query.ts
|
|
7833
8046
|
import fs5 from "fs";
|
|
7834
|
-
function
|
|
8047
|
+
function getClient15() {
|
|
7835
8048
|
return createApiClient();
|
|
7836
8049
|
}
|
|
7837
8050
|
async function addQueries(project, queries2, format) {
|
|
7838
|
-
const client =
|
|
8051
|
+
const client = getClient15();
|
|
7839
8052
|
await client.appendQueries(project, queries2);
|
|
7840
8053
|
if (isMachineFormat(format)) {
|
|
7841
8054
|
console.log(JSON.stringify({
|
|
@@ -7848,7 +8061,7 @@ async function addQueries(project, queries2, format) {
|
|
|
7848
8061
|
console.log(`Added ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} to "${project}".`);
|
|
7849
8062
|
}
|
|
7850
8063
|
async function replaceQueries(project, queries2, opts) {
|
|
7851
|
-
const client =
|
|
8064
|
+
const client = getClient15();
|
|
7852
8065
|
const isJson = isMachineFormat(opts?.format);
|
|
7853
8066
|
if (opts?.dryRun) {
|
|
7854
8067
|
const preview = await client.previewReplaceQueries(project, queries2);
|
|
@@ -7884,7 +8097,7 @@ async function replaceQueries(project, queries2, opts) {
|
|
|
7884
8097
|
console.log(`Set ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} for "${project}".`);
|
|
7885
8098
|
}
|
|
7886
8099
|
async function removeQueries(project, queries2, format) {
|
|
7887
|
-
const client =
|
|
8100
|
+
const client = getClient15();
|
|
7888
8101
|
const existing = await client.listQueries(project);
|
|
7889
8102
|
const existingSet = new Set(existing.map((q) => q.query));
|
|
7890
8103
|
const removedQueries = queries2.filter((q) => existingSet.has(q));
|
|
@@ -7901,7 +8114,7 @@ async function removeQueries(project, queries2, format) {
|
|
|
7901
8114
|
console.log(`Removed ${removedQueries.length} ${removedQueries.length === 1 ? "query" : "queries"} from "${project}".`);
|
|
7902
8115
|
}
|
|
7903
8116
|
async function listQueries(project, format) {
|
|
7904
|
-
const client =
|
|
8117
|
+
const client = getClient15();
|
|
7905
8118
|
const qs = await client.listQueries(project);
|
|
7906
8119
|
if (format === "json") {
|
|
7907
8120
|
console.log(JSON.stringify(qs, null, 2));
|
|
@@ -7947,7 +8160,7 @@ async function importQueries(project, filePath, format) {
|
|
|
7947
8160
|
console.log("No queries found in file.");
|
|
7948
8161
|
return;
|
|
7949
8162
|
}
|
|
7950
|
-
const client =
|
|
8163
|
+
const client = getClient15();
|
|
7951
8164
|
await client.appendQueries(project, queries2);
|
|
7952
8165
|
if (isMachineFormat(format)) {
|
|
7953
8166
|
console.log(JSON.stringify({
|
|
@@ -7961,7 +8174,7 @@ async function importQueries(project, filePath, format) {
|
|
|
7961
8174
|
console.log(`Imported ${queries2.length} ${queries2.length === 1 ? "query" : "queries"} to "${project}".`);
|
|
7962
8175
|
}
|
|
7963
8176
|
async function generateQueries(project, provider, opts) {
|
|
7964
|
-
const client =
|
|
8177
|
+
const client = getClient15();
|
|
7965
8178
|
const result = await client.generateQueries(project, provider, opts.count);
|
|
7966
8179
|
const saved = Boolean(opts.save && result.queries.length > 0);
|
|
7967
8180
|
if (!isMachineFormat(opts.format)) {
|
|
@@ -8456,11 +8669,11 @@ var MCP_CLI_COMMANDS = [
|
|
|
8456
8669
|
];
|
|
8457
8670
|
|
|
8458
8671
|
// src/commands/notify.ts
|
|
8459
|
-
function
|
|
8672
|
+
function getClient16() {
|
|
8460
8673
|
return createApiClient();
|
|
8461
8674
|
}
|
|
8462
8675
|
async function addNotification(project, opts) {
|
|
8463
|
-
const client =
|
|
8676
|
+
const client = getClient16();
|
|
8464
8677
|
const result = await client.createNotification(project, {
|
|
8465
8678
|
channel: "webhook",
|
|
8466
8679
|
url: opts.webhook,
|
|
@@ -8474,7 +8687,7 @@ async function addNotification(project, opts) {
|
|
|
8474
8687
|
printNotification(result);
|
|
8475
8688
|
}
|
|
8476
8689
|
async function listNotifications(project, format) {
|
|
8477
|
-
const client =
|
|
8690
|
+
const client = getClient16();
|
|
8478
8691
|
const results = await client.listNotifications(project);
|
|
8479
8692
|
if (format === "json") {
|
|
8480
8693
|
console.log(JSON.stringify(results, null, 2));
|
|
@@ -8495,7 +8708,7 @@ async function listNotifications(project, format) {
|
|
|
8495
8708
|
}
|
|
8496
8709
|
}
|
|
8497
8710
|
async function removeNotification(project, id, format) {
|
|
8498
|
-
const client =
|
|
8711
|
+
const client = getClient16();
|
|
8499
8712
|
await client.deleteNotification(project, id);
|
|
8500
8713
|
if (isMachineFormat(format)) {
|
|
8501
8714
|
console.log(JSON.stringify({ project, id, removed: true }, null, 2));
|
|
@@ -8504,7 +8717,7 @@ async function removeNotification(project, id, format) {
|
|
|
8504
8717
|
console.log(`Notification ${id} removed from "${project}"`);
|
|
8505
8718
|
}
|
|
8506
8719
|
async function testNotification(project, id, format) {
|
|
8507
|
-
const client =
|
|
8720
|
+
const client = getClient16();
|
|
8508
8721
|
const result = await client.testNotification(project, id);
|
|
8509
8722
|
if (isMachineFormat(format)) {
|
|
8510
8723
|
console.log(JSON.stringify({ project, id, ...result }, null, 2));
|
|
@@ -8701,11 +8914,11 @@ async function applyConfigs(filePaths, format) {
|
|
|
8701
8914
|
}
|
|
8702
8915
|
|
|
8703
8916
|
// src/commands/analytics.ts
|
|
8704
|
-
function
|
|
8917
|
+
function getClient17() {
|
|
8705
8918
|
return createApiClient();
|
|
8706
8919
|
}
|
|
8707
8920
|
async function showAnalytics(project, options) {
|
|
8708
|
-
const client =
|
|
8921
|
+
const client = getClient17();
|
|
8709
8922
|
const features = options.feature ? [options.feature] : ["metrics", "gaps", "sources"];
|
|
8710
8923
|
const results = {};
|
|
8711
8924
|
for (const feature of features) {
|
|
@@ -8908,7 +9121,7 @@ Source Origin Breakdown`);
|
|
|
8908
9121
|
}
|
|
8909
9122
|
|
|
8910
9123
|
// src/commands/sources.ts
|
|
8911
|
-
function
|
|
9124
|
+
function getClient18() {
|
|
8912
9125
|
return createApiClient();
|
|
8913
9126
|
}
|
|
8914
9127
|
var pct = (n) => `${(n * 100).toFixed(1)}%`;
|
|
@@ -8919,7 +9132,7 @@ async function showSources(project, options) {
|
|
|
8919
9132
|
details: { command: "sources", option: "limit", value: options.limit }
|
|
8920
9133
|
});
|
|
8921
9134
|
}
|
|
8922
|
-
const client =
|
|
9135
|
+
const client = getClient18();
|
|
8923
9136
|
const data = await client.getAnalyticsSources(project, { window: options.window, limit: options.limit });
|
|
8924
9137
|
if (options.format === "jsonl") {
|
|
8925
9138
|
emitJsonl(data.ranked.entries.map((e) => ({ project, ...e })));
|
|
@@ -8970,11 +9183,11 @@ function printRankedEntries(list, indent = "") {
|
|
|
8970
9183
|
}
|
|
8971
9184
|
|
|
8972
9185
|
// src/commands/evidence.ts
|
|
8973
|
-
function
|
|
9186
|
+
function getClient19() {
|
|
8974
9187
|
return createApiClient();
|
|
8975
9188
|
}
|
|
8976
9189
|
async function showEvidence(project, format) {
|
|
8977
|
-
const client =
|
|
9190
|
+
const client = getClient19();
|
|
8978
9191
|
const timeline = await client.getTimeline(project);
|
|
8979
9192
|
if (format === "json") {
|
|
8980
9193
|
const enriched = timeline.map((entry) => ({
|
|
@@ -9057,7 +9270,7 @@ async function exportResults(project, opts) {
|
|
|
9057
9270
|
}
|
|
9058
9271
|
|
|
9059
9272
|
// src/commands/history.ts
|
|
9060
|
-
function
|
|
9273
|
+
function getClient20() {
|
|
9061
9274
|
return createApiClient();
|
|
9062
9275
|
}
|
|
9063
9276
|
function originLabel(entry) {
|
|
@@ -9068,7 +9281,7 @@ function originLabel(entry) {
|
|
|
9068
9281
|
return entry.actor;
|
|
9069
9282
|
}
|
|
9070
9283
|
async function showHistory(project, format, opts = {}) {
|
|
9071
|
-
const client =
|
|
9284
|
+
const client = getClient20();
|
|
9072
9285
|
try {
|
|
9073
9286
|
const entries = project ? await client.getHistory(project, opts) : await client.getGlobalHistory(opts);
|
|
9074
9287
|
if (format === "json") {
|
|
@@ -9109,11 +9322,11 @@ async function showHistory(project, format, opts = {}) {
|
|
|
9109
9322
|
}
|
|
9110
9323
|
|
|
9111
9324
|
// src/commands/status.ts
|
|
9112
|
-
function
|
|
9325
|
+
function getClient21() {
|
|
9113
9326
|
return createApiClient();
|
|
9114
9327
|
}
|
|
9115
9328
|
async function showStatus(project, format) {
|
|
9116
|
-
const client =
|
|
9329
|
+
const client = getClient21();
|
|
9117
9330
|
const projectData = await client.getProject(project);
|
|
9118
9331
|
const latest = await getLatestRunSummary(client, project);
|
|
9119
9332
|
if (isMachineFormat(format)) {
|
|
@@ -9312,11 +9525,11 @@ var OPERATOR_CLI_COMMANDS = [
|
|
|
9312
9525
|
];
|
|
9313
9526
|
|
|
9314
9527
|
// src/commands/project.ts
|
|
9315
|
-
function
|
|
9528
|
+
function getClient22() {
|
|
9316
9529
|
return createApiClient();
|
|
9317
9530
|
}
|
|
9318
9531
|
async function createProject(name, opts) {
|
|
9319
|
-
const client =
|
|
9532
|
+
const client = getClient22();
|
|
9320
9533
|
const result = await client.putProject(name, {
|
|
9321
9534
|
displayName: opts.displayName,
|
|
9322
9535
|
canonicalDomain: opts.domain,
|
|
@@ -9334,7 +9547,7 @@ async function createProject(name, opts) {
|
|
|
9334
9547
|
console.log(`Project created: ${result.name} (${result.id})`);
|
|
9335
9548
|
}
|
|
9336
9549
|
async function listProjects(format) {
|
|
9337
|
-
const client =
|
|
9550
|
+
const client = getClient22();
|
|
9338
9551
|
const projects2 = await client.listProjects();
|
|
9339
9552
|
if (format === "json") {
|
|
9340
9553
|
console.log(JSON.stringify(projects2, null, 2));
|
|
@@ -9366,7 +9579,7 @@ async function listProjects(format) {
|
|
|
9366
9579
|
}
|
|
9367
9580
|
}
|
|
9368
9581
|
async function showProject(name, format) {
|
|
9369
|
-
const client =
|
|
9582
|
+
const client = getClient22();
|
|
9370
9583
|
const project = await client.getProject(name);
|
|
9371
9584
|
if (isMachineFormat(format)) {
|
|
9372
9585
|
console.log(JSON.stringify(project, null, 2));
|
|
@@ -9398,7 +9611,7 @@ async function showProject(name, format) {
|
|
|
9398
9611
|
if (project.updatedAt) console.log(` Updated: ${project.updatedAt}`);
|
|
9399
9612
|
}
|
|
9400
9613
|
async function updateProjectSettings(name, opts) {
|
|
9401
|
-
const client =
|
|
9614
|
+
const client = getClient22();
|
|
9402
9615
|
const project = await client.getProject(name);
|
|
9403
9616
|
let ownedDomains = opts.ownedDomains ?? project.ownedDomains ?? [];
|
|
9404
9617
|
if (opts.addOwnedDomain) {
|
|
@@ -9461,7 +9674,7 @@ async function updateProjectSettings(name, opts) {
|
|
|
9461
9674
|
}
|
|
9462
9675
|
}
|
|
9463
9676
|
async function deleteProject(name, opts) {
|
|
9464
|
-
const client =
|
|
9677
|
+
const client = getClient22();
|
|
9465
9678
|
const isJson = isMachineFormat(opts?.format);
|
|
9466
9679
|
if (opts?.dryRun) {
|
|
9467
9680
|
const preview = await client.previewProjectDelete(name);
|
|
@@ -9491,7 +9704,7 @@ async function deleteProject(name, opts) {
|
|
|
9491
9704
|
console.log(`Project deleted: ${name}`);
|
|
9492
9705
|
}
|
|
9493
9706
|
async function addLocation(project, opts) {
|
|
9494
|
-
const client =
|
|
9707
|
+
const client = getClient22();
|
|
9495
9708
|
const location = await client.addLocation(project, {
|
|
9496
9709
|
label: opts.label,
|
|
9497
9710
|
city: opts.city,
|
|
@@ -9506,7 +9719,7 @@ async function addLocation(project, opts) {
|
|
|
9506
9719
|
console.log(`Location added: ${opts.label} (${opts.city}, ${opts.region}, ${opts.country})`);
|
|
9507
9720
|
}
|
|
9508
9721
|
async function listLocations(project, format) {
|
|
9509
|
-
const client =
|
|
9722
|
+
const client = getClient22();
|
|
9510
9723
|
const result = await client.listLocations(project);
|
|
9511
9724
|
if (format === "json") {
|
|
9512
9725
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -9540,7 +9753,7 @@ async function listLocations(project, format) {
|
|
|
9540
9753
|
}
|
|
9541
9754
|
}
|
|
9542
9755
|
async function removeLocation(project, label, format) {
|
|
9543
|
-
const client =
|
|
9756
|
+
const client = getClient22();
|
|
9544
9757
|
await client.removeLocation(project, label);
|
|
9545
9758
|
if (isMachineFormat(format)) {
|
|
9546
9759
|
console.log(JSON.stringify({ project, label, removed: true }, null, 2));
|
|
@@ -9549,7 +9762,7 @@ async function removeLocation(project, label, format) {
|
|
|
9549
9762
|
console.log(`Location removed: ${label}`);
|
|
9550
9763
|
}
|
|
9551
9764
|
async function setDefaultLocation(project, label, format) {
|
|
9552
|
-
const client =
|
|
9765
|
+
const client = getClient22();
|
|
9553
9766
|
const result = await client.setDefaultLocation(project, label);
|
|
9554
9767
|
if (isMachineFormat(format)) {
|
|
9555
9768
|
console.log(JSON.stringify({ project, ...result }, null, 2));
|
|
@@ -9897,12 +10110,12 @@ var ORGANIC_EVIDENCE_CLI_COMMANDS = [
|
|
|
9897
10110
|
];
|
|
9898
10111
|
|
|
9899
10112
|
// src/commands/run.ts
|
|
9900
|
-
function
|
|
10113
|
+
function getClient23() {
|
|
9901
10114
|
return createApiClient();
|
|
9902
10115
|
}
|
|
9903
10116
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "partial", "failed", "cancelled"]);
|
|
9904
10117
|
async function triggerRun(project, opts) {
|
|
9905
|
-
const client =
|
|
10118
|
+
const client = getClient23();
|
|
9906
10119
|
const body = {};
|
|
9907
10120
|
if (opts?.provider) {
|
|
9908
10121
|
const providerInputs = opts.provider.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -9912,6 +10125,12 @@ async function triggerRun(project, opts) {
|
|
|
9912
10125
|
if (opts?.queries?.length) {
|
|
9913
10126
|
body.queries = opts.queries;
|
|
9914
10127
|
}
|
|
10128
|
+
if (opts?.groups?.length || opts?.targets?.length) {
|
|
10129
|
+
body.measurementScope = {
|
|
10130
|
+
...opts.groups?.length ? { groups: opts.groups } : {},
|
|
10131
|
+
...opts.targets?.length ? { targets: opts.targets } : {}
|
|
10132
|
+
};
|
|
10133
|
+
}
|
|
9915
10134
|
if (opts?.location) {
|
|
9916
10135
|
body.location = opts.location;
|
|
9917
10136
|
}
|
|
@@ -10004,7 +10223,7 @@ async function triggerRun(project, opts) {
|
|
|
10004
10223
|
}
|
|
10005
10224
|
}
|
|
10006
10225
|
async function triggerRunAll(opts) {
|
|
10007
|
-
const client =
|
|
10226
|
+
const client = getClient23();
|
|
10008
10227
|
const projects2 = await client.listProjects();
|
|
10009
10228
|
if (projects2.length === 0) {
|
|
10010
10229
|
if (isMachineFormat(opts?.format)) {
|
|
@@ -10087,7 +10306,7 @@ async function triggerRunAll(opts) {
|
|
|
10087
10306
|
}
|
|
10088
10307
|
}
|
|
10089
10308
|
async function cancelRun(project, runId, format) {
|
|
10090
|
-
const client =
|
|
10309
|
+
const client = getClient23();
|
|
10091
10310
|
let targetId = runId;
|
|
10092
10311
|
if (!targetId) {
|
|
10093
10312
|
const runs = await client.listRuns(project);
|
|
@@ -10119,7 +10338,7 @@ To cancel by ID : canonry run cancel ${project} <run-id>`,
|
|
|
10119
10338
|
console.log(`Run ${result.id} cancelled.`);
|
|
10120
10339
|
}
|
|
10121
10340
|
async function showRun(id, format) {
|
|
10122
|
-
const client =
|
|
10341
|
+
const client = getClient23();
|
|
10123
10342
|
const run = await client.getRun(id);
|
|
10124
10343
|
if (isMachineFormat(format)) {
|
|
10125
10344
|
console.log(JSON.stringify(run, null, 2));
|
|
@@ -10128,7 +10347,7 @@ async function showRun(id, format) {
|
|
|
10128
10347
|
printRunDetail(run);
|
|
10129
10348
|
}
|
|
10130
10349
|
async function listRuns(project, opts) {
|
|
10131
|
-
const client =
|
|
10350
|
+
const client = getClient23();
|
|
10132
10351
|
const runs = await client.listRuns(project, opts?.limit, opts?.kind);
|
|
10133
10352
|
if (opts?.format === "json") {
|
|
10134
10353
|
console.log(JSON.stringify(runs, null, 2));
|
|
@@ -10195,6 +10414,90 @@ function printRunDetail(run) {
|
|
|
10195
10414
|
}
|
|
10196
10415
|
|
|
10197
10416
|
// src/cli-commands/run.ts
|
|
10417
|
+
var RUN_TRIGGER_USAGE = "canonry run trigger <project> [--group <key>]... [--target <key>]... [--provider <name>] [--query <q>...] [--location <label>] [--all-locations] [--no-location] [--probe] [--wait] [--format json]";
|
|
10418
|
+
var RUN_USAGE2 = "canonry run <project|--all> [--group <key>]... [--target <key>]... [--provider <name>] [--query <q>...] [--location <label>] [--all-locations] [--no-location] [--probe] [--wait] [--format json]";
|
|
10419
|
+
var RUN_TRIGGER_OPTIONS = {
|
|
10420
|
+
provider: stringOption(),
|
|
10421
|
+
query: multiStringOption(),
|
|
10422
|
+
// Measure one slice of the project's published measurement plan. A group
|
|
10423
|
+
// stands for its member targets; repeat either flag to widen the slice.
|
|
10424
|
+
group: multiStringOption(),
|
|
10425
|
+
target: multiStringOption(),
|
|
10426
|
+
wait: { type: "boolean", default: false },
|
|
10427
|
+
all: { type: "boolean", default: false },
|
|
10428
|
+
location: stringOption(),
|
|
10429
|
+
"all-locations": { type: "boolean", default: false },
|
|
10430
|
+
"no-location": { type: "boolean", default: false },
|
|
10431
|
+
// Probe runs are operator/agent test runs — they write a snapshot
|
|
10432
|
+
// for inspection but are excluded from dashboard / analytics /
|
|
10433
|
+
// intelligence / notifications. Use when you want to verify a
|
|
10434
|
+
// provider works without polluting the project's metrics.
|
|
10435
|
+
probe: { type: "boolean", default: false }
|
|
10436
|
+
};
|
|
10437
|
+
async function triggerRunCommand(input, command) {
|
|
10438
|
+
const groups = getStringArray(input.values, "group") ?? [];
|
|
10439
|
+
const targets = getStringArray(input.values, "target") ?? [];
|
|
10440
|
+
const queries2 = getStringArray(input.values, "query") ?? [];
|
|
10441
|
+
const usage = command === "run" ? RUN_USAGE2 : RUN_TRIGGER_USAGE;
|
|
10442
|
+
if (getBoolean(input.values, "all")) {
|
|
10443
|
+
if (input.positionals.length > 0) {
|
|
10444
|
+
throw usageError("Error: --all cannot be combined with a project name", {
|
|
10445
|
+
message: "--all cannot be combined with a project name",
|
|
10446
|
+
details: {
|
|
10447
|
+
command,
|
|
10448
|
+
usage: "canonry run --all [--provider <name>] [--wait] [--format json]"
|
|
10449
|
+
}
|
|
10450
|
+
});
|
|
10451
|
+
}
|
|
10452
|
+
if (queries2.length) {
|
|
10453
|
+
throw usageError("Error: --query cannot be combined with --all (query scope is project-specific)", {
|
|
10454
|
+
message: "--query cannot be combined with --all (query scope is project-specific)",
|
|
10455
|
+
details: {
|
|
10456
|
+
command,
|
|
10457
|
+
usage: "canonry run <project> --query <q>... [--provider <name>] [--wait] [--format json]"
|
|
10458
|
+
}
|
|
10459
|
+
});
|
|
10460
|
+
}
|
|
10461
|
+
if (groups.length || targets.length) {
|
|
10462
|
+
throw usageError("Error: --group and --target cannot be combined with --all (a plan slice belongs to one project)", {
|
|
10463
|
+
message: "--group and --target cannot be combined with --all (a plan slice belongs to one project)",
|
|
10464
|
+
details: { command, usage }
|
|
10465
|
+
});
|
|
10466
|
+
}
|
|
10467
|
+
await triggerRunAll({
|
|
10468
|
+
provider: getString(input.values, "provider"),
|
|
10469
|
+
wait: getBoolean(input.values, "wait"),
|
|
10470
|
+
allLocations: getBoolean(input.values, "all-locations"),
|
|
10471
|
+
noLocation: getBoolean(input.values, "no-location"),
|
|
10472
|
+
format: input.format
|
|
10473
|
+
});
|
|
10474
|
+
return;
|
|
10475
|
+
}
|
|
10476
|
+
if (queries2.length && (groups.length || targets.length)) {
|
|
10477
|
+
throw usageError("Error: --query cannot be combined with --group or --target (pick questions, or pick a slice of the plan)", {
|
|
10478
|
+
message: "--query cannot be combined with --group or --target (pick questions, or pick a slice of the plan)",
|
|
10479
|
+
details: { command, usage }
|
|
10480
|
+
});
|
|
10481
|
+
}
|
|
10482
|
+
const project = requireProject(
|
|
10483
|
+
input,
|
|
10484
|
+
command,
|
|
10485
|
+
usage,
|
|
10486
|
+
command === "run" ? "project name is required (or use --all)" : "project name is required"
|
|
10487
|
+
);
|
|
10488
|
+
await triggerRun(project, {
|
|
10489
|
+
provider: getString(input.values, "provider"),
|
|
10490
|
+
queries: queries2.length ? queries2 : void 0,
|
|
10491
|
+
groups: groups.length ? groups : void 0,
|
|
10492
|
+
targets: targets.length ? targets : void 0,
|
|
10493
|
+
wait: getBoolean(input.values, "wait"),
|
|
10494
|
+
location: getString(input.values, "location"),
|
|
10495
|
+
allLocations: getBoolean(input.values, "all-locations"),
|
|
10496
|
+
noLocation: getBoolean(input.values, "no-location"),
|
|
10497
|
+
probe: getBoolean(input.values, "probe"),
|
|
10498
|
+
format: input.format
|
|
10499
|
+
});
|
|
10500
|
+
}
|
|
10198
10501
|
var RUN_CLI_COMMANDS = [
|
|
10199
10502
|
{
|
|
10200
10503
|
path: ["run", "show"],
|
|
@@ -10216,69 +10519,25 @@ var RUN_CLI_COMMANDS = [
|
|
|
10216
10519
|
await cancelRun(project, input.positionals[1], input.format);
|
|
10217
10520
|
}
|
|
10218
10521
|
},
|
|
10522
|
+
{
|
|
10523
|
+
path: ["run", "trigger"],
|
|
10524
|
+
usage: RUN_TRIGGER_USAGE,
|
|
10525
|
+
options: RUN_TRIGGER_OPTIONS,
|
|
10526
|
+
run: (input) => triggerRunCommand(
|
|
10527
|
+
// `canonry run trigger` with nothing after it is ambiguous: the
|
|
10528
|
+
// subcommand with no project, or the older form naming a project called
|
|
10529
|
+
// "trigger". Nobody types the subcommand without a project, and a project
|
|
10530
|
+
// whose name collides with a keyword still has to be runnable, so the
|
|
10531
|
+
// project wins and the word is handed back as the positional.
|
|
10532
|
+
input.positionals.length === 0 && !getBoolean(input.values, "all") ? { ...input, positionals: ["trigger"] } : input,
|
|
10533
|
+
"run.trigger"
|
|
10534
|
+
)
|
|
10535
|
+
},
|
|
10219
10536
|
{
|
|
10220
10537
|
path: ["run"],
|
|
10221
|
-
usage:
|
|
10222
|
-
options:
|
|
10223
|
-
|
|
10224
|
-
query: multiStringOption(),
|
|
10225
|
-
wait: { type: "boolean", default: false },
|
|
10226
|
-
all: { type: "boolean", default: false },
|
|
10227
|
-
location: stringOption(),
|
|
10228
|
-
"all-locations": { type: "boolean", default: false },
|
|
10229
|
-
"no-location": { type: "boolean", default: false },
|
|
10230
|
-
// Probe runs are operator/agent test runs — they write a snapshot
|
|
10231
|
-
// for inspection but are excluded from dashboard / analytics /
|
|
10232
|
-
// intelligence / notifications. Use when you want to verify a
|
|
10233
|
-
// provider works without polluting the project's metrics.
|
|
10234
|
-
probe: { type: "boolean", default: false }
|
|
10235
|
-
},
|
|
10236
|
-
run: async (input) => {
|
|
10237
|
-
if (getBoolean(input.values, "all")) {
|
|
10238
|
-
if (input.positionals.length > 0) {
|
|
10239
|
-
throw usageError("Error: --all cannot be combined with a project name", {
|
|
10240
|
-
message: "--all cannot be combined with a project name",
|
|
10241
|
-
details: {
|
|
10242
|
-
command: "run",
|
|
10243
|
-
usage: "canonry run --all [--provider <name>] [--wait] [--format json]"
|
|
10244
|
-
}
|
|
10245
|
-
});
|
|
10246
|
-
}
|
|
10247
|
-
if (getStringArray(input.values, "query")?.length) {
|
|
10248
|
-
throw usageError("Error: --query cannot be combined with --all (query scope is project-specific)", {
|
|
10249
|
-
message: "--query cannot be combined with --all (query scope is project-specific)",
|
|
10250
|
-
details: {
|
|
10251
|
-
command: "run",
|
|
10252
|
-
usage: "canonry run <project> --query <q>... [--provider <name>] [--wait] [--format json]"
|
|
10253
|
-
}
|
|
10254
|
-
});
|
|
10255
|
-
}
|
|
10256
|
-
await triggerRunAll({
|
|
10257
|
-
provider: getString(input.values, "provider"),
|
|
10258
|
-
wait: getBoolean(input.values, "wait"),
|
|
10259
|
-
allLocations: getBoolean(input.values, "all-locations"),
|
|
10260
|
-
noLocation: getBoolean(input.values, "no-location"),
|
|
10261
|
-
format: input.format
|
|
10262
|
-
});
|
|
10263
|
-
return;
|
|
10264
|
-
}
|
|
10265
|
-
const project = requireProject(
|
|
10266
|
-
input,
|
|
10267
|
-
"run",
|
|
10268
|
-
"canonry run <project> [--provider <name>] [--query <q>...] [--wait] [--format json]",
|
|
10269
|
-
"project name is required (or use --all)"
|
|
10270
|
-
);
|
|
10271
|
-
await triggerRun(project, {
|
|
10272
|
-
provider: getString(input.values, "provider"),
|
|
10273
|
-
queries: getStringArray(input.values, "query"),
|
|
10274
|
-
wait: getBoolean(input.values, "wait"),
|
|
10275
|
-
location: getString(input.values, "location"),
|
|
10276
|
-
allLocations: getBoolean(input.values, "all-locations"),
|
|
10277
|
-
noLocation: getBoolean(input.values, "no-location"),
|
|
10278
|
-
probe: getBoolean(input.values, "probe"),
|
|
10279
|
-
format: input.format
|
|
10280
|
-
});
|
|
10281
|
-
}
|
|
10538
|
+
usage: RUN_USAGE2,
|
|
10539
|
+
options: RUN_TRIGGER_OPTIONS,
|
|
10540
|
+
run: (input) => triggerRunCommand(input, "run")
|
|
10282
10541
|
},
|
|
10283
10542
|
{
|
|
10284
10543
|
path: ["runs"],
|
|
@@ -10303,11 +10562,11 @@ var RUN_CLI_COMMANDS = [
|
|
|
10303
10562
|
];
|
|
10304
10563
|
|
|
10305
10564
|
// src/commands/schedule.ts
|
|
10306
|
-
function
|
|
10565
|
+
function getClient24() {
|
|
10307
10566
|
return createApiClient();
|
|
10308
10567
|
}
|
|
10309
10568
|
async function setSchedule(project, opts) {
|
|
10310
|
-
const client =
|
|
10569
|
+
const client = getClient24();
|
|
10311
10570
|
const body = {};
|
|
10312
10571
|
if (opts.kind) body.kind = opts.kind;
|
|
10313
10572
|
if (opts.sourceId) body.sourceId = opts.sourceId;
|
|
@@ -10324,7 +10583,7 @@ async function setSchedule(project, opts) {
|
|
|
10324
10583
|
printSchedule(result);
|
|
10325
10584
|
}
|
|
10326
10585
|
async function showSchedule(project, format, kind) {
|
|
10327
|
-
const client =
|
|
10586
|
+
const client = getClient24();
|
|
10328
10587
|
const result = await client.getSchedule(project, kind);
|
|
10329
10588
|
if (isMachineFormat(format)) {
|
|
10330
10589
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -10333,7 +10592,7 @@ async function showSchedule(project, format, kind) {
|
|
|
10333
10592
|
printSchedule(result);
|
|
10334
10593
|
}
|
|
10335
10594
|
async function enableSchedule(project, format, kind) {
|
|
10336
|
-
const client =
|
|
10595
|
+
const client = getClient24();
|
|
10337
10596
|
const current = await client.getSchedule(project, kind);
|
|
10338
10597
|
const body = { kind: current.kind, timezone: current.timezone, enabled: true };
|
|
10339
10598
|
if (current.preset) body.preset = current.preset;
|
|
@@ -10348,7 +10607,7 @@ async function enableSchedule(project, format, kind) {
|
|
|
10348
10607
|
console.log(`Schedule enabled for "${project}" (kind: ${result.kind})`);
|
|
10349
10608
|
}
|
|
10350
10609
|
async function disableSchedule(project, format, kind) {
|
|
10351
|
-
const client =
|
|
10610
|
+
const client = getClient24();
|
|
10352
10611
|
const current = await client.getSchedule(project, kind);
|
|
10353
10612
|
const body = { kind: current.kind, timezone: current.timezone, enabled: false };
|
|
10354
10613
|
if (current.preset) body.preset = current.preset;
|
|
@@ -10363,7 +10622,7 @@ async function disableSchedule(project, format, kind) {
|
|
|
10363
10622
|
console.log(`Schedule disabled for "${project}" (kind: ${result.kind})`);
|
|
10364
10623
|
}
|
|
10365
10624
|
async function removeSchedule(project, format, kind) {
|
|
10366
|
-
const client =
|
|
10625
|
+
const client = getClient24();
|
|
10367
10626
|
await client.deleteSchedule(project, kind);
|
|
10368
10627
|
const resolvedKind = kind ?? "answer-visibility";
|
|
10369
10628
|
if (isMachineFormat(format)) {
|
|
@@ -10481,11 +10740,11 @@ var SCHEDULE_CLI_COMMANDS = [
|
|
|
10481
10740
|
];
|
|
10482
10741
|
|
|
10483
10742
|
// src/commands/settings.ts
|
|
10484
|
-
function
|
|
10743
|
+
function getClient25() {
|
|
10485
10744
|
return createApiClient();
|
|
10486
10745
|
}
|
|
10487
10746
|
async function setProvider(name, opts) {
|
|
10488
|
-
const client =
|
|
10747
|
+
const client = getClient25();
|
|
10489
10748
|
const { format, ...payload } = opts;
|
|
10490
10749
|
const result = await client.updateProvider(name, payload);
|
|
10491
10750
|
if (isMachineFormat(format)) {
|
|
@@ -10501,7 +10760,7 @@ async function setProvider(name, opts) {
|
|
|
10501
10760
|
}
|
|
10502
10761
|
}
|
|
10503
10762
|
async function showSettings(format) {
|
|
10504
|
-
const client =
|
|
10763
|
+
const client = getClient25();
|
|
10505
10764
|
const config = loadConfig();
|
|
10506
10765
|
const settings = await client.getSettings();
|
|
10507
10766
|
if (isMachineFormat(format)) {
|
|
@@ -11051,7 +11310,7 @@ function wrapText(font, text, size, maxWidth) {
|
|
|
11051
11310
|
}
|
|
11052
11311
|
|
|
11053
11312
|
// src/commands/snapshot.ts
|
|
11054
|
-
function
|
|
11313
|
+
function getClient26() {
|
|
11055
11314
|
return createApiClient();
|
|
11056
11315
|
}
|
|
11057
11316
|
function slugify(value) {
|
|
@@ -11062,7 +11321,7 @@ function autoOutputPath(companyName, ext) {
|
|
|
11062
11321
|
return `${slugify(companyName)}-snapshot-${date}.${ext}`;
|
|
11063
11322
|
}
|
|
11064
11323
|
async function createSnapshotReport(companyName, opts) {
|
|
11065
|
-
const client =
|
|
11324
|
+
const client = getClient26();
|
|
11066
11325
|
const report = await client.createSnapshot({
|
|
11067
11326
|
companyName,
|
|
11068
11327
|
domain: opts.domain,
|
|
@@ -12508,7 +12767,7 @@ function stopDaemon(format = "text") {
|
|
|
12508
12767
|
// src/commands/init.ts
|
|
12509
12768
|
import crypto2 from "crypto";
|
|
12510
12769
|
import fs13 from "fs";
|
|
12511
|
-
import
|
|
12770
|
+
import readline2 from "readline";
|
|
12512
12771
|
import path10 from "path";
|
|
12513
12772
|
var pendingServeHandoff = false;
|
|
12514
12773
|
function consumePendingServeHandoff() {
|
|
@@ -12525,7 +12784,7 @@ async function promptProviderApiKey(label, envVar, promptFn = prompt, env = proc
|
|
|
12525
12784
|
return promptFn(`${label} API key (press Enter to skip): `);
|
|
12526
12785
|
}
|
|
12527
12786
|
function prompt(question) {
|
|
12528
|
-
const rl =
|
|
12787
|
+
const rl = readline2.createInterface({
|
|
12529
12788
|
input: process.stdin,
|
|
12530
12789
|
output: process.stdout
|
|
12531
12790
|
});
|
|
@@ -13438,11 +13697,11 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
13438
13697
|
];
|
|
13439
13698
|
|
|
13440
13699
|
// src/commands/technical-aeo.ts
|
|
13441
|
-
function
|
|
13700
|
+
function getClient27() {
|
|
13442
13701
|
return createApiClient();
|
|
13443
13702
|
}
|
|
13444
13703
|
async function technicalAeoScore(project, opts) {
|
|
13445
|
-
const client =
|
|
13704
|
+
const client = getClient27();
|
|
13446
13705
|
const score = await client.getTechnicalAeoScore(project, { runId: opts.runId });
|
|
13447
13706
|
if (isMachineFormat(opts.format)) {
|
|
13448
13707
|
console.log(JSON.stringify(score, null, 2));
|
|
@@ -13478,7 +13737,7 @@ async function technicalAeoScore(project, opts) {
|
|
|
13478
13737
|
console.log(lines.join("\n"));
|
|
13479
13738
|
}
|
|
13480
13739
|
async function technicalAeoPages(project, opts) {
|
|
13481
|
-
const client =
|
|
13740
|
+
const client = getClient27();
|
|
13482
13741
|
const status = opts.status === "success" || opts.status === "error" ? opts.status : void 0;
|
|
13483
13742
|
const res = await client.getTechnicalAeoPages(project, { runId: opts.runId, status, sort: opts.sort, limit: opts.limit });
|
|
13484
13743
|
if (opts.format === "jsonl") {
|
|
@@ -13504,7 +13763,7 @@ async function technicalAeoPages(project, opts) {
|
|
|
13504
13763
|
console.log(lines.join("\n"));
|
|
13505
13764
|
}
|
|
13506
13765
|
async function technicalAeoTrend(project, opts) {
|
|
13507
|
-
const client =
|
|
13766
|
+
const client = getClient27();
|
|
13508
13767
|
const res = await client.getTechnicalAeoTrend(project, { limit: opts.limit });
|
|
13509
13768
|
if (opts.format === "jsonl") {
|
|
13510
13769
|
emitJsonl(res.points.map((p) => ({ project, ...p })));
|
|
@@ -13526,7 +13785,7 @@ async function technicalAeoTrend(project, opts) {
|
|
|
13526
13785
|
console.log(lines.join("\n"));
|
|
13527
13786
|
}
|
|
13528
13787
|
async function technicalAeoRun(project, opts) {
|
|
13529
|
-
const client =
|
|
13788
|
+
const client = getClient27();
|
|
13530
13789
|
const { runId, status } = await client.triggerSiteAudit(project, {
|
|
13531
13790
|
sitemapUrl: opts.sitemapUrl,
|
|
13532
13791
|
limit: opts.limit
|
|
@@ -13885,7 +14144,7 @@ var VISIBILITY_STATS_CLI_COMMANDS = [
|
|
|
13885
14144
|
import fs15 from "fs";
|
|
13886
14145
|
|
|
13887
14146
|
// src/commands/wordpress.ts
|
|
13888
|
-
function
|
|
14147
|
+
function getClient28() {
|
|
13889
14148
|
return createApiClient();
|
|
13890
14149
|
}
|
|
13891
14150
|
async function loadYamlModule() {
|
|
@@ -14035,7 +14294,7 @@ async function wordpressConnect(project, opts) {
|
|
|
14035
14294
|
details: { project }
|
|
14036
14295
|
});
|
|
14037
14296
|
}
|
|
14038
|
-
const client =
|
|
14297
|
+
const client = getClient28();
|
|
14039
14298
|
const result = await client.wordpressConnect(project, {
|
|
14040
14299
|
url: opts.url,
|
|
14041
14300
|
stagingUrl: opts.stagingUrl,
|
|
@@ -14052,7 +14311,7 @@ async function wordpressConnect(project, opts) {
|
|
|
14052
14311
|
printWordpressStatus(project, result);
|
|
14053
14312
|
}
|
|
14054
14313
|
async function wordpressDisconnect(project, format) {
|
|
14055
|
-
const client =
|
|
14314
|
+
const client = getClient28();
|
|
14056
14315
|
await client.wordpressDisconnect(project);
|
|
14057
14316
|
if (isMachineFormat(format)) {
|
|
14058
14317
|
printJson2({ project, disconnected: true });
|
|
@@ -14061,7 +14320,7 @@ async function wordpressDisconnect(project, format) {
|
|
|
14061
14320
|
console.log(`WordPress disconnected from project "${project}".`);
|
|
14062
14321
|
}
|
|
14063
14322
|
async function wordpressStatus(project, format) {
|
|
14064
|
-
const client =
|
|
14323
|
+
const client = getClient28();
|
|
14065
14324
|
const result = await client.wordpressStatus(project);
|
|
14066
14325
|
if (isMachineFormat(format)) {
|
|
14067
14326
|
printJson2(result);
|
|
@@ -14070,7 +14329,7 @@ async function wordpressStatus(project, format) {
|
|
|
14070
14329
|
printWordpressStatus(project, result);
|
|
14071
14330
|
}
|
|
14072
14331
|
async function wordpressPages(project, opts) {
|
|
14073
|
-
const client =
|
|
14332
|
+
const client = getClient28();
|
|
14074
14333
|
const result = await client.wordpressPages(project, opts.env);
|
|
14075
14334
|
if (isMachineFormat(opts.format)) {
|
|
14076
14335
|
printJson2(result);
|
|
@@ -14079,7 +14338,7 @@ async function wordpressPages(project, opts) {
|
|
|
14079
14338
|
printPages(project, result.env, result.pages);
|
|
14080
14339
|
}
|
|
14081
14340
|
async function wordpressPage(project, slug, opts) {
|
|
14082
|
-
const client =
|
|
14341
|
+
const client = getClient28();
|
|
14083
14342
|
const result = await client.wordpressPage(project, slug, opts.env);
|
|
14084
14343
|
if (isMachineFormat(opts.format)) {
|
|
14085
14344
|
printJson2(result);
|
|
@@ -14088,7 +14347,7 @@ async function wordpressPage(project, slug, opts) {
|
|
|
14088
14347
|
printPageDetail(result);
|
|
14089
14348
|
}
|
|
14090
14349
|
async function wordpressCreatePage(project, body) {
|
|
14091
|
-
const client =
|
|
14350
|
+
const client = getClient28();
|
|
14092
14351
|
const result = await client.wordpressCreatePage(project, body);
|
|
14093
14352
|
if (isMachineFormat(body.format)) {
|
|
14094
14353
|
printJson2(result);
|
|
@@ -14099,7 +14358,7 @@ async function wordpressCreatePage(project, body) {
|
|
|
14099
14358
|
printPageDetail(result);
|
|
14100
14359
|
}
|
|
14101
14360
|
async function wordpressUpdatePage(project, body) {
|
|
14102
|
-
const client =
|
|
14361
|
+
const client = getClient28();
|
|
14103
14362
|
const result = await client.wordpressUpdatePage(project, body);
|
|
14104
14363
|
if (isMachineFormat(body.format)) {
|
|
14105
14364
|
printJson2(result);
|
|
@@ -14110,7 +14369,7 @@ async function wordpressUpdatePage(project, body) {
|
|
|
14110
14369
|
printPageDetail(result);
|
|
14111
14370
|
}
|
|
14112
14371
|
async function wordpressSetMeta(project, body) {
|
|
14113
|
-
const client =
|
|
14372
|
+
const client = getClient28();
|
|
14114
14373
|
const result = await client.wordpressSetMeta(project, body);
|
|
14115
14374
|
if (isMachineFormat(body.format)) {
|
|
14116
14375
|
printJson2(result);
|
|
@@ -14160,7 +14419,7 @@ async function wordpressBulkSetMeta(project, opts) {
|
|
|
14160
14419
|
details: { path: filePath }
|
|
14161
14420
|
});
|
|
14162
14421
|
}
|
|
14163
|
-
const client =
|
|
14422
|
+
const client = getClient28();
|
|
14164
14423
|
const result = await client.wordpressBulkSetMeta(project, { entries, env: opts.env });
|
|
14165
14424
|
if (isMachineFormat(opts.format)) {
|
|
14166
14425
|
printJson2(result);
|
|
@@ -14203,7 +14462,7 @@ async function wordpressBulkSetMeta(project, opts) {
|
|
|
14203
14462
|
Total: ${applied.length} applied, ${skipped.length} skipped, ${manual.length} manual`);
|
|
14204
14463
|
}
|
|
14205
14464
|
async function wordpressSchema(project, slug, opts) {
|
|
14206
|
-
const client =
|
|
14465
|
+
const client = getClient28();
|
|
14207
14466
|
const result = await client.wordpressSchema(project, slug, opts.env);
|
|
14208
14467
|
if (isMachineFormat(opts.format)) {
|
|
14209
14468
|
printJson2(result);
|
|
@@ -14214,7 +14473,7 @@ async function wordpressSchema(project, slug, opts) {
|
|
|
14214
14473
|
printSchemaBlocks(result.blocks);
|
|
14215
14474
|
}
|
|
14216
14475
|
async function wordpressSetSchema(project, body) {
|
|
14217
|
-
const client =
|
|
14476
|
+
const client = getClient28();
|
|
14218
14477
|
const result = await client.wordpressSetSchema(project, body);
|
|
14219
14478
|
if (isMachineFormat(body.format)) {
|
|
14220
14479
|
printJson2(result);
|
|
@@ -14262,7 +14521,7 @@ async function wordpressSchemaDeploy(project, opts) {
|
|
|
14262
14521
|
details: { path: filePath }
|
|
14263
14522
|
});
|
|
14264
14523
|
}
|
|
14265
|
-
const client =
|
|
14524
|
+
const client = getClient28();
|
|
14266
14525
|
const result = await client.wordpressSchemaDeploy(project, { profile: parsed, env: opts.env });
|
|
14267
14526
|
if (isMachineFormat(opts.format)) {
|
|
14268
14527
|
printJson2(result);
|
|
@@ -14301,7 +14560,7 @@ async function wordpressSchemaDeploy(project, opts) {
|
|
|
14301
14560
|
Total: ${deployed} deployed, ${stripped} stripped, ${skipped} skipped, ${failed} failed`);
|
|
14302
14561
|
}
|
|
14303
14562
|
async function wordpressSchemaStatus(project, opts) {
|
|
14304
|
-
const client =
|
|
14563
|
+
const client = getClient28();
|
|
14305
14564
|
const result = await client.wordpressSchemaStatus(project, opts.env);
|
|
14306
14565
|
if (isMachineFormat(opts.format)) {
|
|
14307
14566
|
printJson2(result);
|
|
@@ -14360,7 +14619,7 @@ async function wordpressOnboard(project, opts) {
|
|
|
14360
14619
|
});
|
|
14361
14620
|
}
|
|
14362
14621
|
}
|
|
14363
|
-
const client =
|
|
14622
|
+
const client = getClient28();
|
|
14364
14623
|
const result = await client.wordpressOnboard(project, {
|
|
14365
14624
|
url: opts.url,
|
|
14366
14625
|
username: opts.user,
|
|
@@ -14385,7 +14644,7 @@ async function wordpressOnboard(project, opts) {
|
|
|
14385
14644
|
}
|
|
14386
14645
|
}
|
|
14387
14646
|
async function wordpressLlmsTxt(project, opts) {
|
|
14388
|
-
const client =
|
|
14647
|
+
const client = getClient28();
|
|
14389
14648
|
const result = await client.wordpressLlmsTxt(project, opts.env);
|
|
14390
14649
|
if (isMachineFormat(opts.format)) {
|
|
14391
14650
|
printJson2(result);
|
|
@@ -14396,7 +14655,7 @@ async function wordpressLlmsTxt(project, opts) {
|
|
|
14396
14655
|
console.log(result.content ?? "(not found)");
|
|
14397
14656
|
}
|
|
14398
14657
|
async function wordpressSetLlmsTxt(project, body) {
|
|
14399
|
-
const client =
|
|
14658
|
+
const client = getClient28();
|
|
14400
14659
|
const result = await client.wordpressSetLlmsTxt(project, body);
|
|
14401
14660
|
if (isMachineFormat(body.format)) {
|
|
14402
14661
|
printJson2(result);
|
|
@@ -14405,7 +14664,7 @@ async function wordpressSetLlmsTxt(project, body) {
|
|
|
14405
14664
|
printManualAssist(`llms.txt update for "${project}"`, result);
|
|
14406
14665
|
}
|
|
14407
14666
|
async function wordpressAudit(project, opts) {
|
|
14408
|
-
const client =
|
|
14667
|
+
const client = getClient28();
|
|
14409
14668
|
const result = await client.wordpressAudit(project, opts.env);
|
|
14410
14669
|
if (isMachineFormat(opts.format)) {
|
|
14411
14670
|
printJson2(result);
|
|
@@ -14419,7 +14678,7 @@ async function wordpressAudit(project, opts) {
|
|
|
14419
14678
|
printAuditIssues(result.issues);
|
|
14420
14679
|
}
|
|
14421
14680
|
async function wordpressDiff(project, slug, format) {
|
|
14422
|
-
const client =
|
|
14681
|
+
const client = getClient28();
|
|
14423
14682
|
const result = await client.wordpressDiff(project, slug);
|
|
14424
14683
|
if (isMachineFormat(format)) {
|
|
14425
14684
|
printJson2(result);
|
|
@@ -14428,7 +14687,7 @@ async function wordpressDiff(project, slug, format) {
|
|
|
14428
14687
|
printDiff(result);
|
|
14429
14688
|
}
|
|
14430
14689
|
async function wordpressStagingStatus(project, format) {
|
|
14431
|
-
const client =
|
|
14690
|
+
const client = getClient28();
|
|
14432
14691
|
const result = await client.wordpressStagingStatus(project);
|
|
14433
14692
|
if (isMachineFormat(format)) {
|
|
14434
14693
|
printJson2(result);
|
|
@@ -14442,7 +14701,7 @@ async function wordpressStagingStatus(project, format) {
|
|
|
14442
14701
|
console.log(` Admin URL: ${result.adminUrl}`);
|
|
14443
14702
|
}
|
|
14444
14703
|
async function wordpressStagingPush(project, format) {
|
|
14445
|
-
const client =
|
|
14704
|
+
const client = getClient28();
|
|
14446
14705
|
const result = await client.wordpressStagingPush(project);
|
|
14447
14706
|
if (isMachineFormat(format)) {
|
|
14448
14707
|
printJson2(result);
|
|
@@ -15571,6 +15830,7 @@ var REGISTERED_CLI_COMMANDS = [
|
|
|
15571
15830
|
...QUERY_CLI_COMMANDS,
|
|
15572
15831
|
...KEYWORD_CLI_COMMANDS,
|
|
15573
15832
|
...KEYS_CLI_COMMANDS,
|
|
15833
|
+
...USERS_CLI_COMMANDS,
|
|
15574
15834
|
...COMPETITOR_CLI_COMMANDS,
|
|
15575
15835
|
...SETTINGS_CLI_COMMANDS,
|
|
15576
15836
|
...SKILLS_CLI_COMMANDS,
|