@ainyc/canonry 1.37.0 → 1.38.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/{index-BZX6FEZ4.css → index-CM92zXYn.css} +1 -1
- package/assets/assets/{index-DR4zYsnw.js → index-Du9ZvTq9.js} +55 -55
- package/assets/index.html +2 -2
- package/dist/{chunk-5MOWJJND.js → chunk-SAVCFB5B.js} +398 -213
- package/dist/cli.js +54 -51
- package/dist/index.js +1 -1
- package/package.json +8 -8
package/dist/cli.js
CHANGED
|
@@ -26,22 +26,26 @@ import {
|
|
|
26
26
|
setGoogleAuthConfig,
|
|
27
27
|
showFirstRunNotice,
|
|
28
28
|
trackEvent
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-SAVCFB5B.js";
|
|
30
30
|
|
|
31
31
|
// src/cli.ts
|
|
32
32
|
import { pathToFileURL } from "url";
|
|
33
33
|
|
|
34
34
|
// src/cli-error.ts
|
|
35
|
+
var EXIT_USER_ERROR = 1;
|
|
36
|
+
var EXIT_SYSTEM_ERROR = 2;
|
|
35
37
|
var CliError = class extends Error {
|
|
36
38
|
code;
|
|
37
39
|
displayMessage;
|
|
38
40
|
details;
|
|
41
|
+
exitCode;
|
|
39
42
|
constructor(options) {
|
|
40
43
|
super(options.message);
|
|
41
44
|
this.name = "CliError";
|
|
42
45
|
this.code = options.code;
|
|
43
46
|
this.displayMessage = options.displayMessage;
|
|
44
47
|
this.details = options.details;
|
|
48
|
+
this.exitCode = options.exitCode ?? EXIT_USER_ERROR;
|
|
45
49
|
}
|
|
46
50
|
};
|
|
47
51
|
function usageError(displayMessage, options) {
|
|
@@ -398,13 +402,16 @@ var ApiClient = class {
|
|
|
398
402
|
body: serializedBody
|
|
399
403
|
});
|
|
400
404
|
} catch (err) {
|
|
405
|
+
if (err instanceof CliError) throw err;
|
|
401
406
|
const msg = err instanceof Error ? err.message : String(err);
|
|
402
407
|
if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED") || msg.includes("connect ECONNREFUSED")) {
|
|
403
|
-
throw new
|
|
404
|
-
|
|
405
|
-
|
|
408
|
+
throw new CliError({
|
|
409
|
+
code: "CONNECTION_ERROR",
|
|
410
|
+
message: `Could not connect to canonry server at ${this.baseUrl.replace("/api/v1", "")}. Start it with "canonry serve" (or "canonry serve &" to run in background).`,
|
|
411
|
+
exitCode: EXIT_SYSTEM_ERROR
|
|
412
|
+
});
|
|
406
413
|
}
|
|
407
|
-
throw
|
|
414
|
+
throw new CliError({ code: "CONNECTION_ERROR", message: msg, exitCode: EXIT_SYSTEM_ERROR });
|
|
408
415
|
}
|
|
409
416
|
if (!res.ok) {
|
|
410
417
|
let errorBody;
|
|
@@ -413,8 +420,11 @@ var ApiClient = class {
|
|
|
413
420
|
} catch {
|
|
414
421
|
errorBody = { error: { code: "UNKNOWN", message: res.statusText } };
|
|
415
422
|
}
|
|
416
|
-
const
|
|
417
|
-
|
|
423
|
+
const errorObj = errorBody && typeof errorBody === "object" && "error" in errorBody && errorBody.error && typeof errorBody.error === "object" ? errorBody.error : null;
|
|
424
|
+
const msg = errorObj?.message ? String(errorObj.message) : `HTTP ${res.status}: ${res.statusText}`;
|
|
425
|
+
const code = errorObj?.code ? String(errorObj.code) : "API_ERROR";
|
|
426
|
+
const exitCode = res.status >= 500 ? EXIT_SYSTEM_ERROR : EXIT_USER_ERROR;
|
|
427
|
+
throw new CliError({ code, message: msg, exitCode });
|
|
418
428
|
}
|
|
419
429
|
if (res.status === 204) {
|
|
420
430
|
return void 0;
|
|
@@ -751,22 +761,12 @@ function getClient() {
|
|
|
751
761
|
return createApiClient();
|
|
752
762
|
}
|
|
753
763
|
async function bingConnect(project, opts) {
|
|
754
|
-
|
|
755
|
-
if (!apiKey) {
|
|
756
|
-
const readline2 = await import("readline");
|
|
757
|
-
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
758
|
-
apiKey = await new Promise((resolve) => {
|
|
759
|
-
rl.question("Bing Webmaster Tools API key: ", (answer) => {
|
|
760
|
-
rl.close();
|
|
761
|
-
resolve(answer.trim());
|
|
762
|
-
});
|
|
763
|
-
});
|
|
764
|
-
}
|
|
764
|
+
const apiKey = opts?.apiKey;
|
|
765
765
|
if (!apiKey) {
|
|
766
766
|
throw new CliError({
|
|
767
767
|
code: "BING_API_KEY_REQUIRED",
|
|
768
|
-
message: "API key is required
|
|
769
|
-
displayMessage: "Error: API key is required
|
|
768
|
+
message: "API key is required. Pass --api-key <key>.",
|
|
769
|
+
displayMessage: "Error: API key is required. Pass --api-key <key>.",
|
|
770
770
|
details: {
|
|
771
771
|
project
|
|
772
772
|
}
|
|
@@ -1698,7 +1698,11 @@ async function addCompetitors(project, domains, format) {
|
|
|
1698
1698
|
}, null, 2));
|
|
1699
1699
|
return;
|
|
1700
1700
|
}
|
|
1701
|
-
|
|
1701
|
+
if (addedDomains.length === 0) {
|
|
1702
|
+
console.log(`No new competitors added to "${project}" (all already tracked).`);
|
|
1703
|
+
} else {
|
|
1704
|
+
console.log(`Added ${addedDomains.length} competitor(s) to "${project}".`);
|
|
1705
|
+
}
|
|
1702
1706
|
}
|
|
1703
1707
|
async function listCompetitors(project, format) {
|
|
1704
1708
|
const client = getClient4();
|
|
@@ -3283,13 +3287,13 @@ async function showStatus(project, format) {
|
|
|
3283
3287
|
console.log(JSON.stringify({ project: projectData, runs: runs2 }, null, 2));
|
|
3284
3288
|
return;
|
|
3285
3289
|
}
|
|
3286
|
-
console.log(`Status: ${projectData.displayName} (${projectData.name})
|
|
3290
|
+
console.log(`Status: ${projectData.displayName ?? projectData.name} (${projectData.name})
|
|
3287
3291
|
`);
|
|
3288
3292
|
console.log(` Domain: ${projectData.canonicalDomain}`);
|
|
3289
3293
|
console.log(` Country: ${projectData.country}`);
|
|
3290
3294
|
console.log(` Language: ${projectData.language}`);
|
|
3291
3295
|
if (runs2.length > 0) {
|
|
3292
|
-
const latest = runs2[
|
|
3296
|
+
const latest = runs2[0];
|
|
3293
3297
|
console.log(`
|
|
3294
3298
|
Latest run:`);
|
|
3295
3299
|
console.log(` ID: ${latest.id}`);
|
|
@@ -3309,25 +3313,25 @@ async function showStatus(project, format) {
|
|
|
3309
3313
|
var OPERATOR_CLI_COMMANDS = [
|
|
3310
3314
|
{
|
|
3311
3315
|
path: ["status"],
|
|
3312
|
-
usage: "canonry status <project>",
|
|
3316
|
+
usage: "canonry status <project> [--format json]",
|
|
3313
3317
|
run: async (input) => {
|
|
3314
|
-
const project = requireProject(input, "status", "canonry status <project>");
|
|
3318
|
+
const project = requireProject(input, "status", "canonry status <project> [--format json]");
|
|
3315
3319
|
await showStatus(project, input.format);
|
|
3316
3320
|
}
|
|
3317
3321
|
},
|
|
3318
3322
|
{
|
|
3319
3323
|
path: ["evidence"],
|
|
3320
|
-
usage: "canonry evidence <project>",
|
|
3324
|
+
usage: "canonry evidence <project> [--format json]",
|
|
3321
3325
|
run: async (input) => {
|
|
3322
|
-
const project = requireProject(input, "evidence", "canonry evidence <project>");
|
|
3326
|
+
const project = requireProject(input, "evidence", "canonry evidence <project> [--format json]");
|
|
3323
3327
|
await showEvidence(project, input.format);
|
|
3324
3328
|
}
|
|
3325
3329
|
},
|
|
3326
3330
|
{
|
|
3327
3331
|
path: ["history"],
|
|
3328
|
-
usage: "canonry history <project>",
|
|
3332
|
+
usage: "canonry history <project> [--format json]",
|
|
3329
3333
|
run: async (input) => {
|
|
3330
|
-
const project = requireProject(input, "history", "canonry history <project>");
|
|
3334
|
+
const project = requireProject(input, "history", "canonry history <project> [--format json]");
|
|
3331
3335
|
await showHistory(project, input.format);
|
|
3332
3336
|
}
|
|
3333
3337
|
},
|
|
@@ -3433,7 +3437,7 @@ async function showProject(name, format) {
|
|
|
3433
3437
|
console.log(JSON.stringify(project, null, 2));
|
|
3434
3438
|
return;
|
|
3435
3439
|
}
|
|
3436
|
-
console.log(`Project: ${project.displayName}
|
|
3440
|
+
console.log(`Project: ${project.displayName ?? project.name}
|
|
3437
3441
|
`);
|
|
3438
3442
|
console.log(` Name: ${project.name}`);
|
|
3439
3443
|
console.log(` ID: ${project.id}`);
|
|
@@ -3449,8 +3453,8 @@ async function showProject(name, format) {
|
|
|
3449
3453
|
console.log(` Tags: ${project.tags.length > 0 ? project.tags.join(", ") : "(none)"}`);
|
|
3450
3454
|
const labelEntries = Object.entries(project.labels);
|
|
3451
3455
|
console.log(` Labels: ${labelEntries.length > 0 ? labelEntries.map(([k, v]) => `${k}=${v}`).join(", ") : "(none)"}`);
|
|
3452
|
-
console.log(` Created: ${project.createdAt}`);
|
|
3453
|
-
console.log(` Updated: ${project.updatedAt}`);
|
|
3456
|
+
if (project.createdAt) console.log(` Created: ${project.createdAt}`);
|
|
3457
|
+
if (project.updatedAt) console.log(` Updated: ${project.updatedAt}`);
|
|
3454
3458
|
}
|
|
3455
3459
|
async function updateProjectSettings(name, opts) {
|
|
3456
3460
|
const client = getClient12();
|
|
@@ -3465,7 +3469,7 @@ async function updateProjectSettings(name, opts) {
|
|
|
3465
3469
|
ownedDomains = ownedDomains.filter((d) => !toRemove.has(d));
|
|
3466
3470
|
}
|
|
3467
3471
|
const result = await client.putProject(name, {
|
|
3468
|
-
displayName: opts.displayName ?? project.displayName,
|
|
3472
|
+
displayName: opts.displayName ?? project.displayName ?? project.name,
|
|
3469
3473
|
canonicalDomain: opts.domain ?? project.canonicalDomain,
|
|
3470
3474
|
ownedDomains,
|
|
3471
3475
|
country: opts.country ?? project.country,
|
|
@@ -5450,6 +5454,15 @@ async function serveCommand(format = "text") {
|
|
|
5450
5454
|
const db = createClient(config.database);
|
|
5451
5455
|
migrate(db);
|
|
5452
5456
|
const app = await createServer({ config, db });
|
|
5457
|
+
const shutdown = () => {
|
|
5458
|
+
app.close().then(() => {
|
|
5459
|
+
process.exit(0);
|
|
5460
|
+
}).catch(() => {
|
|
5461
|
+
process.exit(1);
|
|
5462
|
+
});
|
|
5463
|
+
};
|
|
5464
|
+
process.on("SIGTERM", shutdown);
|
|
5465
|
+
process.on("SIGINT", shutdown);
|
|
5453
5466
|
try {
|
|
5454
5467
|
await app.listen({ host, port });
|
|
5455
5468
|
const url = `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`;
|
|
@@ -5754,16 +5767,6 @@ import fs6 from "fs";
|
|
|
5754
5767
|
function getClient17() {
|
|
5755
5768
|
return createApiClient();
|
|
5756
5769
|
}
|
|
5757
|
-
async function promptForAppPassword() {
|
|
5758
|
-
const readline2 = await import("readline");
|
|
5759
|
-
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
5760
|
-
return new Promise((resolve) => {
|
|
5761
|
-
rl.question("WordPress Application Password: ", (answer) => {
|
|
5762
|
-
rl.close();
|
|
5763
|
-
resolve(answer.trim());
|
|
5764
|
-
});
|
|
5765
|
-
});
|
|
5766
|
-
}
|
|
5767
5770
|
function printJson(value) {
|
|
5768
5771
|
console.log(JSON.stringify(value, null, 2));
|
|
5769
5772
|
}
|
|
@@ -5899,12 +5902,12 @@ Staging:`);
|
|
|
5899
5902
|
console.log(` Snippet: ${diff.staging.contentSnippet || "(empty)"}`);
|
|
5900
5903
|
}
|
|
5901
5904
|
async function wordpressConnect(project, opts) {
|
|
5902
|
-
const appPassword = opts.appPassword
|
|
5905
|
+
const appPassword = opts.appPassword;
|
|
5903
5906
|
if (!appPassword) {
|
|
5904
5907
|
throw new CliError({
|
|
5905
5908
|
code: "WORDPRESS_APP_PASSWORD_REQUIRED",
|
|
5906
5909
|
message: "WordPress Application Password is required",
|
|
5907
|
-
displayMessage: "Error: WordPress Application Password is required
|
|
5910
|
+
displayMessage: "Error: WordPress Application Password is required. Pass --app-password <password>.",
|
|
5908
5911
|
details: { project }
|
|
5909
5912
|
});
|
|
5910
5913
|
}
|
|
@@ -6196,12 +6199,12 @@ async function wordpressSchemaStatus(project, opts) {
|
|
|
6196
6199
|
}
|
|
6197
6200
|
}
|
|
6198
6201
|
async function wordpressOnboard(project, opts) {
|
|
6199
|
-
const appPassword = opts.appPassword
|
|
6202
|
+
const appPassword = opts.appPassword;
|
|
6200
6203
|
if (!appPassword) {
|
|
6201
6204
|
throw new CliError({
|
|
6202
6205
|
code: "WORDPRESS_APP_PASSWORD_REQUIRED",
|
|
6203
6206
|
message: "WordPress Application Password is required",
|
|
6204
|
-
displayMessage: "Error: WordPress Application Password is required
|
|
6207
|
+
displayMessage: "Error: WordPress Application Password is required. Pass --app-password <password>.",
|
|
6205
6208
|
details: { project }
|
|
6206
6209
|
});
|
|
6207
6210
|
}
|
|
@@ -6853,10 +6856,10 @@ Usage:
|
|
|
6853
6856
|
canonry run --all Trigger runs for all projects
|
|
6854
6857
|
canonry run show <id> Show run details and snapshots
|
|
6855
6858
|
canonry runs <project> List runs for a project (--limit <n>)
|
|
6856
|
-
canonry status <project> Show project summary
|
|
6857
|
-
canonry evidence <project> Show per-phrase results
|
|
6859
|
+
canonry status <project> Show project summary [--format json]
|
|
6860
|
+
canonry evidence <project> Show per-phrase results [--format json]
|
|
6858
6861
|
canonry analytics <project> Show analytics (--feature metrics|gaps|sources, --window 7d|30d|90d|all)
|
|
6859
|
-
canonry history <project> Show audit trail
|
|
6862
|
+
canonry history <project> Show audit trail [--format json]
|
|
6860
6863
|
canonry export <project> Export project as YAML
|
|
6861
6864
|
canonry apply <file...> Apply declarative config (multi-doc YAML supported)
|
|
6862
6865
|
canonry schedule set <project> Set schedule (--preset or --cron)
|
|
@@ -7015,7 +7018,7 @@ Run "canonry --help" for usage.`, {
|
|
|
7015
7018
|
});
|
|
7016
7019
|
} catch (err) {
|
|
7017
7020
|
printCliError(err, format);
|
|
7018
|
-
return
|
|
7021
|
+
return err instanceof CliError ? err.exitCode : EXIT_SYSTEM_ERROR;
|
|
7019
7022
|
}
|
|
7020
7023
|
}
|
|
7021
7024
|
async function main(args = process.argv.slice(2)) {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The ultimate open-source AEO monitoring tool - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -55,18 +55,18 @@
|
|
|
55
55
|
"tsup": "^8.5.1",
|
|
56
56
|
"tsx": "^4.19.0",
|
|
57
57
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
58
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
59
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
60
|
-
"@ainyc/canonry-db": "0.0.0",
|
|
61
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
62
58
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
59
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
63
60
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
64
|
-
"@ainyc/canonry-
|
|
61
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
62
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
63
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
65
64
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
65
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
66
66
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
67
67
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
68
|
-
"@ainyc/canonry-provider-
|
|
69
|
-
"@ainyc/canonry-provider-
|
|
68
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-provider-local": "0.0.0"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "tsup && tsx build-web.ts",
|