@canonry/canonry 4.133.1 → 4.133.3
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/canonry-cli.md +7 -0
- package/assets/assets/{AuditHistoryPanel-BKJ_bJO3.js → AuditHistoryPanel-DTHQGvkW.js} +1 -1
- package/assets/assets/{BacklinksPage-Dlp78T7O.js → BacklinksPage-DuPI3wt9.js} +1 -1
- package/assets/assets/{ChartPrimitives-BnqLVaHC.js → ChartPrimitives-T8mxOObc.js} +1 -1
- package/assets/assets/{HistoryPage-dEjboZIm.js → HistoryPage-T1W40xKG.js} +1 -1
- package/assets/assets/ProjectPage-DYwM8-Rp.js +8 -0
- package/assets/assets/{RunRow-C0PeLbDh.js → RunRow-nHr4wW9B.js} +1 -1
- package/assets/assets/{RunsPage-8cmHsMEV.js → RunsPage-Cbusy_84.js} +1 -1
- package/assets/assets/{SettingsPage-FzWCV54A.js → SettingsPage-BVcbl4gn.js} +1 -1
- package/assets/assets/{TrafficPage-BrEuU4K9.js → TrafficPage-CZ4NTWI6.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-yqyQGzqQ.js → TrafficSourceDetailPage-xW-KvZY1.js} +1 -1
- package/assets/assets/{arrow-left-DJbzrqwz.js → arrow-left-flskyFPK.js} +1 -1
- package/assets/assets/{extract-error-message-7lcxZroQ.js → extract-error-message-BHfCTm0H.js} +1 -1
- package/assets/assets/{index-DtOyJ_1v.js → index-CQzGDGMB.js} +64 -64
- package/assets/assets/index-JhX-wfQO.css +1 -0
- package/assets/assets/{trash-2-DFJYR1Fq.js → trash-2-LGfqtSzZ.js} +1 -1
- package/assets/index.html +2 -2
- package/dist/{chunk-42P7POVS.js → chunk-6ON6GUAL.js} +9 -5
- package/dist/{chunk-P4MIG7V5.js → chunk-A6BYMSZL.js} +30 -2
- package/dist/{chunk-VPY3PZXV.js → chunk-HENMGNLT.js} +344 -59
- package/dist/{chunk-ZPQX5ZQ2.js → chunk-YRRQFOAH.js} +92 -0
- package/dist/cli.js +45 -4
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-2K7GVEQM.js → intelligence-service-OSLFG5S2.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +8 -8
- package/assets/assets/ProjectPage-CV1zK5No.js +0 -8
- package/assets/assets/index-BKoAGOtU.css +0 -1
|
@@ -8,10 +8,16 @@ import {
|
|
|
8
8
|
AdsActivationEntityTypes,
|
|
9
9
|
AdsActivationGrantStates,
|
|
10
10
|
AdsActivationVersionPolicies,
|
|
11
|
+
AdsActivityAssessmentStates,
|
|
11
12
|
AdsAdGroupBillingEventTypes,
|
|
12
13
|
AdsCampaignBiddingTypes,
|
|
14
|
+
AdsDeliveryConfigurationBases,
|
|
15
|
+
AdsDeliverySnapshotIssues,
|
|
16
|
+
AdsDeliverySnapshotStatuses,
|
|
13
17
|
AdsEntityStatuses,
|
|
14
18
|
AdsEntityTypes,
|
|
19
|
+
AdsHistoricalCampaignRollupStatuses,
|
|
20
|
+
AdsInsightLevels,
|
|
15
21
|
AdsIntegrityDecisions,
|
|
16
22
|
AdsOperationKinds,
|
|
17
23
|
AdsOperationStates,
|
|
@@ -83,6 +89,7 @@ import {
|
|
|
83
89
|
adsConversionPixelListResponseSchema,
|
|
84
90
|
adsCpcMicros,
|
|
85
91
|
adsCtr,
|
|
92
|
+
adsDeliveryDiagnosticsDtoSchema,
|
|
86
93
|
adsDisconnectResponseSchema,
|
|
87
94
|
adsGeoSearchQuerySchema,
|
|
88
95
|
adsGeoSearchResponseSchema,
|
|
@@ -349,10 +356,10 @@ import {
|
|
|
349
356
|
wordpressSchemaDeployResultDtoSchema,
|
|
350
357
|
wordpressSchemaStatusResultDtoSchema,
|
|
351
358
|
wordpressStatusDtoSchema
|
|
352
|
-
} from "./chunk-
|
|
359
|
+
} from "./chunk-YRRQFOAH.js";
|
|
353
360
|
|
|
354
361
|
// src/intelligence-service.ts
|
|
355
|
-
import { eq as eq44, desc as
|
|
362
|
+
import { eq as eq44, desc as desc21, asc as asc9, and as and35, ne as ne6, or as or10, inArray as inArray15, gte as gte12, lte as lte8 } from "drizzle-orm";
|
|
356
363
|
|
|
357
364
|
// ../db/src/client.ts
|
|
358
365
|
import { mkdirSync } from "fs";
|
|
@@ -15267,22 +15274,48 @@ function sumSearchRows(rows) {
|
|
|
15267
15274
|
zero()
|
|
15268
15275
|
);
|
|
15269
15276
|
}
|
|
15277
|
+
var classifyVerificationStatus = (status) => {
|
|
15278
|
+
if (status === VerificationStatuses.verified) return "verified";
|
|
15279
|
+
if (status === VerificationStatuses.claimed_unverified) return "claimedUnverified";
|
|
15280
|
+
if (status === VerificationStatuses.unknown_ai_like) return "unknownAiLike";
|
|
15281
|
+
return null;
|
|
15282
|
+
};
|
|
15283
|
+
var emptyVerificationCounts = () => ({
|
|
15284
|
+
verified: 0,
|
|
15285
|
+
claimedUnverified: 0,
|
|
15286
|
+
unknownAiLike: 0
|
|
15287
|
+
});
|
|
15288
|
+
function summarizeVerificationHits(rows) {
|
|
15289
|
+
const counts2 = emptyVerificationCounts();
|
|
15290
|
+
let unsupportedRows = 0;
|
|
15291
|
+
let unsupportedHits = 0;
|
|
15292
|
+
for (const row of rows) {
|
|
15293
|
+
const tier = classifyVerificationStatus(row.verificationStatus);
|
|
15294
|
+
if (!tier) {
|
|
15295
|
+
unsupportedRows += 1;
|
|
15296
|
+
unsupportedHits += row.hits;
|
|
15297
|
+
continue;
|
|
15298
|
+
}
|
|
15299
|
+
counts2[tier] += row.hits;
|
|
15300
|
+
}
|
|
15301
|
+
return { counts: counts2, unsupportedRows, unsupportedHits };
|
|
15302
|
+
}
|
|
15270
15303
|
function summarizeServer(crawlers, fetches, referrals) {
|
|
15271
15304
|
const total = referrals.reduce((count2, row) => count2 + row.sessionsOrHits, 0);
|
|
15272
15305
|
const paid = referrals.reduce((count2, row) => count2 + row.paidSessionsOrHits, 0);
|
|
15273
15306
|
const organic = referrals.reduce((count2, row) => count2 + row.organicSessionsOrHits, 0);
|
|
15307
|
+
const crawlerHits = summarizeVerificationHits(crawlers);
|
|
15308
|
+
const userFetchHits = summarizeVerificationHits(fetches);
|
|
15274
15309
|
return {
|
|
15275
|
-
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
|
|
15279
|
-
},
|
|
15280
|
-
userFetchHits: {
|
|
15281
|
-
verified: fetches.filter((row) => row.verificationStatus === VerificationStatuses.verified).reduce((count2, row) => count2 + row.hits, 0),
|
|
15282
|
-
claimedUnverified: fetches.filter((row) => row.verificationStatus === VerificationStatuses.claimed_unverified).reduce((count2, row) => count2 + row.hits, 0),
|
|
15283
|
-
unknownAiLike: fetches.filter((row) => row.verificationStatus === VerificationStatuses.unknown_ai_like).reduce((count2, row) => count2 + row.hits, 0)
|
|
15310
|
+
summary: {
|
|
15311
|
+
crawlerHits: crawlerHits.counts,
|
|
15312
|
+
userFetchHits: userFetchHits.counts,
|
|
15313
|
+
referralSessions: { total, paid, organic, unknown: Math.max(0, total - paid - organic) }
|
|
15284
15314
|
},
|
|
15285
|
-
|
|
15315
|
+
unsupportedVerification: {
|
|
15316
|
+
rows: crawlerHits.unsupportedRows + userFetchHits.unsupportedRows,
|
|
15317
|
+
hits: crawlerHits.unsupportedHits + userFetchHits.unsupportedHits
|
|
15318
|
+
}
|
|
15286
15319
|
};
|
|
15287
15320
|
}
|
|
15288
15321
|
function comparisonDetail(latest, prior) {
|
|
@@ -15476,7 +15509,8 @@ function buildOrganicEvidence(db, projectName, periodDays) {
|
|
|
15476
15509
|
const crawlers = allCrawlers.filter((row) => serverInWindow(row.tsHour));
|
|
15477
15510
|
const fetches = allFetches.filter((row) => serverInWindow(row.tsHour));
|
|
15478
15511
|
const referrals = allReferrals.filter((row) => serverInWindow(row.tsHour));
|
|
15479
|
-
const
|
|
15512
|
+
const serverSummary = summarizeServer(crawlers, fetches, referrals);
|
|
15513
|
+
const server = serverSources.length ? serverSummary.summary : null;
|
|
15480
15514
|
const latest = db.select().from(runs).where(and14(
|
|
15481
15515
|
eq18(runs.projectId, project.id),
|
|
15482
15516
|
eq18(runs.kind, RunKinds["answer-visibility"]),
|
|
@@ -15523,16 +15557,16 @@ function buildOrganicEvidence(db, projectName, periodDays) {
|
|
|
15523
15557
|
ensurePage(row.landingPageNormalized ?? row.landingPage).ga4OrganicSessions += row.sessions;
|
|
15524
15558
|
}
|
|
15525
15559
|
for (const row of crawlers) {
|
|
15560
|
+
const tier = classifyVerificationStatus(row.verificationStatus);
|
|
15561
|
+
if (!tier) continue;
|
|
15526
15562
|
const counts2 = ensurePage(row.pathNormalized).server.crawlerHits;
|
|
15527
|
-
|
|
15528
|
-
else if (row.verificationStatus === VerificationStatuses.claimed_unverified) counts2.claimedUnverified += row.hits;
|
|
15529
|
-
else counts2.unknownAiLike += row.hits;
|
|
15563
|
+
counts2[tier] += row.hits;
|
|
15530
15564
|
}
|
|
15531
15565
|
for (const row of fetches) {
|
|
15566
|
+
const tier = classifyVerificationStatus(row.verificationStatus);
|
|
15567
|
+
if (!tier) continue;
|
|
15532
15568
|
const counts2 = ensurePage(row.pathNormalized).server.userFetchHits;
|
|
15533
|
-
|
|
15534
|
-
else if (row.verificationStatus === VerificationStatuses.claimed_unverified) counts2.claimedUnverified += row.hits;
|
|
15535
|
-
else counts2.unknownAiLike += row.hits;
|
|
15569
|
+
counts2[tier] += row.hits;
|
|
15536
15570
|
}
|
|
15537
15571
|
for (const row of referrals) {
|
|
15538
15572
|
const counts2 = ensurePage(row.landingPathNormalized).server.referralSessions;
|
|
@@ -15567,10 +15601,10 @@ function buildOrganicEvidence(db, projectName, periodDays) {
|
|
|
15567
15601
|
}
|
|
15568
15602
|
const latestGa = ga4?.cohorts.at(-1);
|
|
15569
15603
|
const priorGa = ga4?.cohorts.at(-2);
|
|
15570
|
-
if (ga4 && latestGa && priorGa) {
|
|
15604
|
+
if (ga4 && latestGa && priorGa && latestGa.organicSessions !== priorGa.organicSessions) {
|
|
15571
15605
|
findings.push({
|
|
15572
15606
|
tone: "neutral",
|
|
15573
|
-
title: "Organic sessions
|
|
15607
|
+
title: "Organic sessions changed",
|
|
15574
15608
|
detail: `GA4 organic sessions were ${comparisonDetail(latestGa.organicSessions, priorGa.organicSessions)}; visibility alone does not establish lead impact.`
|
|
15575
15609
|
});
|
|
15576
15610
|
}
|
|
@@ -15674,6 +15708,12 @@ function buildOrganicEvidence(db, projectName, periodDays) {
|
|
|
15674
15708
|
detail: "Claimed-unverified and heuristic AI requests are user-agent evidence without operator IP verification and are reported separately from verified requests."
|
|
15675
15709
|
});
|
|
15676
15710
|
}
|
|
15711
|
+
if (serverSummary.unsupportedVerification.rows > 0) {
|
|
15712
|
+
limitations.push({
|
|
15713
|
+
code: "unsupported-server-verification-status",
|
|
15714
|
+
detail: `Skipped ${serverSummary.unsupportedVerification.hits} server hits across ${serverSummary.unsupportedVerification.rows} rows with unsupported verification statuses; they are excluded from all verification tiers.`
|
|
15715
|
+
});
|
|
15716
|
+
}
|
|
15677
15717
|
if (visibility && visibility.ageDays > 30) {
|
|
15678
15718
|
limitations.push({
|
|
15679
15719
|
code: "stale-visibility-sweep",
|
|
@@ -17346,6 +17386,7 @@ var SCHEMA_TABLE = {
|
|
|
17346
17386
|
AdsActivationGrantResponse: adsActivationGrantResponseSchema,
|
|
17347
17387
|
AdsCampaignListResponse: adsCampaignListResponseSchema,
|
|
17348
17388
|
AdsConnectionStatusDto: adsConnectionStatusDtoSchema,
|
|
17389
|
+
AdsDeliveryDiagnosticsDto: adsDeliveryDiagnosticsDtoSchema,
|
|
17349
17390
|
AdsConversionEventSettingListResponse: adsConversionEventSettingListResponseSchema,
|
|
17350
17391
|
AdsConversionPixelListResponse: adsConversionPixelListResponseSchema,
|
|
17351
17392
|
AdsDisconnectResponse: adsDisconnectResponseSchema,
|
|
@@ -20342,6 +20383,18 @@ var routeCatalog = [
|
|
|
20342
20383
|
404: errorResponse("Project not found.")
|
|
20343
20384
|
}
|
|
20344
20385
|
},
|
|
20386
|
+
{
|
|
20387
|
+
method: "get",
|
|
20388
|
+
path: "/api/v1/projects/{name}/ads/delivery-diagnostics",
|
|
20389
|
+
summary: "Stored ads snapshot provenance, configuration facts, and historical campaign activity",
|
|
20390
|
+
description: "Read-only local evidence. It does not call OpenAI and never determines provider eligibility or serving.",
|
|
20391
|
+
tags: ["ads"],
|
|
20392
|
+
parameters: [nameParameter],
|
|
20393
|
+
responses: {
|
|
20394
|
+
200: jsonResponse("Stored diagnostics returned.", "AdsDeliveryDiagnosticsDto"),
|
|
20395
|
+
404: errorResponse("Project not found.")
|
|
20396
|
+
}
|
|
20397
|
+
},
|
|
20345
20398
|
{
|
|
20346
20399
|
method: "post",
|
|
20347
20400
|
path: "/api/v1/projects/{name}/bing/connect",
|
|
@@ -25975,7 +26028,7 @@ async function googleRoutes(app, opts) {
|
|
|
25975
26028
|
|
|
25976
26029
|
// ../api-routes/src/ads.ts
|
|
25977
26030
|
import crypto22 from "crypto";
|
|
25978
|
-
import { eq as eq28, and as and22, asc as asc6, gt as gt2, gte as gte8, lt as lt3, lte as lte6, ne as ne3, inArray as inArray12, or as or8, isNull as isNull2, isNotNull as isNotNull2, sql as sql14 } from "drizzle-orm";
|
|
26031
|
+
import { eq as eq28, and as and22, asc as asc6, desc as desc13, gt as gt2, gte as gte8, lt as lt3, lte as lte6, ne as ne3, inArray as inArray12, or as or8, isNull as isNull2, isNotNull as isNotNull2, sql as sql14 } from "drizzle-orm";
|
|
25979
26032
|
|
|
25980
26033
|
// ../api-routes/src/ads-activation-routes.ts
|
|
25981
26034
|
import crypto21 from "crypto";
|
|
@@ -28413,6 +28466,139 @@ function registerAdsActivationRoutes(app, opts) {
|
|
|
28413
28466
|
}
|
|
28414
28467
|
|
|
28415
28468
|
// ../api-routes/src/ads.ts
|
|
28469
|
+
function runSourceDto(row) {
|
|
28470
|
+
const parsed = runStatusSchema.safeParse(row.status);
|
|
28471
|
+
return parsed.success ? { runId: row.id, status: parsed.data } : null;
|
|
28472
|
+
}
|
|
28473
|
+
function storedSnapshotProvenance(input) {
|
|
28474
|
+
if (!input.connected) {
|
|
28475
|
+
return {
|
|
28476
|
+
status: AdsDeliverySnapshotStatuses.unavailable,
|
|
28477
|
+
issue: AdsDeliverySnapshotIssues.no_ads_connection,
|
|
28478
|
+
sourceSync: null
|
|
28479
|
+
};
|
|
28480
|
+
}
|
|
28481
|
+
if (input.connectionLastSyncedAt === null) {
|
|
28482
|
+
return {
|
|
28483
|
+
status: input.hasEntityRows ? AdsDeliverySnapshotStatuses.partial : AdsDeliverySnapshotStatuses.unavailable,
|
|
28484
|
+
issue: AdsDeliverySnapshotIssues.connection_not_synced,
|
|
28485
|
+
sourceSync: null
|
|
28486
|
+
};
|
|
28487
|
+
}
|
|
28488
|
+
if (!input.hasEntityRows) {
|
|
28489
|
+
if (!input.latestAdsSync) {
|
|
28490
|
+
return {
|
|
28491
|
+
status: AdsDeliverySnapshotStatuses.unavailable,
|
|
28492
|
+
issue: AdsDeliverySnapshotIssues.no_ads_sync,
|
|
28493
|
+
sourceSync: null
|
|
28494
|
+
};
|
|
28495
|
+
}
|
|
28496
|
+
const sourceSync2 = runSourceDto(input.latestAdsSync);
|
|
28497
|
+
if (!sourceSync2 || sourceSync2.status !== RunStatuses.completed) {
|
|
28498
|
+
return {
|
|
28499
|
+
status: AdsDeliverySnapshotStatuses.partial,
|
|
28500
|
+
issue: AdsDeliverySnapshotIssues.source_sync_not_completed,
|
|
28501
|
+
sourceSync: sourceSync2
|
|
28502
|
+
};
|
|
28503
|
+
}
|
|
28504
|
+
return {
|
|
28505
|
+
status: AdsDeliverySnapshotStatuses.complete,
|
|
28506
|
+
issue: null,
|
|
28507
|
+
sourceSync: sourceSync2
|
|
28508
|
+
};
|
|
28509
|
+
}
|
|
28510
|
+
if (input.hasEntityWithoutSyncRunId) {
|
|
28511
|
+
return {
|
|
28512
|
+
status: AdsDeliverySnapshotStatuses.partial,
|
|
28513
|
+
issue: AdsDeliverySnapshotIssues.entity_rows_missing_sync_run_id,
|
|
28514
|
+
sourceSync: null
|
|
28515
|
+
};
|
|
28516
|
+
}
|
|
28517
|
+
if (input.entitySyncRunIds.size !== 1) {
|
|
28518
|
+
return {
|
|
28519
|
+
status: AdsDeliverySnapshotStatuses.partial,
|
|
28520
|
+
issue: AdsDeliverySnapshotIssues.entity_rows_span_multiple_sync_runs,
|
|
28521
|
+
sourceSync: null
|
|
28522
|
+
};
|
|
28523
|
+
}
|
|
28524
|
+
if (!input.sourceSync) {
|
|
28525
|
+
return {
|
|
28526
|
+
status: AdsDeliverySnapshotStatuses.partial,
|
|
28527
|
+
issue: AdsDeliverySnapshotIssues.source_sync_missing,
|
|
28528
|
+
sourceSync: null
|
|
28529
|
+
};
|
|
28530
|
+
}
|
|
28531
|
+
const sourceSync = runSourceDto(input.sourceSync);
|
|
28532
|
+
if (input.sourceSync.kind !== RunKinds["ads-sync"]) {
|
|
28533
|
+
return {
|
|
28534
|
+
status: AdsDeliverySnapshotStatuses.partial,
|
|
28535
|
+
issue: AdsDeliverySnapshotIssues.source_sync_not_ads_sync,
|
|
28536
|
+
sourceSync
|
|
28537
|
+
};
|
|
28538
|
+
}
|
|
28539
|
+
if (!sourceSync || sourceSync.status !== RunStatuses.completed) {
|
|
28540
|
+
return {
|
|
28541
|
+
status: AdsDeliverySnapshotStatuses.partial,
|
|
28542
|
+
issue: AdsDeliverySnapshotIssues.source_sync_not_completed,
|
|
28543
|
+
sourceSync
|
|
28544
|
+
};
|
|
28545
|
+
}
|
|
28546
|
+
return {
|
|
28547
|
+
status: AdsDeliverySnapshotStatuses.complete,
|
|
28548
|
+
issue: null,
|
|
28549
|
+
sourceSync
|
|
28550
|
+
};
|
|
28551
|
+
}
|
|
28552
|
+
function historicalCampaignRollups(rows) {
|
|
28553
|
+
if (rows.length === 0) {
|
|
28554
|
+
return {
|
|
28555
|
+
status: AdsHistoricalCampaignRollupStatuses.unavailable,
|
|
28556
|
+
window: { from: null, to: null },
|
|
28557
|
+
totals: null
|
|
28558
|
+
};
|
|
28559
|
+
}
|
|
28560
|
+
let impressions = 0;
|
|
28561
|
+
let clicks = 0;
|
|
28562
|
+
let spendMicros = 0;
|
|
28563
|
+
let conversions = 0;
|
|
28564
|
+
let fromDate = null;
|
|
28565
|
+
let toDate = null;
|
|
28566
|
+
for (const row of rows) {
|
|
28567
|
+
impressions += row.impressions;
|
|
28568
|
+
clicks += row.clicks;
|
|
28569
|
+
spendMicros += row.spendMicros;
|
|
28570
|
+
conversions += row.conversions;
|
|
28571
|
+
if (fromDate === null || row.date < fromDate) fromDate = row.date;
|
|
28572
|
+
if (toDate === null || row.date > toDate) toDate = row.date;
|
|
28573
|
+
}
|
|
28574
|
+
return {
|
|
28575
|
+
status: AdsHistoricalCampaignRollupStatuses.reported,
|
|
28576
|
+
window: { from: fromDate, to: toDate },
|
|
28577
|
+
totals: {
|
|
28578
|
+
impressions,
|
|
28579
|
+
clicks,
|
|
28580
|
+
spendMicros,
|
|
28581
|
+
conversions,
|
|
28582
|
+
ctr: adsCtr(clicks, impressions),
|
|
28583
|
+
cpcMicros: adsCpcMicros(spendMicros, clicks)
|
|
28584
|
+
}
|
|
28585
|
+
};
|
|
28586
|
+
}
|
|
28587
|
+
function storedActivityAssessment(snapshotStatus, rollupStatus, rollupImpressions) {
|
|
28588
|
+
switch (snapshotStatus) {
|
|
28589
|
+
case AdsDeliverySnapshotStatuses.unavailable:
|
|
28590
|
+
return AdsActivityAssessmentStates.unavailable;
|
|
28591
|
+
case AdsDeliverySnapshotStatuses.partial:
|
|
28592
|
+
return AdsActivityAssessmentStates.partial_snapshot;
|
|
28593
|
+
case AdsDeliverySnapshotStatuses.complete:
|
|
28594
|
+
switch (rollupStatus) {
|
|
28595
|
+
case AdsHistoricalCampaignRollupStatuses.unavailable:
|
|
28596
|
+
return AdsActivityAssessmentStates.metrics_unavailable;
|
|
28597
|
+
case AdsHistoricalCampaignRollupStatuses.reported:
|
|
28598
|
+
return (rollupImpressions ?? 0) > 0 ? AdsActivityAssessmentStates.observed_activity : AdsActivityAssessmentStates.no_observed_activity;
|
|
28599
|
+
}
|
|
28600
|
+
}
|
|
28601
|
+
}
|
|
28416
28602
|
var DEFAULT_RECONCILE_SWEEP_INTERVAL_MS = 6e4;
|
|
28417
28603
|
var DEFAULT_RECONCILE_PENDING_STALE_MS = 5 * 6e4;
|
|
28418
28604
|
var DEFAULT_RECONCILE_BACKOFF_BASE_MS = 5 * 6e4;
|
|
@@ -29538,6 +29724,10 @@ async function adsRoutes(app, opts) {
|
|
|
29538
29724
|
reviewStatus: account.reviewStatus,
|
|
29539
29725
|
integrityReviewStatus: account.integrityReviewStatus,
|
|
29540
29726
|
integrityDecision: account.integrityDecision,
|
|
29727
|
+
// A credential rotation for the same account preserves its
|
|
29728
|
+
// snapshot watermark. A different account invalidates all stored
|
|
29729
|
+
// entity/insight provenance until the new binding is synced.
|
|
29730
|
+
lastSyncedAt: existingRow.adAccountId === account.id ? existingRow.lastSyncedAt : null,
|
|
29541
29731
|
updatedAt: now
|
|
29542
29732
|
}).where(eq28(adsConnections.id, existingRow.id)).run();
|
|
29543
29733
|
} else {
|
|
@@ -30093,6 +30283,101 @@ async function adsRoutes(app, opts) {
|
|
|
30093
30283
|
const response = { rows: dtoRows, currencyCode: conn?.currencyCode ?? null };
|
|
30094
30284
|
return response;
|
|
30095
30285
|
});
|
|
30286
|
+
app.get("/projects/:name/ads/delivery-diagnostics", async (request) => {
|
|
30287
|
+
const project = resolveProject(app.db, request.params.name);
|
|
30288
|
+
const connection = app.db.select().from(adsConnections).where(eq28(adsConnections.projectId, project.id)).get();
|
|
30289
|
+
const campaignRows = app.db.select().from(adsCampaigns).where(eq28(adsCampaigns.projectId, project.id)).all();
|
|
30290
|
+
const adGroupRows = app.db.select().from(adsAdGroups).where(eq28(adsAdGroups.projectId, project.id)).all();
|
|
30291
|
+
const adRows = app.db.select().from(adsAds).where(eq28(adsAds.projectId, project.id)).all();
|
|
30292
|
+
const entityRows = [...campaignRows, ...adGroupRows, ...adRows];
|
|
30293
|
+
const hasEntityWithoutSyncRunId = entityRows.some((row) => row.syncRunId === null);
|
|
30294
|
+
const entitySyncRunIds = new Set(entityRows.flatMap((row) => row.syncRunId === null ? [] : [row.syncRunId]));
|
|
30295
|
+
const sourceSync = entitySyncRunIds.size === 1 ? app.db.select({ id: runs.id, kind: runs.kind, status: runs.status }).from(runs).where(and22(
|
|
30296
|
+
eq28(runs.id, [...entitySyncRunIds][0]),
|
|
30297
|
+
eq28(runs.projectId, project.id)
|
|
30298
|
+
)).get() : void 0;
|
|
30299
|
+
const latestAdsSync = app.db.select({ id: runs.id, kind: runs.kind, status: runs.status }).from(runs).where(and22(
|
|
30300
|
+
eq28(runs.projectId, project.id),
|
|
30301
|
+
eq28(runs.kind, RunKinds["ads-sync"])
|
|
30302
|
+
)).orderBy(desc13(runs.createdAt)).get();
|
|
30303
|
+
const snapshot = storedSnapshotProvenance({
|
|
30304
|
+
connected: Boolean(connection),
|
|
30305
|
+
connectionLastSyncedAt: connection?.lastSyncedAt ?? null,
|
|
30306
|
+
hasEntityRows: entityRows.length > 0,
|
|
30307
|
+
hasEntityWithoutSyncRunId,
|
|
30308
|
+
entitySyncRunIds,
|
|
30309
|
+
sourceSync,
|
|
30310
|
+
latestAdsSync
|
|
30311
|
+
});
|
|
30312
|
+
const rollups = historicalCampaignRollups(app.db.select({
|
|
30313
|
+
date: adsInsightsDaily.date,
|
|
30314
|
+
impressions: adsInsightsDaily.impressions,
|
|
30315
|
+
clicks: adsInsightsDaily.clicks,
|
|
30316
|
+
spendMicros: adsInsightsDaily.spendMicros,
|
|
30317
|
+
conversions: adsInsightsDaily.conversions
|
|
30318
|
+
}).from(adsInsightsDaily).where(and22(
|
|
30319
|
+
eq28(adsInsightsDaily.projectId, project.id),
|
|
30320
|
+
eq28(adsInsightsDaily.level, AdsInsightLevels.campaign)
|
|
30321
|
+
)).all());
|
|
30322
|
+
const adsByGroup = /* @__PURE__ */ new Map();
|
|
30323
|
+
for (const ad of adRows) {
|
|
30324
|
+
const list = adsByGroup.get(ad.adGroupId) ?? [];
|
|
30325
|
+
list.push({ id: ad.id, name: ad.name, status: ad.status, reviewStatus: ad.reviewStatus });
|
|
30326
|
+
adsByGroup.set(ad.adGroupId, list);
|
|
30327
|
+
}
|
|
30328
|
+
const groupsByCampaign = /* @__PURE__ */ new Map();
|
|
30329
|
+
for (const adGroup of adGroupRows) {
|
|
30330
|
+
const list = groupsByCampaign.get(adGroup.campaignId) ?? [];
|
|
30331
|
+
list.push({
|
|
30332
|
+
id: adGroup.id,
|
|
30333
|
+
name: adGroup.name,
|
|
30334
|
+
status: adGroup.status,
|
|
30335
|
+
billingEventType: adGroupBillingEventTypeDto(adGroup.billingEventType),
|
|
30336
|
+
maxBidMicros: adGroup.maxBidMicros,
|
|
30337
|
+
contextHints: adGroup.contextHints,
|
|
30338
|
+
ads: adsByGroup.get(adGroup.id) ?? []
|
|
30339
|
+
});
|
|
30340
|
+
groupsByCampaign.set(adGroup.campaignId, list);
|
|
30341
|
+
}
|
|
30342
|
+
const response = {
|
|
30343
|
+
snapshot: {
|
|
30344
|
+
...snapshot,
|
|
30345
|
+
lastSyncedAt: connection?.lastSyncedAt ?? null,
|
|
30346
|
+
campaignCount: campaignRows.length,
|
|
30347
|
+
adGroupCount: adGroupRows.length,
|
|
30348
|
+
adCount: adRows.length
|
|
30349
|
+
},
|
|
30350
|
+
historicalCampaignRollups: rollups,
|
|
30351
|
+
storedConfiguration: {
|
|
30352
|
+
basis: AdsDeliveryConfigurationBases.storedSnapshot,
|
|
30353
|
+
connection: connection === void 0 ? null : {
|
|
30354
|
+
status: connection.status,
|
|
30355
|
+
reviewStatus: connection.reviewStatus,
|
|
30356
|
+
integrityReviewStatus: connection.integrityReviewStatus,
|
|
30357
|
+
integrityDecision: connection.integrityDecision,
|
|
30358
|
+
conversionTrackingConfigured: connection.conversionTrackingConfigured
|
|
30359
|
+
},
|
|
30360
|
+
campaigns: campaignRows.map((campaign) => ({
|
|
30361
|
+
id: campaign.id,
|
|
30362
|
+
name: campaign.name,
|
|
30363
|
+
status: campaign.status,
|
|
30364
|
+
biddingType: campaignBiddingTypeDto(campaign.biddingType),
|
|
30365
|
+
dailySpendLimitMicros: campaign.dailySpendLimitMicros,
|
|
30366
|
+
lifetimeSpendLimitMicros: campaign.lifetimeSpendLimitMicros,
|
|
30367
|
+
conversionEventSettingIds: campaign.conversionEventSettingIds,
|
|
30368
|
+
adGroups: groupsByCampaign.get(campaign.id) ?? []
|
|
30369
|
+
}))
|
|
30370
|
+
},
|
|
30371
|
+
assessment: {
|
|
30372
|
+
state: storedActivityAssessment(
|
|
30373
|
+
snapshot.status,
|
|
30374
|
+
rollups.status,
|
|
30375
|
+
rollups.totals === null ? null : rollups.totals.impressions
|
|
30376
|
+
)
|
|
30377
|
+
}
|
|
30378
|
+
};
|
|
30379
|
+
return response;
|
|
30380
|
+
});
|
|
30096
30381
|
app.get("/projects/:name/ads/summary", async (request) => {
|
|
30097
30382
|
const project = resolveProject(app.db, request.params.name);
|
|
30098
30383
|
const row = app.db.select().from(adsConnections).where(eq28(adsConnections.projectId, project.id)).get();
|
|
@@ -30141,7 +30426,7 @@ async function adsRoutes(app, opts) {
|
|
|
30141
30426
|
|
|
30142
30427
|
// ../api-routes/src/bing.ts
|
|
30143
30428
|
import crypto23 from "crypto";
|
|
30144
|
-
import { eq as eq29, and as and23, desc as
|
|
30429
|
+
import { eq as eq29, and as and23, desc as desc14 } from "drizzle-orm";
|
|
30145
30430
|
|
|
30146
30431
|
// ../integration-bing/src/constants.ts
|
|
30147
30432
|
var BING_WMT_API_BASE = "https://ssl.bing.com/webmaster/api.svc/json";
|
|
@@ -30515,7 +30800,7 @@ async function bingRoutes(app, opts) {
|
|
|
30515
30800
|
const store = requireConnectionStore();
|
|
30516
30801
|
const project = resolveProject(app.db, request.params.name);
|
|
30517
30802
|
requireConnection(store, project.canonicalDomain);
|
|
30518
|
-
const allInspections = app.db.select().from(bingUrlInspections).where(eq29(bingUrlInspections.projectId, project.id)).orderBy(
|
|
30803
|
+
const allInspections = app.db.select().from(bingUrlInspections).where(eq29(bingUrlInspections.projectId, project.id)).orderBy(desc14(bingUrlInspections.inspectedAt)).all();
|
|
30519
30804
|
const latestByUrl = /* @__PURE__ */ new Map();
|
|
30520
30805
|
const definitiveByUrl = /* @__PURE__ */ new Map();
|
|
30521
30806
|
for (const row of allInspections) {
|
|
@@ -30604,7 +30889,7 @@ async function bingRoutes(app, opts) {
|
|
|
30604
30889
|
const project = resolveProject(app.db, request.params.name);
|
|
30605
30890
|
const parsed = parseInt(request.query.limit ?? "90", 10);
|
|
30606
30891
|
const limit = Number.isNaN(parsed) || parsed <= 0 ? 90 : parsed;
|
|
30607
|
-
const rows = app.db.select().from(bingCoverageSnapshots).where(eq29(bingCoverageSnapshots.projectId, project.id)).orderBy(
|
|
30892
|
+
const rows = app.db.select().from(bingCoverageSnapshots).where(eq29(bingCoverageSnapshots.projectId, project.id)).orderBy(desc14(bingCoverageSnapshots.date)).limit(limit).all();
|
|
30608
30893
|
return rows.map((r) => ({
|
|
30609
30894
|
date: r.date,
|
|
30610
30895
|
indexed: r.indexed,
|
|
@@ -30617,7 +30902,7 @@ async function bingRoutes(app, opts) {
|
|
|
30617
30902
|
const project = resolveProject(app.db, request.params.name);
|
|
30618
30903
|
const { url, limit } = request.query;
|
|
30619
30904
|
const whereClause = url ? and23(eq29(bingUrlInspections.projectId, project.id), eq29(bingUrlInspections.url, url)) : eq29(bingUrlInspections.projectId, project.id);
|
|
30620
|
-
const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(
|
|
30905
|
+
const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(desc14(bingUrlInspections.inspectedAt)).limit(Math.max(1, Math.min(parseInt(limit ?? "100", 10) || 100, 1e3))).all();
|
|
30621
30906
|
return filtered.map((r) => ({
|
|
30622
30907
|
id: r.id,
|
|
30623
30908
|
url: r.url,
|
|
@@ -30761,7 +31046,7 @@ async function bingRoutes(app, opts) {
|
|
|
30761
31046
|
}
|
|
30762
31047
|
let urlsToSubmit = request.body?.urls ?? [];
|
|
30763
31048
|
if (request.body?.allUnindexed) {
|
|
30764
|
-
const allInspections = app.db.select().from(bingUrlInspections).where(eq29(bingUrlInspections.projectId, project.id)).orderBy(
|
|
31049
|
+
const allInspections = app.db.select().from(bingUrlInspections).where(eq29(bingUrlInspections.projectId, project.id)).orderBy(desc14(bingUrlInspections.inspectedAt)).all();
|
|
30765
31050
|
const latestByUrl = /* @__PURE__ */ new Map();
|
|
30766
31051
|
for (const row of allInspections) {
|
|
30767
31052
|
if (!latestByUrl.has(row.url)) {
|
|
@@ -31020,7 +31305,7 @@ async function cdpRoutes(app, opts) {
|
|
|
31020
31305
|
|
|
31021
31306
|
// ../api-routes/src/ga.ts
|
|
31022
31307
|
import crypto24 from "crypto";
|
|
31023
|
-
import { eq as eq31, desc as
|
|
31308
|
+
import { eq as eq31, desc as desc15, and as and25, sql as sql15 } from "drizzle-orm";
|
|
31024
31309
|
|
|
31025
31310
|
// ../api-routes/src/ga-session-history.ts
|
|
31026
31311
|
function buildSessionHistory(landingPageDays, dailyTotals) {
|
|
@@ -31467,7 +31752,7 @@ async function ga4Routes(app, opts) {
|
|
|
31467
31752
|
if (!connected) {
|
|
31468
31753
|
return { connected: false, propertyId: null, clientEmail: null, authMethod: null, lastSyncedAt: null };
|
|
31469
31754
|
}
|
|
31470
|
-
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq31(gaTrafficSummaries.projectId, project.id)).orderBy(
|
|
31755
|
+
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq31(gaTrafficSummaries.projectId, project.id)).orderBy(desc15(gaTrafficSummaries.syncedAt)).limit(1).get();
|
|
31471
31756
|
return {
|
|
31472
31757
|
connected: true,
|
|
31473
31758
|
propertyId: saConn?.propertyId ?? oauthConn?.propertyId ?? null,
|
|
@@ -31873,7 +32158,7 @@ async function ga4Routes(app, opts) {
|
|
|
31873
32158
|
sessions: sql15`SUM(${gaSocialReferrals.sessions})`,
|
|
31874
32159
|
users: sql15`SUM(${gaSocialReferrals.users})`
|
|
31875
32160
|
}).from(gaSocialReferrals).where(and25(...socialConditions)).get();
|
|
31876
|
-
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq31(gaTrafficSummaries.projectId, project.id)).orderBy(
|
|
32161
|
+
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq31(gaTrafficSummaries.projectId, project.id)).orderBy(desc15(gaTrafficSummaries.syncedAt)).limit(1).get();
|
|
31877
32162
|
const total = summaryRow?.totalSessions ?? 0;
|
|
31878
32163
|
const totalDirectSessions = directTotalRow?.totalDirectSessions ?? 0;
|
|
31879
32164
|
const totalOrganicSessions = summaryRow?.totalOrganicSessions ?? 0;
|
|
@@ -33818,7 +34103,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
33818
34103
|
|
|
33819
34104
|
// ../api-routes/src/backlinks.ts
|
|
33820
34105
|
import crypto26 from "crypto";
|
|
33821
|
-
import { and as and27, asc as asc7, desc as
|
|
34106
|
+
import { and as and27, asc as asc7, desc as desc16, eq as eq32, sql as sql16 } from "drizzle-orm";
|
|
33822
34107
|
|
|
33823
34108
|
// ../integration-commoncrawl/src/constants.ts
|
|
33824
34109
|
import os2 from "os";
|
|
@@ -34319,7 +34604,7 @@ function latestSummaryForProject(db, projectId, source, release) {
|
|
|
34319
34604
|
eq32(backlinkSummaries.source, source)
|
|
34320
34605
|
];
|
|
34321
34606
|
if (release) conditions.push(eq32(backlinkSummaries.release, release));
|
|
34322
|
-
return db.select().from(backlinkSummaries).where(and27(...conditions)).orderBy(
|
|
34607
|
+
return db.select().from(backlinkSummaries).where(and27(...conditions)).orderBy(desc16(backlinkSummaries.queriedAt)).limit(1).get();
|
|
34323
34608
|
}
|
|
34324
34609
|
function parseExcludeCrawlers(value) {
|
|
34325
34610
|
if (!value) return false;
|
|
@@ -34341,7 +34626,7 @@ function computeFilteredSummary(db, base) {
|
|
|
34341
34626
|
count: sql16`count(*)`,
|
|
34342
34627
|
total: sql16`coalesce(sum(${backlinkDomains.numHosts}), 0)`
|
|
34343
34628
|
}).from(backlinkDomains).where(filteredCondition).get();
|
|
34344
|
-
const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(
|
|
34629
|
+
const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(desc16(backlinkDomains.numHosts)).limit(10).all();
|
|
34345
34630
|
const totalLinkingDomains = Number(filteredAgg?.count ?? 0);
|
|
34346
34631
|
const totalHosts = Number(filteredAgg?.total ?? 0);
|
|
34347
34632
|
const unfilteredLinkingDomains = Number(unfilteredAgg?.count ?? 0);
|
|
@@ -34362,7 +34647,7 @@ function computeFilteredSummary(db, base) {
|
|
|
34362
34647
|
};
|
|
34363
34648
|
}
|
|
34364
34649
|
function buildSourceAvailability(db, projectId, source, connected, excludeCrawlers) {
|
|
34365
|
-
const summary = db.select().from(backlinkSummaries).where(and27(eq32(backlinkSummaries.projectId, projectId), eq32(backlinkSummaries.source, source))).orderBy(
|
|
34650
|
+
const summary = db.select().from(backlinkSummaries).where(and27(eq32(backlinkSummaries.projectId, projectId), eq32(backlinkSummaries.source, source))).orderBy(desc16(backlinkSummaries.queriedAt)).limit(1).get();
|
|
34366
34651
|
let totalLinkingDomains = summary?.totalLinkingDomains ?? 0;
|
|
34367
34652
|
if (summary && excludeCrawlers) {
|
|
34368
34653
|
const filtered = db.select({ count: sql16`count(*)` }).from(backlinkDomains).where(and27(
|
|
@@ -34468,11 +34753,11 @@ async function backlinksRoutes(app, opts) {
|
|
|
34468
34753
|
return reply.status(201).send(mapSyncRow(inserted));
|
|
34469
34754
|
});
|
|
34470
34755
|
app.get("/backlinks/syncs/latest", async (_request, reply) => {
|
|
34471
|
-
const row = app.db.select().from(ccReleaseSyncs).orderBy(
|
|
34756
|
+
const row = app.db.select().from(ccReleaseSyncs).orderBy(desc16(ccReleaseSyncs.updatedAt)).limit(1).get();
|
|
34472
34757
|
return reply.send(row ? mapSyncRow(row) : null);
|
|
34473
34758
|
});
|
|
34474
34759
|
app.get("/backlinks/syncs", async (_request, reply) => {
|
|
34475
|
-
const rows = app.db.select().from(ccReleaseSyncs).orderBy(
|
|
34760
|
+
const rows = app.db.select().from(ccReleaseSyncs).orderBy(desc16(ccReleaseSyncs.updatedAt)).all();
|
|
34476
34761
|
return reply.send(rows.map(mapSyncRow));
|
|
34477
34762
|
});
|
|
34478
34763
|
app.get("/backlinks/releases", async (_request, reply) => {
|
|
@@ -34559,7 +34844,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
34559
34844
|
linkingDomain: backlinkDomains.linkingDomain,
|
|
34560
34845
|
numHosts: backlinkDomains.numHosts,
|
|
34561
34846
|
source: backlinkDomains.source
|
|
34562
|
-
}).from(backlinkDomains).where(domainCondition).orderBy(
|
|
34847
|
+
}).from(backlinkDomains).where(domainCondition).orderBy(desc16(backlinkDomains.numHosts)).limit(limit).offset(offset).all();
|
|
34563
34848
|
let summary = null;
|
|
34564
34849
|
if (summaryRow) {
|
|
34565
34850
|
summary = excludeCrawlers ? computeFilteredSummary(app.db, summaryRow) : mapSummaryRow(summaryRow);
|
|
@@ -34633,7 +34918,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
34633
34918
|
// ../api-routes/src/traffic.ts
|
|
34634
34919
|
import crypto28 from "crypto";
|
|
34635
34920
|
import { Agent as UndiciAgent } from "undici";
|
|
34636
|
-
import { and as and28, desc as
|
|
34921
|
+
import { and as and28, desc as desc17, eq as eq33, gte as gte9, lte as lte7, sql as sql17 } from "drizzle-orm";
|
|
34637
34922
|
|
|
34638
34923
|
// ../integration-cloud-run/src/auth.ts
|
|
34639
34924
|
import crypto27 from "crypto";
|
|
@@ -39735,7 +40020,7 @@ async function trafficRoutes(app, opts) {
|
|
|
39735
40020
|
eq33(runs.kind, RunKinds["traffic-sync"]),
|
|
39736
40021
|
eq33(runs.sourceId, row.id)
|
|
39737
40022
|
)
|
|
39738
|
-
).orderBy(
|
|
40023
|
+
).orderBy(desc17(runs.startedAt)).limit(1).get();
|
|
39739
40024
|
return {
|
|
39740
40025
|
...rowToDto(row),
|
|
39741
40026
|
totals24h: {
|
|
@@ -39795,14 +40080,14 @@ async function trafficRoutes(app, opts) {
|
|
|
39795
40080
|
});
|
|
39796
40081
|
app.get("/projects/:name/traffic/sources", async (request) => {
|
|
39797
40082
|
const project = resolveProject(app.db, request.params.name);
|
|
39798
|
-
const rows = app.db.select().from(trafficSources).where(eq33(trafficSources.projectId, project.id)).orderBy(
|
|
40083
|
+
const rows = app.db.select().from(trafficSources).where(eq33(trafficSources.projectId, project.id)).orderBy(desc17(trafficSources.createdAt)).all();
|
|
39799
40084
|
const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map(rowToDto);
|
|
39800
40085
|
const response = { sources };
|
|
39801
40086
|
return response;
|
|
39802
40087
|
});
|
|
39803
40088
|
app.get("/projects/:name/traffic/status", async (request) => {
|
|
39804
40089
|
const project = resolveProject(app.db, request.params.name);
|
|
39805
|
-
const rows = app.db.select().from(trafficSources).where(eq33(trafficSources.projectId, project.id)).orderBy(
|
|
40090
|
+
const rows = app.db.select().from(trafficSources).where(eq33(trafficSources.projectId, project.id)).orderBy(desc17(trafficSources.createdAt)).all();
|
|
39806
40091
|
const since = new Date(Date.now() - 24 * 60 * 6e4).toISOString();
|
|
39807
40092
|
const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map((row) => buildSourceDetail(project.id, row, since));
|
|
39808
40093
|
const response = { sources };
|
|
@@ -39901,7 +40186,7 @@ async function trafficRoutes(app, opts) {
|
|
|
39901
40186
|
for (const row of crawlerSeries) {
|
|
39902
40187
|
trafficSeriesPoint(seriesByBucket, row.bucket).crawlerHits = Number(row.hits);
|
|
39903
40188
|
}
|
|
39904
|
-
const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(
|
|
40189
|
+
const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc17(crawlerEventsHourly.tsHour)).limit(limit).all();
|
|
39905
40190
|
for (const r of rows) {
|
|
39906
40191
|
events.push({
|
|
39907
40192
|
kind: TrafficEventKinds.crawler,
|
|
@@ -39939,7 +40224,7 @@ async function trafficRoutes(app, opts) {
|
|
|
39939
40224
|
for (const row of userFetchSeries) {
|
|
39940
40225
|
trafficSeriesPoint(seriesByBucket, row.bucket).aiUserFetchHits = Number(row.hits);
|
|
39941
40226
|
}
|
|
39942
|
-
const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(
|
|
40227
|
+
const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(desc17(aiUserFetchEventsHourly.tsHour)).limit(limit).all();
|
|
39943
40228
|
for (const r of rows) {
|
|
39944
40229
|
events.push({
|
|
39945
40230
|
kind: TrafficEventKinds["ai-user-fetch"],
|
|
@@ -39982,7 +40267,7 @@ async function trafficRoutes(app, opts) {
|
|
|
39982
40267
|
for (const row of referralSeries) {
|
|
39983
40268
|
trafficSeriesPoint(seriesByBucket, row.bucket).aiReferralHits = Number(row.hits);
|
|
39984
40269
|
}
|
|
39985
|
-
const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(
|
|
40270
|
+
const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc17(aiReferralEventsHourly.tsHour)).limit(limit).all();
|
|
39986
40271
|
for (const r of rows) {
|
|
39987
40272
|
const counts2 = aiReferralClassCounts(r.sessionsOrHits, r.paidSessionsOrHits, r.organicSessionsOrHits);
|
|
39988
40273
|
events.push({
|
|
@@ -42218,7 +42503,7 @@ async function doctorRoutes(app, opts) {
|
|
|
42218
42503
|
|
|
42219
42504
|
// ../api-routes/src/discovery/routes.ts
|
|
42220
42505
|
import crypto30 from "crypto";
|
|
42221
|
-
import { and as and32, desc as
|
|
42506
|
+
import { and as and32, desc as desc18, eq as eq40, gte as gte11, inArray as inArray13, isNull as isNull3, or as or9 } from "drizzle-orm";
|
|
42222
42507
|
var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
|
|
42223
42508
|
async function discoveryRoutes(app, opts) {
|
|
42224
42509
|
app.post("/projects/:name/discover/run", async (request, reply) => {
|
|
@@ -42279,7 +42564,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
42279
42564
|
DiscoverySessionStatuses.probing
|
|
42280
42565
|
]),
|
|
42281
42566
|
gte11(discoverySessions.createdAt, ageFloorIso)
|
|
42282
|
-
)).orderBy(
|
|
42567
|
+
)).orderBy(desc18(discoverySessions.createdAt)).get();
|
|
42283
42568
|
if (existing && existing.runId) {
|
|
42284
42569
|
return { reused: true, sessionId: existing.id, runId: existing.runId };
|
|
42285
42570
|
}
|
|
@@ -42348,7 +42633,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
42348
42633
|
const project = resolveProject(app.db, request.params.name);
|
|
42349
42634
|
const parsedLimit = parseInt(request.query.limit ?? "", 10);
|
|
42350
42635
|
const limit = Number.isNaN(parsedLimit) || parsedLimit <= 0 ? 50 : parsedLimit;
|
|
42351
|
-
const rows = app.db.select().from(discoverySessions).where(eq40(discoverySessions.projectId, project.id)).orderBy(
|
|
42636
|
+
const rows = app.db.select().from(discoverySessions).where(eq40(discoverySessions.projectId, project.id)).orderBy(desc18(discoverySessions.createdAt)).limit(limit).all();
|
|
42352
42637
|
return reply.send(rows.map(serializeSession));
|
|
42353
42638
|
}
|
|
42354
42639
|
);
|
|
@@ -42898,7 +43183,7 @@ function dedupeStrings(input) {
|
|
|
42898
43183
|
|
|
42899
43184
|
// ../api-routes/src/technical-aeo.ts
|
|
42900
43185
|
import crypto32 from "crypto";
|
|
42901
|
-
import { and as and33, asc as asc8, count, desc as
|
|
43186
|
+
import { and as and33, asc as asc8, count, desc as desc19, eq as eq42, inArray as inArray14, lt as lt4 } from "drizzle-orm";
|
|
42902
43187
|
var SURFACEABLE_STATUSES = [RunStatuses.completed, RunStatuses.partial];
|
|
42903
43188
|
function emptyScore(projectName) {
|
|
42904
43189
|
return {
|
|
@@ -42937,13 +43222,13 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
42937
43222
|
notProbeRun()
|
|
42938
43223
|
];
|
|
42939
43224
|
const targetFilters = request.query.runId ? [...baseFilters, eq42(siteAuditSnapshots.runId, request.query.runId)] : baseFilters;
|
|
42940
|
-
const latest = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq42(siteAuditSnapshots.runId, runs.id)).where(and33(...targetFilters)).orderBy(
|
|
43225
|
+
const latest = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq42(siteAuditSnapshots.runId, runs.id)).where(and33(...targetFilters)).orderBy(desc19(siteAuditSnapshots.createdAt)).limit(1).get();
|
|
42941
43226
|
if (!latest) {
|
|
42942
43227
|
if (request.query.runId) throw notFound("Site audit run", request.query.runId);
|
|
42943
43228
|
return emptyScore(project.name);
|
|
42944
43229
|
}
|
|
42945
43230
|
const snap = latest.snap;
|
|
42946
|
-
const previous = app.db.select({ snap: siteAuditSnapshots }).from(siteAuditSnapshots).innerJoin(runs, eq42(siteAuditSnapshots.runId, runs.id)).where(and33(...baseFilters, lt4(siteAuditSnapshots.createdAt, snap.createdAt))).orderBy(
|
|
43231
|
+
const previous = app.db.select({ snap: siteAuditSnapshots }).from(siteAuditSnapshots).innerJoin(runs, eq42(siteAuditSnapshots.runId, runs.id)).where(and33(...baseFilters, lt4(siteAuditSnapshots.createdAt, snap.createdAt))).orderBy(desc19(siteAuditSnapshots.createdAt)).limit(1).get()?.snap ?? null;
|
|
42947
43232
|
const deltaScore = previous ? snap.aggregateScore - previous.aggregateScore : null;
|
|
42948
43233
|
const trend = deltaScore == null ? null : deltaScore > 0 ? SiteAuditTrendDirections.up : deltaScore < 0 ? SiteAuditTrendDirections.down : SiteAuditTrendDirections.flat;
|
|
42949
43234
|
return {
|
|
@@ -42976,7 +43261,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
42976
43261
|
notProbeRun()
|
|
42977
43262
|
];
|
|
42978
43263
|
if (request.query.runId) targetFilters.push(eq42(siteAuditSnapshots.runId, request.query.runId));
|
|
42979
|
-
const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq42(siteAuditSnapshots.runId, runs.id)).where(and33(...targetFilters)).orderBy(
|
|
43264
|
+
const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq42(siteAuditSnapshots.runId, runs.id)).where(and33(...targetFilters)).orderBy(desc19(siteAuditSnapshots.createdAt)).limit(1).get();
|
|
42980
43265
|
if (!latest && request.query.runId) {
|
|
42981
43266
|
throw notFound("Site audit run", request.query.runId);
|
|
42982
43267
|
}
|
|
@@ -42991,7 +43276,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
42991
43276
|
const total = totalRow?.value ?? 0;
|
|
42992
43277
|
const limit = parsePositiveInt(request.query.limit, 100, 500);
|
|
42993
43278
|
const offset = parsePositiveInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER);
|
|
42994
|
-
const orderBy = request.query.sort === "score-desc" ?
|
|
43279
|
+
const orderBy = request.query.sort === "score-desc" ? desc19(siteAuditPages.overallScore) : request.query.sort === "url" ? asc8(siteAuditPages.url) : asc8(siteAuditPages.overallScore);
|
|
42995
43280
|
const rows = app.db.select().from(siteAuditPages).where(where).orderBy(orderBy).limit(limit).offset(offset).all();
|
|
42996
43281
|
const pages = rows.map((row) => ({
|
|
42997
43282
|
url: row.url,
|
|
@@ -43015,7 +43300,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
43015
43300
|
eq42(runs.kind, RunKinds["site-audit"]),
|
|
43016
43301
|
inArray14(runs.status, SURFACEABLE_STATUSES),
|
|
43017
43302
|
notProbeRun()
|
|
43018
|
-
)).orderBy(
|
|
43303
|
+
)).orderBy(desc19(siteAuditSnapshots.createdAt)).limit(limit).all();
|
|
43019
43304
|
return { project: project.name, points: rows.reverse() };
|
|
43020
43305
|
});
|
|
43021
43306
|
app.post("/projects/:name/technical-aeo/runs", async (request) => {
|
|
@@ -43052,7 +43337,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
43052
43337
|
|
|
43053
43338
|
// ../api-routes/src/research.ts
|
|
43054
43339
|
import crypto33 from "crypto";
|
|
43055
|
-
import { and as and34, desc as
|
|
43340
|
+
import { and as and34, desc as desc20, eq as eq43 } from "drizzle-orm";
|
|
43056
43341
|
var sameLocation = (a, b) => a.label === b.label && a.city === b.city && a.region === b.region && a.country === b.country && a.timezone === b.timezone;
|
|
43057
43342
|
async function researchRoutes(app, opts) {
|
|
43058
43343
|
app.post("/projects/:name/research/runs", async (request, reply) => {
|
|
@@ -43103,7 +43388,7 @@ async function researchRoutes(app, opts) {
|
|
|
43103
43388
|
const project = resolveProject(app.db, request.params.name);
|
|
43104
43389
|
const requested = Number.parseInt(request.query.limit ?? "", 10);
|
|
43105
43390
|
const limit = Number.isInteger(requested) && requested > 0 ? Math.min(requested, 100) : 20;
|
|
43106
|
-
const runs2 = app.db.select().from(researchRuns).where(eq43(researchRuns.projectId, project.id)).orderBy(
|
|
43391
|
+
const runs2 = app.db.select().from(researchRuns).where(eq43(researchRuns.projectId, project.id)).orderBy(desc20(researchRuns.createdAt)).limit(limit).all().map(serializeRun);
|
|
43107
43392
|
return { runs: runs2 };
|
|
43108
43393
|
});
|
|
43109
43394
|
app.get("/projects/:name/research/runs/:runId", async (request) => {
|
|
@@ -43719,7 +44004,7 @@ var IntelligenceService = class {
|
|
|
43719
44004
|
// intelligence window.
|
|
43720
44005
|
ne6(runs.trigger, RunTriggers.probe)
|
|
43721
44006
|
)
|
|
43722
|
-
).orderBy(
|
|
44007
|
+
).orderBy(desc21(runs.finishedAt), desc21(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
|
|
43723
44008
|
if (recentRuns.length === 0) {
|
|
43724
44009
|
log.info("intelligence.skip", { runId, reason: "no completed runs" });
|
|
43725
44010
|
return null;
|
|
@@ -43841,10 +44126,10 @@ var IntelligenceService = class {
|
|
|
43841
44126
|
buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
|
|
43842
44127
|
const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and35(eq44(gbpDailyMetrics.projectId, projectId), eq44(gbpDailyMetrics.locationName, locationName))).all();
|
|
43843
44128
|
const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and35(eq44(gbpPlaceActions.projectId, projectId), eq44(gbpPlaceActions.locationName, locationName))).all();
|
|
43844
|
-
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and35(eq44(gbpLodgingSnapshots.projectId, projectId), eq44(gbpLodgingSnapshots.locationName, locationName))).orderBy(
|
|
44129
|
+
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and35(eq44(gbpLodgingSnapshots.projectId, projectId), eq44(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc21(gbpLodgingSnapshots.syncedAt)).limit(1).get();
|
|
43845
44130
|
const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and35(eq44(gbpLocations.projectId, projectId), eq44(gbpLocations.locationName, locationName))).get();
|
|
43846
44131
|
const descriptionMissing = !(ownerRow?.description ?? "").trim();
|
|
43847
|
-
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and35(eq44(gbpPlaceDetails.projectId, projectId), eq44(gbpPlaceDetails.locationName, locationName))).orderBy(
|
|
44132
|
+
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and35(eq44(gbpPlaceDetails.projectId, projectId), eq44(gbpPlaceDetails.locationName, locationName))).orderBy(desc21(gbpPlaceDetails.syncedAt)).limit(1).get();
|
|
43848
44133
|
const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
|
|
43849
44134
|
const summary = buildGbpSummary({
|
|
43850
44135
|
locationName,
|
|
@@ -44197,7 +44482,7 @@ var IntelligenceService = class {
|
|
|
44197
44482
|
// Defensive — see top of file.
|
|
44198
44483
|
ne6(runs.trigger, RunTriggers.probe)
|
|
44199
44484
|
)
|
|
44200
|
-
).orderBy(
|
|
44485
|
+
).orderBy(desc21(runs.createdAt), desc21(runs.id)).limit((RECURRENCE_LOOKBACK_RUNS + 1) * ROWS_PER_GROUP_BUDGET).all();
|
|
44201
44486
|
const recentGroups = groupRunsByCreatedAt(recentRunRows);
|
|
44202
44487
|
const recentRunIds = [];
|
|
44203
44488
|
const recentRunIdToCreatedAt = /* @__PURE__ */ new Map();
|