@ainyc/canonry 1.34.0 → 1.35.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-CxMuEW6I.css → index-B9SBdBOm.css} +1 -1
- package/assets/assets/index-DyipkdOb.js +281 -0
- package/assets/index.html +2 -2
- package/dist/{chunk-4SRBJCNX.js → chunk-ETP5IOHC.js} +53 -9
- package/dist/cli.js +38 -4
- package/dist/index.js +1 -1
- package/package.json +6 -6
- package/assets/assets/index-BPuIj1DV.js +0 -246
package/assets/index.html
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
16
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-DyipkdOb.js"></script>
|
|
16
|
+
<link rel="stylesheet" crossorigin href="./assets/index-B9SBdBOm.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
19
19
|
<div id="root"></div>
|
|
@@ -1074,6 +1074,13 @@ var ga4TrafficSummaryDtoSchema = z11.object({
|
|
|
1074
1074
|
aiReferrals: z11.array(ga4AiReferralDtoSchema),
|
|
1075
1075
|
lastSyncedAt: z11.string().nullable()
|
|
1076
1076
|
});
|
|
1077
|
+
var ga4AiReferralHistoryEntrySchema = z11.object({
|
|
1078
|
+
date: z11.string(),
|
|
1079
|
+
source: z11.string(),
|
|
1080
|
+
medium: z11.string(),
|
|
1081
|
+
sessions: z11.number(),
|
|
1082
|
+
users: z11.number()
|
|
1083
|
+
});
|
|
1077
1084
|
|
|
1078
1085
|
// ../contracts/src/answer-visibility.ts
|
|
1079
1086
|
var GENERIC_TOKENS = /* @__PURE__ */ new Set([
|
|
@@ -5754,6 +5761,18 @@ var routeCatalog = [
|
|
|
5754
5761
|
404: { description: "Project not found." }
|
|
5755
5762
|
}
|
|
5756
5763
|
},
|
|
5764
|
+
{
|
|
5765
|
+
method: "get",
|
|
5766
|
+
path: "/api/v1/projects/{name}/ga/ai-referral-history",
|
|
5767
|
+
summary: "Get AI referral sessions per day grouped by source",
|
|
5768
|
+
tags: ["ga4"],
|
|
5769
|
+
parameters: [nameParameter],
|
|
5770
|
+
responses: {
|
|
5771
|
+
200: { description: "AI referral history returned." },
|
|
5772
|
+
400: { description: "GA4 is not connected." },
|
|
5773
|
+
404: { description: "Project not found." }
|
|
5774
|
+
}
|
|
5775
|
+
},
|
|
5757
5776
|
{
|
|
5758
5777
|
method: "get",
|
|
5759
5778
|
path: "/api/v1/projects/{name}/ga/coverage",
|
|
@@ -6263,6 +6282,7 @@ var GSC_MAX_ROWS_PER_REQUEST = 25e3;
|
|
|
6263
6282
|
var GSC_DATA_LAG_DAYS = 3;
|
|
6264
6283
|
var INDEXING_API_BASE = "https://indexing.googleapis.com/v3";
|
|
6265
6284
|
var INDEXING_API_DAILY_LIMIT = 200;
|
|
6285
|
+
var GOOGLE_REQUEST_TIMEOUT_MS = 3e4;
|
|
6266
6286
|
|
|
6267
6287
|
// ../integration-google/src/types.ts
|
|
6268
6288
|
var GoogleAuthError = class extends Error {
|
|
@@ -6303,7 +6323,8 @@ async function exchangeCode(clientId, clientSecret, code, redirectUri) {
|
|
|
6303
6323
|
code,
|
|
6304
6324
|
redirect_uri: redirectUri,
|
|
6305
6325
|
grant_type: "authorization_code"
|
|
6306
|
-
})
|
|
6326
|
+
}),
|
|
6327
|
+
signal: AbortSignal.timeout(GOOGLE_REQUEST_TIMEOUT_MS)
|
|
6307
6328
|
});
|
|
6308
6329
|
if (!res.ok) {
|
|
6309
6330
|
const body = await res.text();
|
|
@@ -6320,7 +6341,8 @@ async function refreshAccessToken(clientId, clientSecret, currentRefreshToken) {
|
|
|
6320
6341
|
client_secret: clientSecret,
|
|
6321
6342
|
refresh_token: currentRefreshToken,
|
|
6322
6343
|
grant_type: "refresh_token"
|
|
6323
|
-
})
|
|
6344
|
+
}),
|
|
6345
|
+
signal: AbortSignal.timeout(GOOGLE_REQUEST_TIMEOUT_MS)
|
|
6324
6346
|
});
|
|
6325
6347
|
if (!res.ok) {
|
|
6326
6348
|
const body = await res.text();
|
|
@@ -6344,7 +6366,8 @@ async function gscFetch(accessToken, url, opts) {
|
|
|
6344
6366
|
const res = await fetch(url, {
|
|
6345
6367
|
method,
|
|
6346
6368
|
headers,
|
|
6347
|
-
body: opts?.body != null ? JSON.stringify(opts.body) : void 0
|
|
6369
|
+
body: opts?.body != null ? JSON.stringify(opts.body) : void 0,
|
|
6370
|
+
signal: AbortSignal.timeout(GOOGLE_REQUEST_TIMEOUT_MS)
|
|
6348
6371
|
});
|
|
6349
6372
|
if (res.status === 401) {
|
|
6350
6373
|
const body = await res.text().catch(() => "");
|
|
@@ -6446,6 +6469,7 @@ var GA4_SCOPE = "https://www.googleapis.com/auth/analytics.readonly";
|
|
|
6446
6469
|
var GOOGLE_TOKEN_URL2 = "https://oauth2.googleapis.com/token";
|
|
6447
6470
|
var GA4_DEFAULT_SYNC_DAYS = 30;
|
|
6448
6471
|
var GA4_MAX_SYNC_DAYS = 90;
|
|
6472
|
+
var GA4_REQUEST_TIMEOUT_MS = 3e4;
|
|
6449
6473
|
|
|
6450
6474
|
// ../integration-google-analytics/src/types.ts
|
|
6451
6475
|
var GA4ApiError = class extends Error {
|
|
@@ -6491,7 +6515,8 @@ async function getAccessToken(clientEmail, privateKey) {
|
|
|
6491
6515
|
body: new URLSearchParams({
|
|
6492
6516
|
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
6493
6517
|
assertion: jwt
|
|
6494
|
-
})
|
|
6518
|
+
}),
|
|
6519
|
+
signal: AbortSignal.timeout(GA4_REQUEST_TIMEOUT_MS)
|
|
6495
6520
|
});
|
|
6496
6521
|
if (!res.ok) {
|
|
6497
6522
|
const body = await res.text().catch(() => "");
|
|
@@ -6509,7 +6534,8 @@ async function runReport(accessToken, propertyId, request) {
|
|
|
6509
6534
|
"Authorization": `Bearer ${accessToken}`,
|
|
6510
6535
|
"Content-Type": "application/json"
|
|
6511
6536
|
},
|
|
6512
|
-
body: JSON.stringify(request)
|
|
6537
|
+
body: JSON.stringify(request),
|
|
6538
|
+
signal: AbortSignal.timeout(GA4_REQUEST_TIMEOUT_MS)
|
|
6513
6539
|
});
|
|
6514
6540
|
if (res.status === 401 || res.status === 403) {
|
|
6515
6541
|
const body = await res.text().catch(() => "");
|
|
@@ -6549,7 +6575,8 @@ async function batchRunReports(accessToken, propertyId, requests) {
|
|
|
6549
6575
|
"Authorization": `Bearer ${accessToken}`,
|
|
6550
6576
|
"Content-Type": "application/json"
|
|
6551
6577
|
},
|
|
6552
|
-
body: JSON.stringify({ requests })
|
|
6578
|
+
body: JSON.stringify({ requests }),
|
|
6579
|
+
signal: AbortSignal.timeout(GA4_REQUEST_TIMEOUT_MS)
|
|
6553
6580
|
});
|
|
6554
6581
|
if (res.status === 401 || res.status === 403) {
|
|
6555
6582
|
const body = await res.text().catch(() => "");
|
|
@@ -7488,6 +7515,7 @@ import { eq as eq14, and as and3, desc as desc5 } from "drizzle-orm";
|
|
|
7488
7515
|
var BING_WMT_API_BASE = "https://ssl.bing.com/webmaster/api.svc/json";
|
|
7489
7516
|
var BING_SUBMIT_URL_BATCH_LIMIT = 500;
|
|
7490
7517
|
var BING_SUBMIT_URL_DAILY_LIMIT = 1e4;
|
|
7518
|
+
var BING_REQUEST_TIMEOUT_MS = 3e4;
|
|
7491
7519
|
|
|
7492
7520
|
// ../integration-bing/src/types.ts
|
|
7493
7521
|
var BingApiError = class extends Error {
|
|
@@ -7515,7 +7543,8 @@ async function bingFetch(apiKey, endpoint, opts) {
|
|
|
7515
7543
|
const res = await fetch(url, {
|
|
7516
7544
|
method,
|
|
7517
7545
|
headers,
|
|
7518
|
-
body: opts?.body != null ? JSON.stringify(opts.body) : void 0
|
|
7546
|
+
body: opts?.body != null ? JSON.stringify(opts.body) : void 0,
|
|
7547
|
+
signal: AbortSignal.timeout(BING_REQUEST_TIMEOUT_MS)
|
|
7519
7548
|
});
|
|
7520
7549
|
if (res.status === 401 || res.status === 403) {
|
|
7521
7550
|
const body = await res.text().catch(() => "");
|
|
@@ -8463,6 +8492,18 @@ async function ga4Routes(app, opts) {
|
|
|
8463
8492
|
lastSyncedAt: latestSync?.syncedAt ?? null
|
|
8464
8493
|
};
|
|
8465
8494
|
});
|
|
8495
|
+
app.get("/projects/:name/ga/ai-referral-history", async (request, _reply) => {
|
|
8496
|
+
const project = resolveProject(app.db, request.params.name);
|
|
8497
|
+
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
|
8498
|
+
const rows = app.db.select({
|
|
8499
|
+
date: gaAiReferrals.date,
|
|
8500
|
+
source: gaAiReferrals.source,
|
|
8501
|
+
medium: gaAiReferrals.medium,
|
|
8502
|
+
sessions: gaAiReferrals.sessions,
|
|
8503
|
+
users: gaAiReferrals.users
|
|
8504
|
+
}).from(gaAiReferrals).where(eq16(gaAiReferrals.projectId, project.id)).orderBy(gaAiReferrals.date).all();
|
|
8505
|
+
return rows;
|
|
8506
|
+
});
|
|
8466
8507
|
app.get("/projects/:name/ga/coverage", async (request, _reply) => {
|
|
8467
8508
|
const project = resolveProject(app.db, request.params.name);
|
|
8468
8509
|
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
|
@@ -8606,6 +8647,8 @@ function parseSchemaPageEntry(entry) {
|
|
|
8606
8647
|
|
|
8607
8648
|
// ../integration-wordpress/src/wordpress-client.ts
|
|
8608
8649
|
import crypto17 from "crypto";
|
|
8650
|
+
var WP_REQUEST_TIMEOUT_MS = 3e4;
|
|
8651
|
+
var WP_FETCH_TEXT_TIMEOUT_MS = 15e3;
|
|
8609
8652
|
var PAGE_FIELDS = "id,slug,status,link,modified,modified_gmt,title,content,meta";
|
|
8610
8653
|
var PAGE_LIST_FIELDS = "id,slug,status,link,modified,modified_gmt,title";
|
|
8611
8654
|
var VERIFY_PAGE_FIELDS = "id,status";
|
|
@@ -8662,7 +8705,8 @@ async function fetchJson(connection, siteUrl, path7, init) {
|
|
|
8662
8705
|
"Authorization": `Basic ${encodeBasicAuth(connection.username, connection.appPassword)}`,
|
|
8663
8706
|
...init?.body != null ? { "Content-Type": "application/json" } : {},
|
|
8664
8707
|
...init?.headers ?? {}
|
|
8665
|
-
}
|
|
8708
|
+
},
|
|
8709
|
+
signal: AbortSignal.timeout(WP_REQUEST_TIMEOUT_MS)
|
|
8666
8710
|
});
|
|
8667
8711
|
if (res.status === 401 || res.status === 403) {
|
|
8668
8712
|
const text2 = await res.text().catch(() => "");
|
|
@@ -8705,7 +8749,7 @@ async function fetchPageCollectionSummary(connection, siteUrl, options) {
|
|
|
8705
8749
|
}
|
|
8706
8750
|
async function fetchText(url) {
|
|
8707
8751
|
try {
|
|
8708
|
-
const res = await fetch(url);
|
|
8752
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(WP_FETCH_TEXT_TIMEOUT_MS) });
|
|
8709
8753
|
if (!res.ok) return null;
|
|
8710
8754
|
return await res.text();
|
|
8711
8755
|
} catch {
|
package/dist/cli.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
setGoogleAuthConfig,
|
|
27
27
|
showFirstRunNotice,
|
|
28
28
|
trackEvent
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-ETP5IOHC.js";
|
|
30
30
|
|
|
31
31
|
// src/cli.ts
|
|
32
32
|
import { pathToFileURL } from "url";
|
|
@@ -667,6 +667,9 @@ var ApiClient = class {
|
|
|
667
667
|
async gaCoverage(project) {
|
|
668
668
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/coverage`);
|
|
669
669
|
}
|
|
670
|
+
async gaAiReferralHistory(project) {
|
|
671
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/ai-referral-history`);
|
|
672
|
+
}
|
|
670
673
|
async wordpressConnect(project, body) {
|
|
671
674
|
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/connect`, body);
|
|
672
675
|
}
|
|
@@ -1516,6 +1519,29 @@ async function gaTraffic(project, opts) {
|
|
|
1516
1519
|
Last synced: ${result.lastSyncedAt}`);
|
|
1517
1520
|
}
|
|
1518
1521
|
}
|
|
1522
|
+
async function gaAiReferralHistory(project, format) {
|
|
1523
|
+
const client = getClient3();
|
|
1524
|
+
const result = await client.gaAiReferralHistory(project);
|
|
1525
|
+
if (format === "json") {
|
|
1526
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
if (result.length === 0) {
|
|
1530
|
+
console.log('No AI referral history. Run "canonry ga sync <project>" first.');
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
const dateWidth = 12;
|
|
1534
|
+
const sourceWidth = Math.min(30, Math.max(10, ...result.map((r) => r.source.length)));
|
|
1535
|
+
console.log(`GA4 AI Referral History for "${project}":
|
|
1536
|
+
`);
|
|
1537
|
+
console.log(` ${"DATE".padEnd(dateWidth)} ${"SOURCE".padEnd(sourceWidth)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
|
|
1538
|
+
console.log(` ${"\u2500".repeat(dateWidth)} ${"\u2500".repeat(sourceWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
|
|
1539
|
+
for (const row of result) {
|
|
1540
|
+
console.log(
|
|
1541
|
+
` ${row.date.padEnd(dateWidth)} ${row.source.padEnd(sourceWidth)} ${String(row.sessions).padEnd(10)}${String(row.users).padEnd(8)}`
|
|
1542
|
+
);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1519
1545
|
async function gaCoverage(project, format) {
|
|
1520
1546
|
const client = getClient3();
|
|
1521
1547
|
const result = await client.gaCoverage(project);
|
|
@@ -1620,14 +1646,22 @@ var GA_CLI_COMMANDS = [
|
|
|
1620
1646
|
await gaCoverage(project, input.format);
|
|
1621
1647
|
}
|
|
1622
1648
|
},
|
|
1649
|
+
{
|
|
1650
|
+
path: ["ga", "ai-referral-history"],
|
|
1651
|
+
usage: "canonry ga ai-referral-history <project> [--format json]",
|
|
1652
|
+
run: async (input) => {
|
|
1653
|
+
const project = requireProject(input, "ga.ai-referral-history", "canonry ga ai-referral-history <project> [--format json]");
|
|
1654
|
+
await gaAiReferralHistory(project, input.format);
|
|
1655
|
+
}
|
|
1656
|
+
},
|
|
1623
1657
|
{
|
|
1624
1658
|
path: ["ga"],
|
|
1625
|
-
usage: "canonry ga <connect|disconnect|status|sync|traffic|coverage> <project> [args]",
|
|
1659
|
+
usage: "canonry ga <connect|disconnect|status|sync|traffic|coverage|ai-referral-history> <project> [args]",
|
|
1626
1660
|
run: async (input) => {
|
|
1627
1661
|
unknownSubcommand(input.positionals[0], {
|
|
1628
1662
|
command: "ga",
|
|
1629
|
-
usage: "canonry ga <connect|disconnect|status|sync|traffic|coverage> <project> [args]",
|
|
1630
|
-
available: ["connect", "disconnect", "status", "sync", "traffic", "coverage"]
|
|
1663
|
+
usage: "canonry ga <connect|disconnect|status|sync|traffic|coverage|ai-referral-history> <project> [args]",
|
|
1664
|
+
available: ["connect", "disconnect", "status", "sync", "traffic", "coverage", "ai-referral-history"]
|
|
1631
1665
|
});
|
|
1632
1666
|
}
|
|
1633
1667
|
}
|
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.35.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-
|
|
58
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
59
59
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
60
60
|
"@ainyc/canonry-db": "0.0.0",
|
|
61
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
61
62
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
62
63
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
63
|
-
"@ainyc/canonry-
|
|
64
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
64
65
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
65
66
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
66
|
-
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
67
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
68
67
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
69
|
-
"@ainyc/canonry-provider-
|
|
68
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-provider-gemini": "0.0.0"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "tsup && tsx build-web.ts",
|