@ainyc/canonry 4.91.1 → 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/aero/references/regression-playbook.md +1 -0
- package/assets/agent-workspace/skills/canonry/references/google-business-profile.md +7 -0
- package/assets/assets/{BacklinksPage-DHC1po5Q.js → BacklinksPage-nkgAbbjk.js} +1 -1
- package/assets/assets/{ChartPrimitives-Cu2xEVle.js → ChartPrimitives-kdfylr1f.js} +1 -1
- package/assets/assets/ProjectPage-BQYmq7FP.js +6 -0
- package/assets/assets/{RunRow-BPqbBlXl.js → RunRow-P-n5OkiY.js} +1 -1
- package/assets/assets/{RunsPage-BJx3_Nel.js → RunsPage-DfBb4WCS.js} +1 -1
- package/assets/assets/{SettingsPage-CXTIHdsv.js → SettingsPage-CRGuFgeK.js} +1 -1
- package/assets/assets/{TrafficPage-iibCIBqX.js → TrafficPage-CMqP0AGZ.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-WU30E_59.js → TrafficSourceDetailPage-XRGzkKWk.js} +1 -1
- package/assets/assets/{arrow-left-Ds_f14R8.js → arrow-left-BCR55g4n.js} +1 -1
- package/assets/assets/{extract-error-message-D250utEX.js → extract-error-message-BG1AlucT.js} +1 -1
- package/assets/assets/{index-qiysJOcG.js → index-BPjIZIDO.js} +73 -73
- package/assets/assets/{index-fLUYE9Z5.css → index-DiykVUPr.css} +1 -1
- package/assets/assets/{trash-2-CcVWAeec.js → trash-2-Cme1gNjU.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-KFJPJBW3.js → chunk-ADTLQHJY.js} +69 -5
- package/dist/{chunk-WMBOHP7E.js → chunk-AUQNKEHV.js} +20 -0
- package/dist/{chunk-4KQYRCVC.js → chunk-KBDQ5OE4.js} +181 -56
- package/dist/{chunk-6RVUSM4Y.js → chunk-PK46TKGM.js} +33 -1
- package/dist/cli.js +36 -4
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-QB6HQRWU.js → intelligence-service-4ATCJITP.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +10 -10
- package/assets/assets/ProjectPage-DXYcaMVO.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) {
|
|
@@ -5269,6 +5300,18 @@ function analyzeGbp(signals) {
|
|
|
5269
5300
|
});
|
|
5270
5301
|
}
|
|
5271
5302
|
}
|
|
5303
|
+
if (loc.descriptionMissing) {
|
|
5304
|
+
drafts.push({
|
|
5305
|
+
...base,
|
|
5306
|
+
type: "gbp-description-missing",
|
|
5307
|
+
severity: "low",
|
|
5308
|
+
title: `${loc.displayName}: no business description set`,
|
|
5309
|
+
recommendation: {
|
|
5310
|
+
action: "Add a business description (up to 750 characters) in the Google Business Profile.",
|
|
5311
|
+
reason: "The owner description is the cheapest owner-controlled prose an AI answer engine can lift to describe the business, and it seeds the entity attributes (specialties, service area, differentiators) models draw on. It reads straight from the GBP API, so an empty one is a real, easily-closed gap."
|
|
5312
|
+
}
|
|
5313
|
+
});
|
|
5314
|
+
}
|
|
5272
5315
|
if (loc.placeActionCount > 0 && !loc.hasDirectMerchantCta) {
|
|
5273
5316
|
drafts.push({
|
|
5274
5317
|
...base,
|
|
@@ -13766,6 +13809,7 @@ var SCHEMA_TABLE = {
|
|
|
13766
13809
|
GbpLocationDto: gbpLocationDtoSchema,
|
|
13767
13810
|
GbpLocationListResponse: gbpLocationListResponseSchema,
|
|
13768
13811
|
GbpLodgingListResponse: gbpLodgingListResponseSchema,
|
|
13812
|
+
GbpAttributesListResponse: gbpAttributesListResponseSchema,
|
|
13769
13813
|
GbpPlaceActionListResponse: gbpPlaceActionListResponseSchema,
|
|
13770
13814
|
GbpPlaceDetailsListResponse: gbpPlaceDetailsListResponseSchema,
|
|
13771
13815
|
GbpSummaryDto: gbpSummaryDtoSchema,
|
|
@@ -15779,6 +15823,20 @@ var routeCatalog = [
|
|
|
15779
15823
|
404: errorResponse("Project not found.")
|
|
15780
15824
|
}
|
|
15781
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
|
+
},
|
|
15782
15840
|
{
|
|
15783
15841
|
method: "get",
|
|
15784
15842
|
path: "/api/v1/projects/{name}/gbp/places",
|
|
@@ -18517,7 +18575,7 @@ function formatNotification(row) {
|
|
|
18517
18575
|
}
|
|
18518
18576
|
|
|
18519
18577
|
// ../api-routes/src/google.ts
|
|
18520
|
-
import
|
|
18578
|
+
import crypto18 from "crypto";
|
|
18521
18579
|
import { eq as eq21, and as and14, desc as desc11, sql as sql8, inArray as inArray10 } from "drizzle-orm";
|
|
18522
18580
|
|
|
18523
18581
|
// ../api-routes/src/gbp-summary.ts
|
|
@@ -20070,6 +20128,46 @@ function stableStringify2(value) {
|
|
|
20070
20128
|
return `{${keys.map((k) => `${JSON.stringify(k)}:${stableStringify2(obj[k])}`).join(",")}}`;
|
|
20071
20129
|
}
|
|
20072
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
|
+
|
|
20073
20171
|
// ../api-routes/src/google.ts
|
|
20074
20172
|
function scopesForConnectionType(type) {
|
|
20075
20173
|
switch (type) {
|
|
@@ -20082,7 +20180,7 @@ function scopesForConnectionType(type) {
|
|
|
20082
20180
|
}
|
|
20083
20181
|
}
|
|
20084
20182
|
function signState(payload, secret) {
|
|
20085
|
-
return
|
|
20183
|
+
return crypto18.createHmac("sha256", secret).update(payload).digest("hex");
|
|
20086
20184
|
}
|
|
20087
20185
|
function buildSignedState(data, secret) {
|
|
20088
20186
|
const payload = JSON.stringify(data);
|
|
@@ -20093,7 +20191,7 @@ function verifySignedState(encoded, secret) {
|
|
|
20093
20191
|
try {
|
|
20094
20192
|
const { payload, sig } = JSON.parse(Buffer.from(encoded, "base64url").toString());
|
|
20095
20193
|
const expected = signState(payload, secret);
|
|
20096
|
-
if (!
|
|
20194
|
+
if (!crypto18.timingSafeEqual(Buffer.from(sig, "hex"), Buffer.from(expected, "hex"))) return null;
|
|
20097
20195
|
return JSON.parse(payload);
|
|
20098
20196
|
} catch {
|
|
20099
20197
|
return null;
|
|
@@ -20429,7 +20527,7 @@ async function googleRoutes(app, opts) {
|
|
|
20429
20527
|
throw validationError('No GSC connection found for this domain. Run "canonry google connect" first.');
|
|
20430
20528
|
}
|
|
20431
20529
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20432
|
-
const runId =
|
|
20530
|
+
const runId = crypto18.randomUUID();
|
|
20433
20531
|
app.db.insert(runs).values({
|
|
20434
20532
|
id: runId,
|
|
20435
20533
|
projectId: project.id,
|
|
@@ -20527,7 +20625,7 @@ async function googleRoutes(app, opts) {
|
|
|
20527
20625
|
const mob = ir.mobileUsabilityResult;
|
|
20528
20626
|
const rich = ir.richResultsResult;
|
|
20529
20627
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20530
|
-
const id =
|
|
20628
|
+
const id = crypto18.randomUUID();
|
|
20531
20629
|
app.db.insert(gscUrlInspections).values({
|
|
20532
20630
|
id,
|
|
20533
20631
|
projectId: project.id,
|
|
@@ -20771,7 +20869,7 @@ async function googleRoutes(app, opts) {
|
|
|
20771
20869
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
20772
20870
|
});
|
|
20773
20871
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20774
|
-
const runId =
|
|
20872
|
+
const runId = crypto18.randomUUID();
|
|
20775
20873
|
app.db.insert(runs).values({
|
|
20776
20874
|
id: runId,
|
|
20777
20875
|
projectId: project.id,
|
|
@@ -20797,7 +20895,7 @@ async function googleRoutes(app, opts) {
|
|
|
20797
20895
|
throw validationError("No GSC property configured for this connection");
|
|
20798
20896
|
}
|
|
20799
20897
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20800
|
-
const runId =
|
|
20898
|
+
const runId = crypto18.randomUUID();
|
|
20801
20899
|
app.db.insert(runs).values({
|
|
20802
20900
|
id: runId,
|
|
20803
20901
|
projectId: project.id,
|
|
@@ -21078,7 +21176,7 @@ async function googleRoutes(app, opts) {
|
|
|
21078
21176
|
}).where(eq21(gbpLocations.id, existing.id)).run();
|
|
21079
21177
|
} else {
|
|
21080
21178
|
tx.insert(gbpLocations).values({
|
|
21081
|
-
id:
|
|
21179
|
+
id: crypto18.randomUUID(),
|
|
21082
21180
|
projectId: project.id,
|
|
21083
21181
|
accountName,
|
|
21084
21182
|
locationName: remote.name,
|
|
@@ -21202,7 +21300,7 @@ async function googleRoutes(app, opts) {
|
|
|
21202
21300
|
throw validationError(parsed.error.issues[0]?.message ?? "Invalid sync request");
|
|
21203
21301
|
}
|
|
21204
21302
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21205
|
-
const runId =
|
|
21303
|
+
const runId = crypto18.randomUUID();
|
|
21206
21304
|
app.db.insert(runs).values({
|
|
21207
21305
|
id: runId,
|
|
21208
21306
|
projectId: project.id,
|
|
@@ -21279,6 +21377,23 @@ async function googleRoutes(app, opts) {
|
|
|
21279
21377
|
}));
|
|
21280
21378
|
return { lodging, total: lodging.length };
|
|
21281
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
|
+
});
|
|
21282
21397
|
app.get("/projects/:name/gbp/places", async (request) => {
|
|
21283
21398
|
const project = resolveProject(app.db, request.params.name);
|
|
21284
21399
|
const conditions = [eq21(gbpPlaceDetails.projectId, project.id)];
|
|
@@ -21348,7 +21463,7 @@ async function googleRoutes(app, opts) {
|
|
|
21348
21463
|
}
|
|
21349
21464
|
|
|
21350
21465
|
// ../api-routes/src/ads.ts
|
|
21351
|
-
import
|
|
21466
|
+
import crypto19 from "crypto";
|
|
21352
21467
|
import { eq as eq22, and as and15, asc as asc2, gte as gte3, lte as lte2, inArray as inArray11 } from "drizzle-orm";
|
|
21353
21468
|
function statusDto(row) {
|
|
21354
21469
|
if (!row) return { connected: false };
|
|
@@ -21411,7 +21526,7 @@ async function adsRoutes(app, opts) {
|
|
|
21411
21526
|
}).where(eq22(adsConnections.id, existingRow.id)).run();
|
|
21412
21527
|
} else {
|
|
21413
21528
|
tx.insert(adsConnections).values({
|
|
21414
|
-
id:
|
|
21529
|
+
id: crypto19.randomUUID(),
|
|
21415
21530
|
projectId: project.id,
|
|
21416
21531
|
adAccountId: account.id,
|
|
21417
21532
|
displayName: account.name,
|
|
@@ -21473,7 +21588,7 @@ async function adsRoutes(app, opts) {
|
|
|
21473
21588
|
const existing = { runId: inFlight.id, status: inFlight.status };
|
|
21474
21589
|
return existing;
|
|
21475
21590
|
}
|
|
21476
|
-
const runId =
|
|
21591
|
+
const runId = crypto19.randomUUID();
|
|
21477
21592
|
app.db.insert(runs).values({
|
|
21478
21593
|
id: runId,
|
|
21479
21594
|
projectId: project.id,
|
|
@@ -21608,7 +21723,7 @@ async function adsRoutes(app, opts) {
|
|
|
21608
21723
|
}
|
|
21609
21724
|
|
|
21610
21725
|
// ../api-routes/src/bing.ts
|
|
21611
|
-
import
|
|
21726
|
+
import crypto20 from "crypto";
|
|
21612
21727
|
import { eq as eq23, and as and16, desc as desc12 } from "drizzle-orm";
|
|
21613
21728
|
|
|
21614
21729
|
// ../integration-bing/src/constants.ts
|
|
@@ -22040,7 +22155,7 @@ async function bingRoutes(app, opts) {
|
|
|
22040
22155
|
const snapshotDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
22041
22156
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22042
22157
|
app.db.insert(bingCoverageSnapshots).values({
|
|
22043
|
-
id:
|
|
22158
|
+
id: crypto20.randomUUID(),
|
|
22044
22159
|
projectId: project.id,
|
|
22045
22160
|
syncRunId: snapshotRunId,
|
|
22046
22161
|
date: snapshotDate,
|
|
@@ -22111,7 +22226,7 @@ async function bingRoutes(app, opts) {
|
|
|
22111
22226
|
throw validationError("url is required");
|
|
22112
22227
|
}
|
|
22113
22228
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22114
|
-
const runId =
|
|
22229
|
+
const runId = crypto20.randomUUID();
|
|
22115
22230
|
app.db.insert(runs).values({
|
|
22116
22231
|
id: runId,
|
|
22117
22232
|
projectId: project.id,
|
|
@@ -22132,7 +22247,7 @@ async function bingRoutes(app, opts) {
|
|
|
22132
22247
|
discoveryDate: result.DiscoveryDate ?? null
|
|
22133
22248
|
});
|
|
22134
22249
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22135
|
-
const id =
|
|
22250
|
+
const id = crypto20.randomUUID();
|
|
22136
22251
|
const httpCode = result.HttpStatus ?? result.HttpCode ?? null;
|
|
22137
22252
|
const lastCrawledDate = parseBingDate(result.LastCrawledDate);
|
|
22138
22253
|
const inIndexDate = parseBingDate(result.InIndexDate);
|
|
@@ -22202,7 +22317,7 @@ async function bingRoutes(app, opts) {
|
|
|
22202
22317
|
throw validationError('No Bing site configured. Run "canonry bing set-site <project> <url>" first.');
|
|
22203
22318
|
}
|
|
22204
22319
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
22205
|
-
const runId =
|
|
22320
|
+
const runId = crypto20.randomUUID();
|
|
22206
22321
|
app.db.insert(runs).values({
|
|
22207
22322
|
id: runId,
|
|
22208
22323
|
projectId: project.id,
|
|
@@ -22486,7 +22601,7 @@ async function cdpRoutes(app, opts) {
|
|
|
22486
22601
|
}
|
|
22487
22602
|
|
|
22488
22603
|
// ../api-routes/src/ga.ts
|
|
22489
|
-
import
|
|
22604
|
+
import crypto21 from "crypto";
|
|
22490
22605
|
import { eq as eq25, desc as desc13, and as and18, sql as sql9 } from "drizzle-orm";
|
|
22491
22606
|
function gaLog(level, action, ctx) {
|
|
22492
22607
|
const entry = { ts: (/* @__PURE__ */ new Date()).toISOString(), level, module: "GA4Routes", action, ...ctx };
|
|
@@ -22742,7 +22857,7 @@ async function ga4Routes(app, opts) {
|
|
|
22742
22857
|
const syncAi = !only || only === "ai";
|
|
22743
22858
|
const syncSocial = !only || only === "social";
|
|
22744
22859
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
22745
|
-
const runId =
|
|
22860
|
+
const runId = crypto21.randomUUID();
|
|
22746
22861
|
app.db.insert(runs).values({
|
|
22747
22862
|
id: runId,
|
|
22748
22863
|
projectId: project.id,
|
|
@@ -22790,7 +22905,7 @@ async function ga4Routes(app, opts) {
|
|
|
22790
22905
|
).run();
|
|
22791
22906
|
for (const row of rows) {
|
|
22792
22907
|
tx.insert(gaTrafficSnapshots).values({
|
|
22793
|
-
id:
|
|
22908
|
+
id: crypto21.randomUUID(),
|
|
22794
22909
|
projectId: project.id,
|
|
22795
22910
|
date: row.date,
|
|
22796
22911
|
landingPage: row.landingPage,
|
|
@@ -22814,7 +22929,7 @@ async function ga4Routes(app, opts) {
|
|
|
22814
22929
|
).run();
|
|
22815
22930
|
for (const row of aiReferrals) {
|
|
22816
22931
|
tx.insert(gaAiReferrals).values({
|
|
22817
|
-
id:
|
|
22932
|
+
id: crypto21.randomUUID(),
|
|
22818
22933
|
projectId: project.id,
|
|
22819
22934
|
date: row.date,
|
|
22820
22935
|
source: row.source,
|
|
@@ -22840,7 +22955,7 @@ async function ga4Routes(app, opts) {
|
|
|
22840
22955
|
).run();
|
|
22841
22956
|
for (const row of socialReferrals) {
|
|
22842
22957
|
tx.insert(gaSocialReferrals).values({
|
|
22843
|
-
id:
|
|
22958
|
+
id: crypto21.randomUUID(),
|
|
22844
22959
|
projectId: project.id,
|
|
22845
22960
|
date: row.date,
|
|
22846
22961
|
source: row.source,
|
|
@@ -22856,7 +22971,7 @@ async function ga4Routes(app, opts) {
|
|
|
22856
22971
|
if (syncSummary) {
|
|
22857
22972
|
tx.delete(gaTrafficSummaries).where(eq25(gaTrafficSummaries.projectId, project.id)).run();
|
|
22858
22973
|
tx.insert(gaTrafficSummaries).values({
|
|
22859
|
-
id:
|
|
22974
|
+
id: crypto21.randomUUID(),
|
|
22860
22975
|
projectId: project.id,
|
|
22861
22976
|
periodStart: summary.periodStart,
|
|
22862
22977
|
periodEnd: summary.periodEnd,
|
|
@@ -22869,7 +22984,7 @@ async function ga4Routes(app, opts) {
|
|
|
22869
22984
|
tx.delete(gaTrafficWindowSummaries).where(eq25(gaTrafficWindowSummaries.projectId, project.id)).run();
|
|
22870
22985
|
for (const ws of windowSummaries) {
|
|
22871
22986
|
tx.insert(gaTrafficWindowSummaries).values({
|
|
22872
|
-
id:
|
|
22987
|
+
id: crypto21.randomUUID(),
|
|
22873
22988
|
projectId: project.id,
|
|
22874
22989
|
windowKey: ws.windowKey,
|
|
22875
22990
|
periodStart: ws.periodStart,
|
|
@@ -23440,7 +23555,7 @@ function parseSchemaPageEntry(entry) {
|
|
|
23440
23555
|
}
|
|
23441
23556
|
|
|
23442
23557
|
// ../integration-wordpress/src/wordpress-client.ts
|
|
23443
|
-
import
|
|
23558
|
+
import crypto22 from "crypto";
|
|
23444
23559
|
function validateUsername(username) {
|
|
23445
23560
|
if (!username || typeof username !== "string" || username.trim().length === 0) {
|
|
23446
23561
|
throw new WordpressApiError("AUTH_INVALID", "Username is required and must be a non-empty string", 400);
|
|
@@ -23653,7 +23768,7 @@ function buildSnippet(content) {
|
|
|
23653
23768
|
return `${text2.slice(0, 157)}...`;
|
|
23654
23769
|
}
|
|
23655
23770
|
function contentHash(content) {
|
|
23656
|
-
return
|
|
23771
|
+
return crypto22.createHash("sha256").update(content).digest("hex");
|
|
23657
23772
|
}
|
|
23658
23773
|
function buildAmbiguousSlugMessage(slug, pages) {
|
|
23659
23774
|
const candidates = pages.map((page) => {
|
|
@@ -24953,7 +25068,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
24953
25068
|
}
|
|
24954
25069
|
|
|
24955
25070
|
// ../api-routes/src/backlinks.ts
|
|
24956
|
-
import
|
|
25071
|
+
import crypto23 from "crypto";
|
|
24957
25072
|
import { and as and20, asc as asc3, desc as desc14, eq as eq26, sql as sql10 } from "drizzle-orm";
|
|
24958
25073
|
|
|
24959
25074
|
// ../integration-commoncrawl/src/constants.ts
|
|
@@ -25591,7 +25706,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
25591
25706
|
const refreshed = app.db.select().from(ccReleaseSyncs).where(eq26(ccReleaseSyncs.id, existing.id)).get();
|
|
25592
25707
|
return reply.status(200).send(mapSyncRow(refreshed));
|
|
25593
25708
|
}
|
|
25594
|
-
const id =
|
|
25709
|
+
const id = crypto23.randomUUID();
|
|
25595
25710
|
app.db.insert(ccReleaseSyncs).values({
|
|
25596
25711
|
id,
|
|
25597
25712
|
release,
|
|
@@ -25648,7 +25763,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
25648
25763
|
throw validationError("Invalid release id");
|
|
25649
25764
|
}
|
|
25650
25765
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25651
|
-
const runId =
|
|
25766
|
+
const runId = crypto23.randomUUID();
|
|
25652
25767
|
app.db.insert(runs).values({
|
|
25653
25768
|
id: runId,
|
|
25654
25769
|
projectId: project.id,
|
|
@@ -25750,7 +25865,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
25750
25865
|
);
|
|
25751
25866
|
}
|
|
25752
25867
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25753
|
-
const runId =
|
|
25868
|
+
const runId = crypto23.randomUUID();
|
|
25754
25869
|
app.db.insert(runs).values({
|
|
25755
25870
|
id: runId,
|
|
25756
25871
|
projectId: project.id,
|
|
@@ -25767,12 +25882,12 @@ async function backlinksRoutes(app, opts) {
|
|
|
25767
25882
|
}
|
|
25768
25883
|
|
|
25769
25884
|
// ../api-routes/src/traffic.ts
|
|
25770
|
-
import
|
|
25885
|
+
import crypto25 from "crypto";
|
|
25771
25886
|
import { Agent as UndiciAgent } from "undici";
|
|
25772
25887
|
import { and as and21, desc as desc15, eq as eq27, gte as gte4, lte as lte3, sql as sql11 } from "drizzle-orm";
|
|
25773
25888
|
|
|
25774
25889
|
// ../integration-cloud-run/src/auth.ts
|
|
25775
|
-
import
|
|
25890
|
+
import crypto24 from "crypto";
|
|
25776
25891
|
var GOOGLE_TOKEN_URL3 = "https://oauth2.googleapis.com/token";
|
|
25777
25892
|
var CLOUD_LOGGING_READ_SCOPE = "https://www.googleapis.com/auth/logging.read";
|
|
25778
25893
|
var TOKEN_REQUEST_TIMEOUT_MS = 3e4;
|
|
@@ -25803,7 +25918,7 @@ function createServiceAccountJwt2(clientEmail, privateKey, scope) {
|
|
|
25803
25918
|
const headerB64 = encode(header);
|
|
25804
25919
|
const payloadB64 = encode(payload);
|
|
25805
25920
|
const signingInput = `${headerB64}.${payloadB64}`;
|
|
25806
|
-
const sign =
|
|
25921
|
+
const sign = crypto24.createSign("RSA-SHA256");
|
|
25807
25922
|
sign.update(signingInput);
|
|
25808
25923
|
const signature = sign.sign(privateKey, "base64url");
|
|
25809
25924
|
return `${signingInput}.${signature}`;
|
|
@@ -29711,7 +29826,7 @@ async function runBackfillTask(options) {
|
|
|
29711
29826
|
}
|
|
29712
29827
|
})();
|
|
29713
29828
|
tx.insert(rawEventSamples).values({
|
|
29714
|
-
id:
|
|
29829
|
+
id: crypto25.randomUUID(),
|
|
29715
29830
|
projectId: project.id,
|
|
29716
29831
|
sourceId: sourceRow.id,
|
|
29717
29832
|
ts: sample.observedAt,
|
|
@@ -29837,7 +29952,7 @@ async function trafficRoutes(app, opts) {
|
|
|
29837
29952
|
}).where(eq27(trafficSources.id, activeSource.id)).run();
|
|
29838
29953
|
sourceRow = app.db.select().from(trafficSources).where(eq27(trafficSources.id, activeSource.id)).get();
|
|
29839
29954
|
} else {
|
|
29840
|
-
const newId =
|
|
29955
|
+
const newId = crypto25.randomUUID();
|
|
29841
29956
|
app.db.insert(trafficSources).values({
|
|
29842
29957
|
id: newId,
|
|
29843
29958
|
projectId: project.id,
|
|
@@ -29918,7 +30033,7 @@ async function trafficRoutes(app, opts) {
|
|
|
29918
30033
|
}).where(eq27(trafficSources.id, activeSource.id)).run();
|
|
29919
30034
|
sourceRow = app.db.select().from(trafficSources).where(eq27(trafficSources.id, activeSource.id)).get();
|
|
29920
30035
|
} else {
|
|
29921
|
-
const newId =
|
|
30036
|
+
const newId = crypto25.randomUUID();
|
|
29922
30037
|
app.db.insert(trafficSources).values({
|
|
29923
30038
|
id: newId,
|
|
29924
30039
|
projectId: project.id,
|
|
@@ -30002,7 +30117,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30002
30117
|
}).where(eq27(trafficSources.id, activeSource.id)).run();
|
|
30003
30118
|
row = tx.select().from(trafficSources).where(eq27(trafficSources.id, activeSource.id)).get();
|
|
30004
30119
|
} else {
|
|
30005
|
-
const newId =
|
|
30120
|
+
const newId = crypto25.randomUUID();
|
|
30006
30121
|
tx.insert(trafficSources).values({
|
|
30007
30122
|
id: newId,
|
|
30008
30123
|
projectId: project.id,
|
|
@@ -30036,7 +30151,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30036
30151
|
let created = false;
|
|
30037
30152
|
if (!existingSchedule) {
|
|
30038
30153
|
tx.insert(schedules).values({
|
|
30039
|
-
id:
|
|
30154
|
+
id: crypto25.randomUUID(),
|
|
30040
30155
|
projectId: project.id,
|
|
30041
30156
|
kind: SchedulableRunKinds["traffic-sync"],
|
|
30042
30157
|
cronExpr: DEFAULT_TRAFFIC_SYNC_CRON,
|
|
@@ -30091,7 +30206,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30091
30206
|
const windowEnd = /* @__PURE__ */ new Date();
|
|
30092
30207
|
const startedAt = windowEnd.toISOString();
|
|
30093
30208
|
const syncStartedAtMs = windowEnd.getTime();
|
|
30094
|
-
const runId =
|
|
30209
|
+
const runId = crypto25.randomUUID();
|
|
30095
30210
|
app.db.insert(runs).values({
|
|
30096
30211
|
id: runId,
|
|
30097
30212
|
projectId: project.id,
|
|
@@ -30474,7 +30589,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30474
30589
|
}
|
|
30475
30590
|
})();
|
|
30476
30591
|
tx.insert(rawEventSamples).values({
|
|
30477
|
-
id:
|
|
30592
|
+
id: crypto25.randomUUID(),
|
|
30478
30593
|
projectId: project.id,
|
|
30479
30594
|
sourceId: sourceRow.id,
|
|
30480
30595
|
ts: sample.observedAt,
|
|
@@ -30712,7 +30827,7 @@ async function trafficRoutes(app, opts) {
|
|
|
30712
30827
|
};
|
|
30713
30828
|
}
|
|
30714
30829
|
const startedAt = windowEnd.toISOString();
|
|
30715
|
-
const runId =
|
|
30830
|
+
const runId = crypto25.randomUUID();
|
|
30716
30831
|
app.db.insert(runs).values({
|
|
30717
30832
|
id: runId,
|
|
30718
30833
|
projectId: project.id,
|
|
@@ -31013,7 +31128,7 @@ async function trafficRoutes(app, opts) {
|
|
|
31013
31128
|
}
|
|
31014
31129
|
|
|
31015
31130
|
// ../api-routes/src/doctor/checks/agent.ts
|
|
31016
|
-
import
|
|
31131
|
+
import crypto26 from "crypto";
|
|
31017
31132
|
import fs6 from "fs";
|
|
31018
31133
|
import path7 from "path";
|
|
31019
31134
|
var REQUIRED_SKILLS = ["canonry", "aero"];
|
|
@@ -31166,7 +31281,7 @@ function isInstalled(dir) {
|
|
|
31166
31281
|
}
|
|
31167
31282
|
function hashInstalledFile(filePath) {
|
|
31168
31283
|
try {
|
|
31169
|
-
return
|
|
31284
|
+
return crypto26.createHash("sha256").update(fs6.readFileSync(filePath)).digest("hex");
|
|
31170
31285
|
} catch {
|
|
31171
31286
|
return void 0;
|
|
31172
31287
|
}
|
|
@@ -33068,7 +33183,7 @@ async function doctorRoutes(app, opts) {
|
|
|
33068
33183
|
}
|
|
33069
33184
|
|
|
33070
33185
|
// ../api-routes/src/discovery/routes.ts
|
|
33071
|
-
import
|
|
33186
|
+
import crypto27 from "crypto";
|
|
33072
33187
|
import { and as and25, desc as desc16, eq as eq34, gte as gte6, inArray as inArray12 } from "drizzle-orm";
|
|
33073
33188
|
var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
|
|
33074
33189
|
async function discoveryRoutes(app, opts) {
|
|
@@ -33114,8 +33229,8 @@ async function discoveryRoutes(app, opts) {
|
|
|
33114
33229
|
if (existing && existing.runId) {
|
|
33115
33230
|
return { reused: true, sessionId: existing.id, runId: existing.runId };
|
|
33116
33231
|
}
|
|
33117
|
-
const sessionId =
|
|
33118
|
-
const runId =
|
|
33232
|
+
const sessionId = crypto27.randomUUID();
|
|
33233
|
+
const runId = crypto27.randomUUID();
|
|
33119
33234
|
tx.insert(discoverySessions).values({
|
|
33120
33235
|
id: sessionId,
|
|
33121
33236
|
projectId: project.id,
|
|
@@ -33363,7 +33478,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
33363
33478
|
app.db.transaction((tx) => {
|
|
33364
33479
|
for (const query of promotedQueries) {
|
|
33365
33480
|
tx.insert(queries).values({
|
|
33366
|
-
id:
|
|
33481
|
+
id: crypto27.randomUUID(),
|
|
33367
33482
|
projectId: project.id,
|
|
33368
33483
|
query,
|
|
33369
33484
|
provenance,
|
|
@@ -33372,7 +33487,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
33372
33487
|
}
|
|
33373
33488
|
for (const domain of promotedCompetitors) {
|
|
33374
33489
|
tx.insert(competitors).values({
|
|
33375
|
-
id:
|
|
33490
|
+
id: crypto27.randomUUID(),
|
|
33376
33491
|
projectId: project.id,
|
|
33377
33492
|
domain,
|
|
33378
33493
|
provenance,
|
|
@@ -33450,7 +33565,7 @@ function selectEligibleCompetitors(competitorMap, competitorTypes) {
|
|
|
33450
33565
|
}
|
|
33451
33566
|
|
|
33452
33567
|
// ../api-routes/src/discovery/orchestrate.ts
|
|
33453
|
-
import
|
|
33568
|
+
import crypto28 from "crypto";
|
|
33454
33569
|
import { eq as eq35 } from "drizzle-orm";
|
|
33455
33570
|
var DEFAULT_MAX_PROBES = 100;
|
|
33456
33571
|
var ABSOLUTE_MAX_PROBES = 500;
|
|
@@ -33544,7 +33659,7 @@ async function executeDiscovery(opts) {
|
|
|
33544
33659
|
probeRows.push({ citedDomains: probe.citedDomains, bucket });
|
|
33545
33660
|
buckets[bucket]++;
|
|
33546
33661
|
opts.db.insert(discoveryProbes).values({
|
|
33547
|
-
id:
|
|
33662
|
+
id: crypto28.randomUUID(),
|
|
33548
33663
|
sessionId: opts.sessionId,
|
|
33549
33664
|
projectId: opts.project.id,
|
|
33550
33665
|
query,
|
|
@@ -33589,7 +33704,7 @@ function upsertDomainClassifications(db, projectId, sessionId, competitorMap) {
|
|
|
33589
33704
|
const domain = normalizeDomain(entry.domain);
|
|
33590
33705
|
if (!domain) continue;
|
|
33591
33706
|
db.insert(domainClassifications).values({
|
|
33592
|
-
id:
|
|
33707
|
+
id: crypto28.randomUUID(),
|
|
33593
33708
|
projectId,
|
|
33594
33709
|
domain,
|
|
33595
33710
|
competitorType: entry.competitorType,
|
|
@@ -33629,7 +33744,7 @@ function dedupeStrings(input) {
|
|
|
33629
33744
|
}
|
|
33630
33745
|
|
|
33631
33746
|
// ../api-routes/src/technical-aeo.ts
|
|
33632
|
-
import
|
|
33747
|
+
import crypto29 from "crypto";
|
|
33633
33748
|
import { and as and26, asc as asc4, count, desc as desc17, eq as eq36, inArray as inArray13 } from "drizzle-orm";
|
|
33634
33749
|
var SURFACEABLE_STATUSES = [RunStatuses.completed, RunStatuses.partial];
|
|
33635
33750
|
function emptyScore(projectName) {
|
|
@@ -33756,7 +33871,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
33756
33871
|
return { runId: existing.id, status: existing.status };
|
|
33757
33872
|
}
|
|
33758
33873
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
33759
|
-
const runId =
|
|
33874
|
+
const runId = crypto29.randomUUID();
|
|
33760
33875
|
app.db.insert(runs).values({
|
|
33761
33876
|
id: runId,
|
|
33762
33877
|
projectId: project.id,
|
|
@@ -34107,7 +34222,7 @@ function buildTrafficSourceValidators(opts) {
|
|
|
34107
34222
|
}
|
|
34108
34223
|
|
|
34109
34224
|
// src/intelligence-service.ts
|
|
34110
|
-
import
|
|
34225
|
+
import crypto30 from "crypto";
|
|
34111
34226
|
|
|
34112
34227
|
// src/logger.ts
|
|
34113
34228
|
var IS_TTY = process.stdout.isTTY === true;
|
|
@@ -34471,6 +34586,8 @@ var IntelligenceService = class {
|
|
|
34471
34586
|
const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and27(eq37(gbpDailyMetrics.projectId, projectId), eq37(gbpDailyMetrics.locationName, locationName))).all();
|
|
34472
34587
|
const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and27(eq37(gbpPlaceActions.projectId, projectId), eq37(gbpPlaceActions.locationName, locationName))).all();
|
|
34473
34588
|
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and27(eq37(gbpLodgingSnapshots.projectId, projectId), eq37(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc18(gbpLodgingSnapshots.syncedAt)).limit(1).get();
|
|
34589
|
+
const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and27(eq37(gbpLocations.projectId, projectId), eq37(gbpLocations.locationName, locationName))).get();
|
|
34590
|
+
const descriptionMissing = !(ownerRow?.description ?? "").trim();
|
|
34474
34591
|
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and27(eq37(gbpPlaceDetails.projectId, projectId), eq37(gbpPlaceDetails.locationName, locationName))).orderBy(desc18(gbpPlaceDetails.syncedAt)).limit(1).get();
|
|
34475
34592
|
const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
|
|
34476
34593
|
const summary = buildGbpSummary({
|
|
@@ -34495,6 +34612,7 @@ var IntelligenceService = class {
|
|
|
34495
34612
|
metricDeltaPct: summary.performance.deltaPct,
|
|
34496
34613
|
lodgingCapable: summary.lodging.lodgingLocationCount > 0,
|
|
34497
34614
|
lodgingEmpty: summary.lodging.emptyLodgingCount > 0,
|
|
34615
|
+
descriptionMissing,
|
|
34498
34616
|
placesAmenities,
|
|
34499
34617
|
placeActionCount: summary.placeActions.total,
|
|
34500
34618
|
hasDirectMerchantCta: summary.placeActions.hasDirectMerchantCta,
|
|
@@ -34769,7 +34887,7 @@ var IntelligenceService = class {
|
|
|
34769
34887
|
}).run();
|
|
34770
34888
|
}
|
|
34771
34889
|
tx.insert(healthSnapshots).values({
|
|
34772
|
-
id:
|
|
34890
|
+
id: crypto30.randomUUID(),
|
|
34773
34891
|
projectId,
|
|
34774
34892
|
runId,
|
|
34775
34893
|
overallCitedRate: String(result.health.overallCitedRate),
|
|
@@ -34964,6 +35082,7 @@ export {
|
|
|
34964
35082
|
gbpPlaceActions,
|
|
34965
35083
|
gbpLodgingSnapshots,
|
|
34966
35084
|
gbpPlaceDetails,
|
|
35085
|
+
gbpAttributesSnapshots,
|
|
34967
35086
|
adsConnections,
|
|
34968
35087
|
adsCampaigns,
|
|
34969
35088
|
adsAdGroups,
|
|
@@ -34993,12 +35112,18 @@ export {
|
|
|
34993
35112
|
fetchSearchAnalytics,
|
|
34994
35113
|
inspectUrl,
|
|
34995
35114
|
GBP_DAILY_METRICS,
|
|
35115
|
+
listLocations,
|
|
35116
|
+
formatStorefrontAddress,
|
|
35117
|
+
buildLocationProfileFields,
|
|
34996
35118
|
fetchDailyMetrics,
|
|
34997
35119
|
listMonthlyKeywords,
|
|
34998
35120
|
listPlaceActionLinks,
|
|
34999
35121
|
getLodging,
|
|
35000
35122
|
countPopulatedGroups,
|
|
35001
35123
|
hashLodging,
|
|
35124
|
+
getAttributes,
|
|
35125
|
+
countAttributes,
|
|
35126
|
+
hashAttributes,
|
|
35002
35127
|
getUrlInfo,
|
|
35003
35128
|
getCrawlIssues,
|
|
35004
35129
|
getLinkCounts,
|