@ainyc/canonry 4.92.0 → 4.93.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/agent-workspace/skills/canonry/references/google-business-profile.md +6 -0
- package/assets/assets/{BacklinksPage-D3JpcWtH.js → BacklinksPage-nkgAbbjk.js} +1 -1
- package/assets/assets/{ChartPrimitives-DdwqEX5v.js → ChartPrimitives-kdfylr1f.js} +1 -1
- package/assets/assets/ProjectPage-BQYmq7FP.js +6 -0
- package/assets/assets/{RunRow-c_2jd8iz.js → RunRow-P-n5OkiY.js} +1 -1
- package/assets/assets/{RunsPage-D6eM_5tB.js → RunsPage-DfBb4WCS.js} +1 -1
- package/assets/assets/{SettingsPage-DaMc8nxK.js → SettingsPage-CRGuFgeK.js} +1 -1
- package/assets/assets/{TrafficPage-Dw16dcSc.js → TrafficPage-CMqP0AGZ.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-Dy9D80dz.js → TrafficSourceDetailPage-XRGzkKWk.js} +1 -1
- package/assets/assets/{arrow-left-D8UaBG9a.js → arrow-left-BCR55g4n.js} +1 -1
- package/assets/assets/{extract-error-message-CfxCIMNJ.js → extract-error-message-BG1AlucT.js} +1 -1
- package/assets/assets/{index-BA-lh2pG.js → index-BPjIZIDO.js} +73 -73
- package/assets/assets/{index-fLUYE9Z5.css → index-DiykVUPr.css} +1 -1
- package/assets/assets/{trash-2-j1tX1-Kq.js → trash-2-Cme1gNjU.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-QYC2N23P.js → chunk-ADTLQHJY.js} +69 -5
- package/dist/{chunk-VJPVFCZW.js → chunk-AUQNKEHV.js} +18 -0
- package/dist/{chunk-IFUHXONX.js → chunk-KBDQ5OE4.js} +166 -56
- package/dist/{chunk-HW4GVIQD.js → chunk-PK46TKGM.js} +33 -1
- package/dist/cli.js +36 -4
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-24HCX4SJ.js → intelligence-service-4ATCJITP.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
- package/assets/assets/ProjectPage-BPLf4U3A.js +0 -6
|
@@ -137,6 +137,7 @@ import {
|
|
|
137
137
|
ga4SyncResponseDtoSchema,
|
|
138
138
|
gateHarvestedSearchQueries,
|
|
139
139
|
gbpAccountListResponseSchema,
|
|
140
|
+
gbpAttributesListResponseSchema,
|
|
140
141
|
gbpDailyMetricListResponseSchema,
|
|
141
142
|
gbpDiscoverRequestSchema,
|
|
142
143
|
gbpKeywordImpressionListResponseSchema,
|
|
@@ -258,7 +259,7 @@ import {
|
|
|
258
259
|
wordpressSchemaDeployResultDtoSchema,
|
|
259
260
|
wordpressSchemaStatusResultDtoSchema,
|
|
260
261
|
wordpressStatusDtoSchema
|
|
261
|
-
} from "./chunk-
|
|
262
|
+
} from "./chunk-AUQNKEHV.js";
|
|
262
263
|
|
|
263
264
|
// src/intelligence-service.ts
|
|
264
265
|
import { eq as eq37, desc as desc18, asc as asc5, and as and27, ne as ne5, or as or5, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
|
|
@@ -302,6 +303,7 @@ __export(schema_exports, {
|
|
|
302
303
|
gaTrafficSnapshots: () => gaTrafficSnapshots,
|
|
303
304
|
gaTrafficSummaries: () => gaTrafficSummaries,
|
|
304
305
|
gaTrafficWindowSummaries: () => gaTrafficWindowSummaries,
|
|
306
|
+
gbpAttributesSnapshots: () => gbpAttributesSnapshots,
|
|
305
307
|
gbpDailyMetrics: () => gbpDailyMetrics,
|
|
306
308
|
gbpKeywordImpressions: () => gbpKeywordImpressions,
|
|
307
309
|
gbpKeywordMonthly: () => gbpKeywordMonthly,
|
|
@@ -1276,6 +1278,18 @@ var gbpPlaceDetails = sqliteTable("gbp_place_details", {
|
|
|
1276
1278
|
}, (table) => [
|
|
1277
1279
|
index("idx_gbp_place_details_loc").on(table.projectId, table.locationName, table.syncedAt)
|
|
1278
1280
|
]);
|
|
1281
|
+
var gbpAttributesSnapshots = sqliteTable("gbp_attributes_snapshots", {
|
|
1282
|
+
id: text("id").primaryKey(),
|
|
1283
|
+
projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
|
|
1284
|
+
locationName: text("location_name").notNull(),
|
|
1285
|
+
contentHash: text("content_hash").notNull(),
|
|
1286
|
+
attributes: text("attributes", { mode: "json" }).$type().notNull().default([]),
|
|
1287
|
+
attributeCount: integer("attribute_count").notNull().default(0),
|
|
1288
|
+
syncedAt: text("synced_at").notNull(),
|
|
1289
|
+
syncRunId: text("sync_run_id").references(() => runs.id, { onDelete: "set null" })
|
|
1290
|
+
}, (table) => [
|
|
1291
|
+
index("idx_gbp_attributes_loc").on(table.projectId, table.locationName, table.syncedAt)
|
|
1292
|
+
]);
|
|
1279
1293
|
var adsConnections = sqliteTable("ads_connections", {
|
|
1280
1294
|
id: text("id").primaryKey(),
|
|
1281
1295
|
projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
|
|
@@ -3166,6 +3180,23 @@ var MIGRATION_VERSIONS = [
|
|
|
3166
3180
|
}
|
|
3167
3181
|
}
|
|
3168
3182
|
}
|
|
3183
|
+
},
|
|
3184
|
+
{
|
|
3185
|
+
version: 82,
|
|
3186
|
+
name: "gbp-attributes-snapshots",
|
|
3187
|
+
statements: [
|
|
3188
|
+
`CREATE TABLE IF NOT EXISTS gbp_attributes_snapshots (
|
|
3189
|
+
id TEXT PRIMARY KEY,
|
|
3190
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
3191
|
+
location_name TEXT NOT NULL,
|
|
3192
|
+
content_hash TEXT NOT NULL,
|
|
3193
|
+
attributes TEXT NOT NULL DEFAULT '[]',
|
|
3194
|
+
attribute_count INTEGER NOT NULL DEFAULT 0,
|
|
3195
|
+
synced_at TEXT NOT NULL,
|
|
3196
|
+
sync_run_id TEXT REFERENCES runs(id) ON DELETE SET NULL
|
|
3197
|
+
)`,
|
|
3198
|
+
`CREATE INDEX IF NOT EXISTS idx_gbp_attributes_loc ON gbp_attributes_snapshots(project_id, location_name, synced_at)`
|
|
3199
|
+
]
|
|
3169
3200
|
}
|
|
3170
3201
|
];
|
|
3171
3202
|
function rebuildBacklinkTableWithSource(tx, table) {
|
|
@@ -13778,6 +13809,7 @@ var SCHEMA_TABLE = {
|
|
|
13778
13809
|
GbpLocationDto: gbpLocationDtoSchema,
|
|
13779
13810
|
GbpLocationListResponse: gbpLocationListResponseSchema,
|
|
13780
13811
|
GbpLodgingListResponse: gbpLodgingListResponseSchema,
|
|
13812
|
+
GbpAttributesListResponse: gbpAttributesListResponseSchema,
|
|
13781
13813
|
GbpPlaceActionListResponse: gbpPlaceActionListResponseSchema,
|
|
13782
13814
|
GbpPlaceDetailsListResponse: gbpPlaceDetailsListResponseSchema,
|
|
13783
13815
|
GbpSummaryDto: gbpSummaryDtoSchema,
|
|
@@ -15791,6 +15823,20 @@ var routeCatalog = [
|
|
|
15791
15823
|
404: errorResponse("Project not found.")
|
|
15792
15824
|
}
|
|
15793
15825
|
},
|
|
15826
|
+
{
|
|
15827
|
+
method: "get",
|
|
15828
|
+
path: "/api/v1/projects/{name}/gbp/attributes",
|
|
15829
|
+
summary: "List latest Google Business Profile owner-set attribute snapshots per location",
|
|
15830
|
+
tags: ["gbp"],
|
|
15831
|
+
parameters: [
|
|
15832
|
+
nameParameter,
|
|
15833
|
+
{ in: "query", name: "locationName", required: false, description: "Filter to one location resource name", schema: stringSchema }
|
|
15834
|
+
],
|
|
15835
|
+
responses: {
|
|
15836
|
+
200: jsonResponse("Attribute snapshots returned.", "GbpAttributesListResponse"),
|
|
15837
|
+
404: errorResponse("Project not found.")
|
|
15838
|
+
}
|
|
15839
|
+
},
|
|
15794
15840
|
{
|
|
15795
15841
|
method: "get",
|
|
15796
15842
|
path: "/api/v1/projects/{name}/gbp/places",
|
|
@@ -18529,7 +18575,7 @@ function formatNotification(row) {
|
|
|
18529
18575
|
}
|
|
18530
18576
|
|
|
18531
18577
|
// ../api-routes/src/google.ts
|
|
18532
|
-
import
|
|
18578
|
+
import crypto18 from "crypto";
|
|
18533
18579
|
import { eq as eq21, and as and14, desc as desc11, sql as sql8, inArray as inArray10 } from "drizzle-orm";
|
|
18534
18580
|
|
|
18535
18581
|
// ../api-routes/src/gbp-summary.ts
|
|
@@ -20082,6 +20128,46 @@ function stableStringify2(value) {
|
|
|
20082
20128
|
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify2(obj[k])}`).join(",")}}`;
|
|
20083
20129
|
}
|
|
20084
20130
|
|
|
20131
|
+
// ../integration-google-business-profile/src/attributes-client.ts
|
|
20132
|
+
import crypto17 from "crypto";
|
|
20133
|
+
async function getAttributes(accessToken, locationName, opts = {}) {
|
|
20134
|
+
const url = `${GBP_BUSINESS_INFO_BASE}/${locationName}/attributes`;
|
|
20135
|
+
let res;
|
|
20136
|
+
try {
|
|
20137
|
+
res = await gbpFetchGet(url, accessToken, opts);
|
|
20138
|
+
} catch (err) {
|
|
20139
|
+
if (err instanceof GbpApiError && err.status === 404) return [];
|
|
20140
|
+
throw err;
|
|
20141
|
+
}
|
|
20142
|
+
return (res.attributes ?? []).map(normalizeAttribute).filter((a) => a.name.length > 0);
|
|
20143
|
+
}
|
|
20144
|
+
function normalizeAttribute(raw) {
|
|
20145
|
+
const values = [];
|
|
20146
|
+
for (const v of raw.values ?? []) {
|
|
20147
|
+
if (typeof v === "boolean" || typeof v === "string") values.push(v);
|
|
20148
|
+
}
|
|
20149
|
+
for (const s of raw.repeatedEnumValue?.setValues ?? []) values.push(s);
|
|
20150
|
+
const uris = [];
|
|
20151
|
+
for (const u of raw.uriValues ?? []) {
|
|
20152
|
+
if (u?.uri) uris.push(u.uri);
|
|
20153
|
+
}
|
|
20154
|
+
return { name: raw.name ?? "", valueType: raw.valueType ?? "", values, uris };
|
|
20155
|
+
}
|
|
20156
|
+
function countAttributes(attrs) {
|
|
20157
|
+
return attrs.length;
|
|
20158
|
+
}
|
|
20159
|
+
function hashAttributes(attrs) {
|
|
20160
|
+
const sorted = [...attrs].sort((a, b) => a.name.localeCompare(b.name));
|
|
20161
|
+
return crypto17.createHash("sha256").update(stableStringify3(sorted)).digest("hex");
|
|
20162
|
+
}
|
|
20163
|
+
function stableStringify3(value) {
|
|
20164
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
20165
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify3).join(",")}]`;
|
|
20166
|
+
const obj = value;
|
|
20167
|
+
const keys = Object.keys(obj).sort();
|
|
20168
|
+
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify3(obj[k])}`).join(",")}}`;
|
|
20169
|
+
}
|
|
20170
|
+
|
|
20085
20171
|
// ../api-routes/src/google.ts
|
|
20086
20172
|
function scopesForConnectionType(type) {
|
|
20087
20173
|
switch (type) {
|
|
@@ -20094,7 +20180,7 @@ function scopesForConnectionType(type) {
|
|
|
20094
20180
|
}
|
|
20095
20181
|
}
|
|
20096
20182
|
function signState(payload, secret) {
|
|
20097
|
-
return
|
|
20183
|
+
return crypto18.createHmac("sha256", secret).update(payload).digest("hex");
|
|
20098
20184
|
}
|
|
20099
20185
|
function buildSignedState(data, secret) {
|
|
20100
20186
|
const payload = JSON.stringify(data);
|
|
@@ -20105,7 +20191,7 @@ function verifySignedState(encoded, secret) {
|
|
|
20105
20191
|
try {
|
|
20106
20192
|
const { payload, sig } = JSON.parse(Buffer.from(encoded, "base64url").toString());
|
|
20107
20193
|
const expected = signState(payload, secret);
|
|
20108
|
-
if (!
|
|
20194
|
+
if (!crypto18.timingSafeEqual(Buffer.from(sig, "hex"), Buffer.from(expected, "hex"))) return null;
|
|
20109
20195
|
return JSON.parse(payload);
|
|
20110
20196
|
} catch {
|
|
20111
20197
|
return null;
|
|
@@ -20441,7 +20527,7 @@ async function googleRoutes(app, opts) {
|
|
|
20441
20527
|
throw validationError('No GSC connection found for this domain. Run "canonry google connect" first.');
|
|
20442
20528
|
}
|
|
20443
20529
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20444
|
-
const runId =
|
|
20530
|
+
const runId = crypto18.randomUUID();
|
|
20445
20531
|
app.db.insert(runs).values({
|
|
20446
20532
|
id: runId,
|
|
20447
20533
|
projectId: project.id,
|
|
@@ -20539,7 +20625,7 @@ async function googleRoutes(app, opts) {
|
|
|
20539
20625
|
const mob = ir.mobileUsabilityResult;
|
|
20540
20626
|
const rich = ir.richResultsResult;
|
|
20541
20627
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20542
|
-
const id =
|
|
20628
|
+
const id = crypto18.randomUUID();
|
|
20543
20629
|
app.db.insert(gscUrlInspections).values({
|
|
20544
20630
|
id,
|
|
20545
20631
|
projectId: project.id,
|
|
@@ -20783,7 +20869,7 @@ async function googleRoutes(app, opts) {
|
|
|
20783
20869
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20784
20870
|
});
|
|
20785
20871
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20786
|
-
const runId =
|
|
20872
|
+
const runId = crypto18.randomUUID();
|
|
20787
20873
|
app.db.insert(runs).values({
|
|
20788
20874
|
id: runId,
|
|
20789
20875
|
projectId: project.id,
|
|
@@ -20809,7 +20895,7 @@ async function googleRoutes(app, opts) {
|
|
|
20809
20895
|
throw validationError("No GSC property configured for this connection");
|
|
20810
20896
|
}
|
|
20811
20897
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20812
|
-
const runId =
|
|
20898
|
+
const runId = crypto18.randomUUID();
|
|
20813
20899
|
app.db.insert(runs).values({
|
|
20814
20900
|
id: runId,
|
|
20815
20901
|
projectId: project.id,
|
|
@@ -21090,7 +21176,7 @@ async function googleRoutes(app, opts) {
|
|
|
21090
21176
|
}).where(eq21(gbpLocations.id, existing.id)).run();
|
|
21091
21177
|
} else {
|
|
21092
21178
|
tx.insert(gbpLocations).values({
|
|
21093
|
-
id:
|
|
21179
|
+
id: crypto18.randomUUID(),
|
|
21094
21180
|
projectId: project.id,
|
|
21095
21181
|
accountName,
|
|
21096
21182
|
locationName: remote.name,
|
|
@@ -21214,7 +21300,7 @@ async function googleRoutes(app, opts) {
|
|
|
21214
21300
|
throw validationError(parsed.error.issues[0]?.message ?? "Invalid sync request");
|
|
21215
21301
|
}
|
|
21216
21302
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21217
|
-
const runId =
|
|
21303
|
+
const runId = crypto18.randomUUID();
|
|
21218
21304
|
app.db.insert(runs).values({
|
|
21219
21305
|
id: runId,
|
|
21220
21306
|
projectId: project.id,
|
|
@@ -21291,6 +21377,23 @@ async function googleRoutes(app, opts) {
|
|
|
21291
21377
|
}));
|
|
21292
21378
|
return { lodging, total: lodging.length };
|
|
21293
21379
|
});
|
|
21380
|
+
app.get("/projects/:name/gbp/attributes", async (request) => {
|
|
21381
|
+
const project = resolveProject(app.db, request.params.name);
|
|
21382
|
+
const conditions = [eq21(gbpAttributesSnapshots.projectId, project.id)];
|
|
21383
|
+
if (request.query.locationName) conditions.push(eq21(gbpAttributesSnapshots.locationName, request.query.locationName));
|
|
21384
|
+
const rows = app.db.select().from(gbpAttributesSnapshots).where(and14(...conditions)).orderBy(desc11(gbpAttributesSnapshots.syncedAt)).all();
|
|
21385
|
+
const latestByLocation = /* @__PURE__ */ new Map();
|
|
21386
|
+
for (const row of rows) {
|
|
21387
|
+
if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
|
|
21388
|
+
}
|
|
21389
|
+
const attributes = [...latestByLocation.values()].map((r) => ({
|
|
21390
|
+
locationName: r.locationName,
|
|
21391
|
+
attributeCount: r.attributeCount,
|
|
21392
|
+
syncedAt: r.syncedAt,
|
|
21393
|
+
attributes: r.attributes
|
|
21394
|
+
}));
|
|
21395
|
+
return { attributes, total: attributes.length };
|
|
21396
|
+
});
|
|
21294
21397
|
app.get("/projects/:name/gbp/places", async (request) => {
|
|
21295
21398
|
const project = resolveProject(app.db, request.params.name);
|
|
21296
21399
|
const conditions = [eq21(gbpPlaceDetails.projectId, project.id)];
|
|
@@ -21360,7 +21463,7 @@ async function googleRoutes(app, opts) {
|
|
|
21360
21463
|
}
|
|
21361
21464
|
|
|
21362
21465
|
// ../api-routes/src/ads.ts
|
|
21363
|
-
import
|
|
21466
|
+
import crypto19 from "crypto";
|
|
21364
21467
|
import { eq as eq22, and as and15, asc as asc2, gte as gte3, lte as lte2, inArray as inArray11 } from "drizzle-orm";
|
|
21365
21468
|
function statusDto(row) {
|
|
21366
21469
|
if (!row) return { connected: false };
|
|
@@ -21423,7 +21526,7 @@ async function adsRoutes(app, opts) {
|
|
|
21423
21526
|
}).where(eq22(adsConnections.id, existingRow.id)).run();
|
|
21424
21527
|
} else {
|
|
21425
21528
|
tx.insert(adsConnections).values({
|
|
21426
|
-
id:
|
|
21529
|
+
id: crypto19.randomUUID(),
|
|
21427
21530
|
projectId: project.id,
|
|
21428
21531
|
adAccountId: account.id,
|
|
21429
21532
|
displayName: account.name,
|
|
@@ -21485,7 +21588,7 @@ async function adsRoutes(app, opts) {
|
|
|
21485
21588
|
const existing = { runId: inFlight.id, status: inFlight.status };
|
|
21486
21589
|
return existing;
|
|
21487
21590
|
}
|
|
21488
|
-
const runId =
|
|
21591
|
+
const runId = crypto19.randomUUID();
|
|
21489
21592
|
app.db.insert(runs).values({
|
|
21490
21593
|
id: runId,
|
|
21491
21594
|
projectId: project.id,
|
|
@@ -21620,7 +21723,7 @@ async function adsRoutes(app, opts) {
|
|
|
21620
21723
|
}
|
|
21621
21724
|
|
|
21622
21725
|
// ../api-routes/src/bing.ts
|
|
21623
|
-
import
|
|
21726
|
+
import crypto20 from "crypto";
|
|
21624
21727
|
import { eq as eq23, and as and16, desc as desc12 } from "drizzle-orm";
|
|
21625
21728
|
|
|
21626
21729
|
// ../integration-bing/src/constants.ts
|
|
@@ -22052,7 +22155,7 @@ async function bingRoutes(app, opts) {
|
|
|
22052
22155
|
const snapshotDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
22053
22156
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22054
22157
|
app.db.insert(bingCoverageSnapshots).values({
|
|
22055
|
-
id:
|
|
22158
|
+
id: crypto20.randomUUID(),
|
|
22056
22159
|
projectId: project.id,
|
|
22057
22160
|
syncRunId: snapshotRunId,
|
|
22058
22161
|
date: snapshotDate,
|
|
@@ -22123,7 +22226,7 @@ async function bingRoutes(app, opts) {
|
|
|
22123
22226
|
throw validationError("url is required");
|
|
22124
22227
|
}
|
|
22125
22228
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22126
|
-
const runId =
|
|
22229
|
+
const runId = crypto20.randomUUID();
|
|
22127
22230
|
app.db.insert(runs).values({
|
|
22128
22231
|
id: runId,
|
|
22129
22232
|
projectId: project.id,
|
|
@@ -22144,7 +22247,7 @@ async function bingRoutes(app, opts) {
|
|
|
22144
22247
|
discoveryDate: result.DiscoveryDate ?? null
|
|
22145
22248
|
});
|
|
22146
22249
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22147
|
-
const id =
|
|
22250
|
+
const id = crypto20.randomUUID();
|
|
22148
22251
|
const httpCode = result.HttpStatus ?? result.HttpCode ?? null;
|
|
22149
22252
|
const lastCrawledDate = parseBingDate(result.LastCrawledDate);
|
|
22150
22253
|
const inIndexDate = parseBingDate(result.InIndexDate);
|
|
@@ -22214,7 +22317,7 @@ async function bingRoutes(app, opts) {
|
|
|
22214
22317
|
throw validationError('No Bing site configured. Run "canonry bing set-site <project> <url>" first.');
|
|
22215
22318
|
}
|
|
22216
22319
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22217
|
-
const runId =
|
|
22320
|
+
const runId = crypto20.randomUUID();
|
|
22218
22321
|
app.db.insert(runs).values({
|
|
22219
22322
|
id: runId,
|
|
22220
22323
|
projectId: project.id,
|
|
@@ -22498,7 +22601,7 @@ async function cdpRoutes(app, opts) {
|
|
|
22498
22601
|
}
|
|
22499
22602
|
|
|
22500
22603
|
// ../api-routes/src/ga.ts
|
|
22501
|
-
import
|
|
22604
|
+
import crypto21 from "crypto";
|
|
22502
22605
|
import { eq as eq25, desc as desc13, and as and18, sql as sql9 } from "drizzle-orm";
|
|
22503
22606
|
function gaLog(level, action, ctx) {
|
|
22504
22607
|
const entry = { ts: (/* @__PURE__ */ new Date()).toISOString(), level, module: "GA4Routes", action, ...ctx };
|
|
@@ -22754,7 +22857,7 @@ async function ga4Routes(app, opts) {
|
|
|
22754
22857
|
const syncAi = !only || only === "ai";
|
|
22755
22858
|
const syncSocial = !only || only === "social";
|
|
22756
22859
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22757
|
-
const runId =
|
|
22860
|
+
const runId = crypto21.randomUUID();
|
|
22758
22861
|
app.db.insert(runs).values({
|
|
22759
22862
|
id: runId,
|
|
22760
22863
|
projectId: project.id,
|
|
@@ -22802,7 +22905,7 @@ async function ga4Routes(app, opts) {
|
|
|
22802
22905
|
).run();
|
|
22803
22906
|
for (const row of rows) {
|
|
22804
22907
|
tx.insert(gaTrafficSnapshots).values({
|
|
22805
|
-
id:
|
|
22908
|
+
id: crypto21.randomUUID(),
|
|
22806
22909
|
projectId: project.id,
|
|
22807
22910
|
date: row.date,
|
|
22808
22911
|
landingPage: row.landingPage,
|
|
@@ -22826,7 +22929,7 @@ async function ga4Routes(app, opts) {
|
|
|
22826
22929
|
).run();
|
|
22827
22930
|
for (const row of aiReferrals) {
|
|
22828
22931
|
tx.insert(gaAiReferrals).values({
|
|
22829
|
-
id:
|
|
22932
|
+
id: crypto21.randomUUID(),
|
|
22830
22933
|
projectId: project.id,
|
|
22831
22934
|
date: row.date,
|
|
22832
22935
|
source: row.source,
|
|
@@ -22852,7 +22955,7 @@ async function ga4Routes(app, opts) {
|
|
|
22852
22955
|
).run();
|
|
22853
22956
|
for (const row of socialReferrals) {
|
|
22854
22957
|
tx.insert(gaSocialReferrals).values({
|
|
22855
|
-
id:
|
|
22958
|
+
id: crypto21.randomUUID(),
|
|
22856
22959
|
projectId: project.id,
|
|
22857
22960
|
date: row.date,
|
|
22858
22961
|
source: row.source,
|
|
@@ -22868,7 +22971,7 @@ async function ga4Routes(app, opts) {
|
|
|
22868
22971
|
if (syncSummary) {
|
|
22869
22972
|
tx.delete(gaTrafficSummaries).where(eq25(gaTrafficSummaries.projectId, project.id)).run();
|
|
22870
22973
|
tx.insert(gaTrafficSummaries).values({
|
|
22871
|
-
id:
|
|
22974
|
+
id: crypto21.randomUUID(),
|
|
22872
22975
|
projectId: project.id,
|
|
22873
22976
|
periodStart: summary.periodStart,
|
|
22874
22977
|
periodEnd: summary.periodEnd,
|
|
@@ -22881,7 +22984,7 @@ async function ga4Routes(app, opts) {
|
|
|
22881
22984
|
tx.delete(gaTrafficWindowSummaries).where(eq25(gaTrafficWindowSummaries.projectId, project.id)).run();
|
|
22882
22985
|
for (const ws of windowSummaries) {
|
|
22883
22986
|
tx.insert(gaTrafficWindowSummaries).values({
|
|
22884
|
-
id:
|
|
22987
|
+
id: crypto21.randomUUID(),
|
|
22885
22988
|
projectId: project.id,
|
|
22886
22989
|
windowKey: ws.windowKey,
|
|
22887
22990
|
periodStart: ws.periodStart,
|
|
@@ -23452,7 +23555,7 @@ function parseSchemaPageEntry(entry) {
|
|
|
23452
23555
|
}
|
|
23453
23556
|
|
|
23454
23557
|
// ../integration-wordpress/src/wordpress-client.ts
|
|
23455
|
-
import
|
|
23558
|
+
import crypto22 from "crypto";
|
|
23456
23559
|
function validateUsername(username) {
|
|
23457
23560
|
if (!username || typeof username !== "string" || username.trim().length === 0) {
|
|
23458
23561
|
throw new WordpressApiError("AUTH_INVALID", "Username is required and must be a non-empty string", 400);
|
|
@@ -23665,7 +23768,7 @@ function buildSnippet(content) {
|
|
|
23665
23768
|
return `${text2.slice(0, 157)}...`;
|
|
23666
23769
|
}
|
|
23667
23770
|
function contentHash(content) {
|
|
23668
|
-
return
|
|
23771
|
+
return crypto22.createHash("sha256").update(content).digest("hex");
|
|
23669
23772
|
}
|
|
23670
23773
|
function buildAmbiguousSlugMessage(slug, pages) {
|
|
23671
23774
|
const candidates = pages.map((page) => {
|
|
@@ -24965,7 +25068,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
24965
25068
|
}
|
|
24966
25069
|
|
|
24967
25070
|
// ../api-routes/src/backlinks.ts
|
|
24968
|
-
import
|
|
25071
|
+
import crypto23 from "crypto";
|
|
24969
25072
|
import { and as and20, asc as asc3, desc as desc14, eq as eq26, sql as sql10 } from "drizzle-orm";
|
|
24970
25073
|
|
|
24971
25074
|
// ../integration-commoncrawl/src/constants.ts
|
|
@@ -25603,7 +25706,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
25603
25706
|
const refreshed = app.db.select().from(ccReleaseSyncs).where(eq26(ccReleaseSyncs.id, existing.id)).get();
|
|
25604
25707
|
return reply.status(200).send(mapSyncRow(refreshed));
|
|
25605
25708
|
}
|
|
25606
|
-
const id =
|
|
25709
|
+
const id = crypto23.randomUUID();
|
|
25607
25710
|
app.db.insert(ccReleaseSyncs).values({
|
|
25608
25711
|
id,
|
|
25609
25712
|
release,
|
|
@@ -25660,7 +25763,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
25660
25763
|
throw validationError("Invalid release id");
|
|
25661
25764
|
}
|
|
25662
25765
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25663
|
-
const runId =
|
|
25766
|
+
const runId = crypto23.randomUUID();
|
|
25664
25767
|
app.db.insert(runs).values({
|
|
25665
25768
|
id: runId,
|
|
25666
25769
|
projectId: project.id,
|
|
@@ -25762,7 +25865,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
25762
25865
|
);
|
|
25763
25866
|
}
|
|
25764
25867
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25765
|
-
const runId =
|
|
25868
|
+
const runId = crypto23.randomUUID();
|
|
25766
25869
|
app.db.insert(runs).values({
|
|
25767
25870
|
id: runId,
|
|
25768
25871
|
projectId: project.id,
|
|
@@ -25779,12 +25882,12 @@ async function backlinksRoutes(app, opts) {
|
|
|
25779
25882
|
}
|
|
25780
25883
|
|
|
25781
25884
|
// ../api-routes/src/traffic.ts
|
|
25782
|
-
import
|
|
25885
|
+
import crypto25 from "crypto";
|
|
25783
25886
|
import { Agent as UndiciAgent } from "undici";
|
|
25784
25887
|
import { and as and21, desc as desc15, eq as eq27, gte as gte4, lte as lte3, sql as sql11 } from "drizzle-orm";
|
|
25785
25888
|
|
|
25786
25889
|
// ../integration-cloud-run/src/auth.ts
|
|
25787
|
-
import
|
|
25890
|
+
import crypto24 from "crypto";
|
|
25788
25891
|
var GOOGLE_TOKEN_URL3 = "https://oauth2.googleapis.com/token";
|
|
25789
25892
|
var CLOUD_LOGGING_READ_SCOPE = "https://www.googleapis.com/auth/logging.read";
|
|
25790
25893
|
var TOKEN_REQUEST_TIMEOUT_MS = 3e4;
|
|
@@ -25815,7 +25918,7 @@ function createServiceAccountJwt2(clientEmail, privateKey, scope) {
|
|
|
25815
25918
|
const headerB64 = encode(header);
|
|
25816
25919
|
const payloadB64 = encode(payload);
|
|
25817
25920
|
const signingInput = `${headerB64}.${payloadB64}`;
|
|
25818
|
-
const sign =
|
|
25921
|
+
const sign = crypto24.createSign("RSA-SHA256");
|
|
25819
25922
|
sign.update(signingInput);
|
|
25820
25923
|
const signature = sign.sign(privateKey, "base64url");
|
|
25821
25924
|
return `${signingInput}.${signature}`;
|
|
@@ -29723,7 +29826,7 @@ async function runBackfillTask(options) {
|
|
|
29723
29826
|
}
|
|
29724
29827
|
})();
|
|
29725
29828
|
tx.insert(rawEventSamples).values({
|
|
29726
|
-
id:
|
|
29829
|
+
id: crypto25.randomUUID(),
|
|
29727
29830
|
projectId: project.id,
|
|
29728
29831
|
sourceId: sourceRow.id,
|
|
29729
29832
|
ts: sample.observedAt,
|
|
@@ -29849,7 +29952,7 @@ async function trafficRoutes(app, opts) {
|
|
|
29849
29952
|
}).where(eq27(trafficSources.id, activeSource.id)).run();
|
|
29850
29953
|
sourceRow = app.db.select().from(trafficSources).where(eq27(trafficSources.id, activeSource.id)).get();
|
|
29851
29954
|
} else {
|
|
29852
|
-
const newId =
|
|
29955
|
+
const newId = crypto25.randomUUID();
|
|
29853
29956
|
app.db.insert(trafficSources).values({
|
|
29854
29957
|
id: newId,
|
|
29855
29958
|
projectId: project.id,
|
|
@@ -29930,7 +30033,7 @@ async function trafficRoutes(app, opts) {
|
|
|
29930
30033
|
}).where(eq27(trafficSources.id, activeSource.id)).run();
|
|
29931
30034
|
sourceRow = app.db.select().from(trafficSources).where(eq27(trafficSources.id, activeSource.id)).get();
|
|
29932
30035
|
} else {
|
|
29933
|
-
const newId =
|
|
30036
|
+
const newId = crypto25.randomUUID();
|
|
29934
30037
|
app.db.insert(trafficSources).values({
|
|
29935
30038
|
id: newId,
|
|
29936
30039
|
projectId: project.id,
|
|
@@ -30014,7 +30117,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30014
30117
|
}).where(eq27(trafficSources.id, activeSource.id)).run();
|
|
30015
30118
|
row = tx.select().from(trafficSources).where(eq27(trafficSources.id, activeSource.id)).get();
|
|
30016
30119
|
} else {
|
|
30017
|
-
const newId =
|
|
30120
|
+
const newId = crypto25.randomUUID();
|
|
30018
30121
|
tx.insert(trafficSources).values({
|
|
30019
30122
|
id: newId,
|
|
30020
30123
|
projectId: project.id,
|
|
@@ -30048,7 +30151,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30048
30151
|
let created = false;
|
|
30049
30152
|
if (!existingSchedule) {
|
|
30050
30153
|
tx.insert(schedules).values({
|
|
30051
|
-
id:
|
|
30154
|
+
id: crypto25.randomUUID(),
|
|
30052
30155
|
projectId: project.id,
|
|
30053
30156
|
kind: SchedulableRunKinds["traffic-sync"],
|
|
30054
30157
|
cronExpr: DEFAULT_TRAFFIC_SYNC_CRON,
|
|
@@ -30103,7 +30206,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30103
30206
|
const windowEnd = /* @__PURE__ */ new Date();
|
|
30104
30207
|
const startedAt = windowEnd.toISOString();
|
|
30105
30208
|
const syncStartedAtMs = windowEnd.getTime();
|
|
30106
|
-
const runId =
|
|
30209
|
+
const runId = crypto25.randomUUID();
|
|
30107
30210
|
app.db.insert(runs).values({
|
|
30108
30211
|
id: runId,
|
|
30109
30212
|
projectId: project.id,
|
|
@@ -30486,7 +30589,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30486
30589
|
}
|
|
30487
30590
|
})();
|
|
30488
30591
|
tx.insert(rawEventSamples).values({
|
|
30489
|
-
id:
|
|
30592
|
+
id: crypto25.randomUUID(),
|
|
30490
30593
|
projectId: project.id,
|
|
30491
30594
|
sourceId: sourceRow.id,
|
|
30492
30595
|
ts: sample.observedAt,
|
|
@@ -30724,7 +30827,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30724
30827
|
};
|
|
30725
30828
|
}
|
|
30726
30829
|
const startedAt = windowEnd.toISOString();
|
|
30727
|
-
const runId =
|
|
30830
|
+
const runId = crypto25.randomUUID();
|
|
30728
30831
|
app.db.insert(runs).values({
|
|
30729
30832
|
id: runId,
|
|
30730
30833
|
projectId: project.id,
|
|
@@ -31025,7 +31128,7 @@ async function trafficRoutes(app, opts) {
|
|
|
31025
31128
|
}
|
|
31026
31129
|
|
|
31027
31130
|
// ../api-routes/src/doctor/checks/agent.ts
|
|
31028
|
-
import
|
|
31131
|
+
import crypto26 from "crypto";
|
|
31029
31132
|
import fs6 from "fs";
|
|
31030
31133
|
import path7 from "path";
|
|
31031
31134
|
var REQUIRED_SKILLS = ["canonry", "aero"];
|
|
@@ -31178,7 +31281,7 @@ function isInstalled(dir) {
|
|
|
31178
31281
|
}
|
|
31179
31282
|
function hashInstalledFile(filePath) {
|
|
31180
31283
|
try {
|
|
31181
|
-
return
|
|
31284
|
+
return crypto26.createHash("sha256").update(fs6.readFileSync(filePath)).digest("hex");
|
|
31182
31285
|
} catch {
|
|
31183
31286
|
return void 0;
|
|
31184
31287
|
}
|
|
@@ -33080,7 +33183,7 @@ async function doctorRoutes(app, opts) {
|
|
|
33080
33183
|
}
|
|
33081
33184
|
|
|
33082
33185
|
// ../api-routes/src/discovery/routes.ts
|
|
33083
|
-
import
|
|
33186
|
+
import crypto27 from "crypto";
|
|
33084
33187
|
import { and as and25, desc as desc16, eq as eq34, gte as gte6, inArray as inArray12 } from "drizzle-orm";
|
|
33085
33188
|
var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
|
|
33086
33189
|
async function discoveryRoutes(app, opts) {
|
|
@@ -33126,8 +33229,8 @@ async function discoveryRoutes(app, opts) {
|
|
|
33126
33229
|
if (existing && existing.runId) {
|
|
33127
33230
|
return { reused: true, sessionId: existing.id, runId: existing.runId };
|
|
33128
33231
|
}
|
|
33129
|
-
const sessionId =
|
|
33130
|
-
const runId =
|
|
33232
|
+
const sessionId = crypto27.randomUUID();
|
|
33233
|
+
const runId = crypto27.randomUUID();
|
|
33131
33234
|
tx.insert(discoverySessions).values({
|
|
33132
33235
|
id: sessionId,
|
|
33133
33236
|
projectId: project.id,
|
|
@@ -33375,7 +33478,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
33375
33478
|
app.db.transaction((tx) => {
|
|
33376
33479
|
for (const query of promotedQueries) {
|
|
33377
33480
|
tx.insert(queries).values({
|
|
33378
|
-
id:
|
|
33481
|
+
id: crypto27.randomUUID(),
|
|
33379
33482
|
projectId: project.id,
|
|
33380
33483
|
query,
|
|
33381
33484
|
provenance,
|
|
@@ -33384,7 +33487,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
33384
33487
|
}
|
|
33385
33488
|
for (const domain of promotedCompetitors) {
|
|
33386
33489
|
tx.insert(competitors).values({
|
|
33387
|
-
id:
|
|
33490
|
+
id: crypto27.randomUUID(),
|
|
33388
33491
|
projectId: project.id,
|
|
33389
33492
|
domain,
|
|
33390
33493
|
provenance,
|
|
@@ -33462,7 +33565,7 @@ function selectEligibleCompetitors(competitorMap, competitorTypes) {
|
|
|
33462
33565
|
}
|
|
33463
33566
|
|
|
33464
33567
|
// ../api-routes/src/discovery/orchestrate.ts
|
|
33465
|
-
import
|
|
33568
|
+
import crypto28 from "crypto";
|
|
33466
33569
|
import { eq as eq35 } from "drizzle-orm";
|
|
33467
33570
|
var DEFAULT_MAX_PROBES = 100;
|
|
33468
33571
|
var ABSOLUTE_MAX_PROBES = 500;
|
|
@@ -33556,7 +33659,7 @@ async function executeDiscovery(opts) {
|
|
|
33556
33659
|
probeRows.push({ citedDomains: probe.citedDomains, bucket });
|
|
33557
33660
|
buckets[bucket]++;
|
|
33558
33661
|
opts.db.insert(discoveryProbes).values({
|
|
33559
|
-
id:
|
|
33662
|
+
id: crypto28.randomUUID(),
|
|
33560
33663
|
sessionId: opts.sessionId,
|
|
33561
33664
|
projectId: opts.project.id,
|
|
33562
33665
|
query,
|
|
@@ -33601,7 +33704,7 @@ function upsertDomainClassifications(db, projectId, sessionId, competitorMap) {
|
|
|
33601
33704
|
const domain = normalizeDomain(entry.domain);
|
|
33602
33705
|
if (!domain) continue;
|
|
33603
33706
|
db.insert(domainClassifications).values({
|
|
33604
|
-
id:
|
|
33707
|
+
id: crypto28.randomUUID(),
|
|
33605
33708
|
projectId,
|
|
33606
33709
|
domain,
|
|
33607
33710
|
competitorType: entry.competitorType,
|
|
@@ -33641,7 +33744,7 @@ function dedupeStrings(input) {
|
|
|
33641
33744
|
}
|
|
33642
33745
|
|
|
33643
33746
|
// ../api-routes/src/technical-aeo.ts
|
|
33644
|
-
import
|
|
33747
|
+
import crypto29 from "crypto";
|
|
33645
33748
|
import { and as and26, asc as asc4, count, desc as desc17, eq as eq36, inArray as inArray13 } from "drizzle-orm";
|
|
33646
33749
|
var SURFACEABLE_STATUSES = [RunStatuses.completed, RunStatuses.partial];
|
|
33647
33750
|
function emptyScore(projectName) {
|
|
@@ -33768,7 +33871,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
33768
33871
|
return { runId: existing.id, status: existing.status };
|
|
33769
33872
|
}
|
|
33770
33873
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
33771
|
-
const runId =
|
|
33874
|
+
const runId = crypto29.randomUUID();
|
|
33772
33875
|
app.db.insert(runs).values({
|
|
33773
33876
|
id: runId,
|
|
33774
33877
|
projectId: project.id,
|
|
@@ -34119,7 +34222,7 @@ function buildTrafficSourceValidators(opts) {
|
|
|
34119
34222
|
}
|
|
34120
34223
|
|
|
34121
34224
|
// src/intelligence-service.ts
|
|
34122
|
-
import
|
|
34225
|
+
import crypto30 from "crypto";
|
|
34123
34226
|
|
|
34124
34227
|
// src/logger.ts
|
|
34125
34228
|
var IS_TTY = process.stdout.isTTY === true;
|
|
@@ -34784,7 +34887,7 @@ var IntelligenceService = class {
|
|
|
34784
34887
|
}).run();
|
|
34785
34888
|
}
|
|
34786
34889
|
tx.insert(healthSnapshots).values({
|
|
34787
|
-
id:
|
|
34890
|
+
id: crypto30.randomUUID(),
|
|
34788
34891
|
projectId,
|
|
34789
34892
|
runId,
|
|
34790
34893
|
overallCitedRate: String(result.health.overallCitedRate),
|
|
@@ -34979,6 +35082,7 @@ export {
|
|
|
34979
35082
|
gbpPlaceActions,
|
|
34980
35083
|
gbpLodgingSnapshots,
|
|
34981
35084
|
gbpPlaceDetails,
|
|
35085
|
+
gbpAttributesSnapshots,
|
|
34982
35086
|
adsConnections,
|
|
34983
35087
|
adsCampaigns,
|
|
34984
35088
|
adsAdGroups,
|
|
@@ -35008,12 +35112,18 @@ export {
|
|
|
35008
35112
|
fetchSearchAnalytics,
|
|
35009
35113
|
inspectUrl,
|
|
35010
35114
|
GBP_DAILY_METRICS,
|
|
35115
|
+
listLocations,
|
|
35116
|
+
formatStorefrontAddress,
|
|
35117
|
+
buildLocationProfileFields,
|
|
35011
35118
|
fetchDailyMetrics,
|
|
35012
35119
|
listMonthlyKeywords,
|
|
35013
35120
|
listPlaceActionLinks,
|
|
35014
35121
|
getLodging,
|
|
35015
35122
|
countPopulatedGroups,
|
|
35016
35123
|
hashLodging,
|
|
35124
|
+
getAttributes,
|
|
35125
|
+
countAttributes,
|
|
35126
|
+
hashAttributes,
|
|
35017
35127
|
getUrlInfo,
|
|
35018
35128
|
getCrawlIssues,
|
|
35019
35129
|
getLinkCounts,
|