@canonry/canonry 7.5.1 → 7.6.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/canonry-cli.md +8 -0
- package/assets/assets/{AuditHistoryPanel-B5aLMnWE.js → AuditHistoryPanel-DZbPVuDn.js} +1 -1
- package/assets/assets/{BacklinksPage-Biq1jrqe.js → BacklinksPage-6iPxcQdF.js} +1 -1
- package/assets/assets/{HistoryPage-CGGkAgnz.js → HistoryPage-DQ4gqs5s.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-BwyWGGBg.js → MeasurementPropertyPage-X4EGa3a5.js} +1 -1
- package/assets/assets/{ProjectPage-DEnKyD3e.js → ProjectPage-qvbLROZz.js} +1 -1
- package/assets/assets/{RunsPage-DNBn0Rau.js → RunsPage-DBfy79uf.js} +1 -1
- package/assets/assets/{SettingsPage-D3m-BLuf.js → SettingsPage-BlNafKGd.js} +1 -1
- package/assets/assets/{SiteHealthSection-CPMu1l-l.js → SiteHealthSection-79l2PnfR.js} +3 -3
- package/assets/assets/{TrafficPage-BCK_V__i.js → TrafficPage-CPZWDxjp.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DaCehUm8.js → TrafficSourceDetailPage-BIhpWiRg.js} +1 -1
- package/assets/assets/{extract-error-message-CqBLzzuR.js → extract-error-message-C9XX_kMH.js} +1 -1
- package/assets/assets/{index-C2X_UARl.js → index-CUQtRdIf.js} +20 -20
- package/assets/assets/{react-sigma_core.esm.min-BvO4SZKT.js → react-sigma_core.esm.min-FTRP6jVQ.js} +1 -1
- package/assets/assets/{v2-overview-adapter-CgDChBa5.js → v2-overview-adapter-DEuH0zoM.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-56YOI7QX.js → chunk-7FJZCG7A.js} +2 -2
- package/dist/{chunk-VVEMJCC6.js → chunk-B7IT47FE.js} +4 -2
- package/dist/{chunk-HAWCV4SU.js → chunk-BLHPFAR6.js} +22 -10
- package/dist/{chunk-JTQ4KFIR.js → chunk-FRSGZYQZ.js} +427 -277
- package/dist/{chunk-KJIXDPYH.js → chunk-HXAGDOYV.js} +3 -3
- package/dist/{chunk-Y7K5NMNV.js → chunk-P72CWNTU.js} +2 -2
- package/dist/{chunk-RVM6QJQT.js → chunk-WO7XJJHH.js} +5508 -5464
- package/dist/cli.js +24 -12
- package/dist/{demo-server-V3DDLXND.js → demo-server-Z7NM6DJT.js} +4 -4
- package/dist/index.js +6 -6
- package/dist/{intelligence-service-MZVPWIXL.js → intelligence-service-P7AOOXLZ.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +8 -8
|
@@ -105,6 +105,8 @@ import {
|
|
|
105
105
|
POOLED_RUN_ID_LIMIT,
|
|
106
106
|
PROJECTS_WRITE_SCOPE,
|
|
107
107
|
PROJECT_OVERVIEW_QUERY_CLASS_SCOPE,
|
|
108
|
+
PROVIDER_ACCOUNT_FAILURE_STREAK,
|
|
109
|
+
PROVIDER_ACCOUNT_RETRY_HOURS,
|
|
108
110
|
ProviderDispatchModes,
|
|
109
111
|
READ_ONLY_SCOPE,
|
|
110
112
|
RESEARCH_RUN_SCOPE,
|
|
@@ -447,6 +449,7 @@ import {
|
|
|
447
449
|
isBrowserProvider,
|
|
448
450
|
isLocationRedirectStatus,
|
|
449
451
|
isNegativeReviewRating,
|
|
452
|
+
isProviderAccountFailure,
|
|
450
453
|
isReadOnlyKey,
|
|
451
454
|
isRetryableHttpError,
|
|
452
455
|
isStrictSemver,
|
|
@@ -615,6 +618,7 @@ import {
|
|
|
615
618
|
providerDispatchModeSchema,
|
|
616
619
|
providerError,
|
|
617
620
|
providerSummaryEntryDtoSchema,
|
|
621
|
+
providersFailing,
|
|
618
622
|
queryDtoSchema,
|
|
619
623
|
queryGenerateRequestSchema,
|
|
620
624
|
queryTrackingCommitRequestSchema,
|
|
@@ -796,10 +800,10 @@ import {
|
|
|
796
800
|
wordpressSchemaDeployResultDtoSchema,
|
|
797
801
|
wordpressSchemaStatusResultDtoSchema,
|
|
798
802
|
wordpressStatusDtoSchema
|
|
799
|
-
} from "./chunk-
|
|
803
|
+
} from "./chunk-WO7XJJHH.js";
|
|
800
804
|
|
|
801
805
|
// src/intelligence-service.ts
|
|
802
|
-
import { eq as eq84, desc as
|
|
806
|
+
import { eq as eq84, desc as desc38, asc as asc15, and as and71, ne as ne15, or as or20, inArray as inArray34, gte as gte22, lte as lte20, isNull as isNull16, sql as sql31, exists as exists2 } from "drizzle-orm";
|
|
803
807
|
|
|
804
808
|
// ../db/src/client.ts
|
|
805
809
|
import { mkdirSync } from "fs";
|
|
@@ -1210,6 +1214,9 @@ var runs = sqliteTable("runs", {
|
|
|
1210
1214
|
index("idx_runs_status").on(table.status),
|
|
1211
1215
|
index("idx_runs_source").on(table.sourceId),
|
|
1212
1216
|
index("idx_runs_measurement_plan").on(table.projectId, table.measurementPlanVersionId, table.createdAt),
|
|
1217
|
+
// A project's newest runs of one kind: run admission reads ten of them on
|
|
1218
|
+
// every queue (`providerAccountRefusal`), as does the failure-streak count.
|
|
1219
|
+
index("idx_runs_project_kind_created").on(table.projectId, table.kind, table.createdAt),
|
|
1213
1220
|
foreignKey({
|
|
1214
1221
|
name: "runs_measurement_plan_version_fk",
|
|
1215
1222
|
columns: [table.projectId, table.measurementPlanVersionId],
|
|
@@ -8165,6 +8172,15 @@ var MIGRATION_VERSIONS = [
|
|
|
8165
8172
|
statements: [
|
|
8166
8173
|
`ALTER TABLE projects ADD COLUMN site_audit_max_pages INTEGER`
|
|
8167
8174
|
]
|
|
8175
|
+
},
|
|
8176
|
+
{
|
|
8177
|
+
// Run admission reads a project's ten newest runs of one kind on every
|
|
8178
|
+
// queue; without this it sorted every run the project ever had.
|
|
8179
|
+
version: 170,
|
|
8180
|
+
name: "runs-project-kind-created-index",
|
|
8181
|
+
statements: [
|
|
8182
|
+
`CREATE INDEX IF NOT EXISTS idx_runs_project_kind_created ON runs(project_id, kind, created_at)`
|
|
8183
|
+
]
|
|
8168
8184
|
}
|
|
8169
8185
|
];
|
|
8170
8186
|
var AERO_LEDGER_REBUILDS = [
|
|
@@ -15288,7 +15304,7 @@ function pruneProviderDispatchModes(modes, providers, revisionProviders) {
|
|
|
15288
15304
|
|
|
15289
15305
|
// ../api-routes/src/run-queue.ts
|
|
15290
15306
|
import crypto10 from "crypto";
|
|
15291
|
-
import { and as and10, eq as eq16, or as or4 } from "drizzle-orm";
|
|
15307
|
+
import { and as and10, desc as desc7, eq as eq16, gt as gt3, inArray as inArray6, or as or4 } from "drizzle-orm";
|
|
15292
15308
|
|
|
15293
15309
|
// ../api-routes/src/measurement-report-adapter.ts
|
|
15294
15310
|
import { and as and8, desc as desc5, eq as eq14, gte as gte2, inArray as inArray5, isNull as isNull4, lt as lt4, lte as lte5, ne as ne4 } from "drizzle-orm";
|
|
@@ -16907,6 +16923,92 @@ function resolveQueueDispatch(tx, params, stamp) {
|
|
|
16907
16923
|
}
|
|
16908
16924
|
return resolution;
|
|
16909
16925
|
}
|
|
16926
|
+
function providersARunWouldCall(roster, runnable) {
|
|
16927
|
+
const listed = normalizeProviders(roster);
|
|
16928
|
+
if (runnable == null) return listed;
|
|
16929
|
+
const available = new Set(normalizeProviders(runnable));
|
|
16930
|
+
return listed.filter((provider) => available.has(provider));
|
|
16931
|
+
}
|
|
16932
|
+
var PROVIDER_ACCOUNT_LOOKBACK = PROVIDER_ACCOUNT_FAILURE_STREAK * 5;
|
|
16933
|
+
function providerSettingsChangeCouldFix(action, diff) {
|
|
16934
|
+
if (action === "provider.created") return true;
|
|
16935
|
+
try {
|
|
16936
|
+
const parsed = JSON.parse(diff ?? "null");
|
|
16937
|
+
if (!parsed) return false;
|
|
16938
|
+
if (parsed.apiKeyRotated) return true;
|
|
16939
|
+
const before = parsed.before ?? {};
|
|
16940
|
+
const after = parsed.after ?? {};
|
|
16941
|
+
return before.configured !== after.configured || before.model !== after.model || before.baseUrl !== after.baseUrl;
|
|
16942
|
+
} catch {
|
|
16943
|
+
return false;
|
|
16944
|
+
}
|
|
16945
|
+
}
|
|
16946
|
+
function providerAccountRefusal(db, params) {
|
|
16947
|
+
if (params.force || params.trigger === RunTriggers.probe) return null;
|
|
16948
|
+
const recent = db.select({
|
|
16949
|
+
id: runs.id,
|
|
16950
|
+
status: runs.status,
|
|
16951
|
+
error: runs.error,
|
|
16952
|
+
createdAt: runs.createdAt,
|
|
16953
|
+
finishedAt: runs.finishedAt
|
|
16954
|
+
}).from(runs).where(and10(
|
|
16955
|
+
eq16(runs.projectId, params.projectId),
|
|
16956
|
+
eq16(runs.kind, RunKinds["answer-visibility"]),
|
|
16957
|
+
inArray6(runs.status, [RunStatuses.completed, RunStatuses.partial, RunStatuses.failed, RunStatuses.cancelled])
|
|
16958
|
+
)).orderBy(desc7(runs.createdAt), desc7(runs.id)).limit(PROVIDER_ACCOUNT_LOOKBACK).all().map((run) => ({ ...run, providers: parseRunError(run.error)?.providers ?? {} }));
|
|
16959
|
+
const withAccountFailure = recent.filter((run) => Object.values(run.providers).some((entry) => isProviderAccountFailure(entry.code)));
|
|
16960
|
+
if (withAccountFailure.length < PROVIDER_ACCOUNT_FAILURE_STREAK) return null;
|
|
16961
|
+
const calling = normalizeProviders(params.providers());
|
|
16962
|
+
if (calling.length === 0) return null;
|
|
16963
|
+
const answered2 = (runId, provider) => db.select({ id: querySnapshots.id }).from(querySnapshots).where(and10(eq16(querySnapshots.runId, runId), eq16(querySnapshots.provider, provider))).limit(1).get() !== void 0;
|
|
16964
|
+
const streaks = /* @__PURE__ */ new Map();
|
|
16965
|
+
for (const provider of calling) {
|
|
16966
|
+
let count4 = 0;
|
|
16967
|
+
let newest2 = null;
|
|
16968
|
+
let oldest = null;
|
|
16969
|
+
let code = null;
|
|
16970
|
+
for (const run of recent) {
|
|
16971
|
+
const entry = run.providers[provider];
|
|
16972
|
+
if (!entry) {
|
|
16973
|
+
if (run.status !== RunStatuses.failed && answered2(run.id, provider)) return null;
|
|
16974
|
+
continue;
|
|
16975
|
+
}
|
|
16976
|
+
if (!isProviderAccountFailure(entry.code)) return null;
|
|
16977
|
+
newest2 ??= run;
|
|
16978
|
+
code ??= entry.code;
|
|
16979
|
+
oldest = run;
|
|
16980
|
+
count4 += 1;
|
|
16981
|
+
if (count4 === PROVIDER_ACCOUNT_FAILURE_STREAK) break;
|
|
16982
|
+
}
|
|
16983
|
+
if (count4 < PROVIDER_ACCOUNT_FAILURE_STREAK) return null;
|
|
16984
|
+
streaks.set(provider, { newest: newest2, oldest, code });
|
|
16985
|
+
}
|
|
16986
|
+
const finished = (run) => Date.parse(run.finishedAt ?? run.createdAt);
|
|
16987
|
+
const newest = [...streaks.values()].map((streak) => streak.newest).sort((a, b) => finished(b) - finished(a))[0];
|
|
16988
|
+
const retryAfterMs = finished(newest) + PROVIDER_ACCOUNT_RETRY_HOURS * 36e5;
|
|
16989
|
+
if (Date.parse(params.now) >= retryAfterMs) return null;
|
|
16990
|
+
const since = [...streaks.values()].map((streak) => streak.oldest.createdAt).sort()[0];
|
|
16991
|
+
const settingsChanges = db.select({ entityId: auditLog.entityId, action: auditLog.action, diff: auditLog.diff, createdAt: auditLog.createdAt }).from(auditLog).where(and10(eq16(auditLog.entityType, "provider"), inArray6(auditLog.entityId, calling), gt3(auditLog.createdAt, since))).all();
|
|
16992
|
+
const fixedSince = settingsChanges.some((change) => {
|
|
16993
|
+
const streak = streaks.get(change.entityId ?? "");
|
|
16994
|
+
return streak !== void 0 && change.createdAt > streak.oldest.createdAt && providerSettingsChangeCouldFix(change.action, change.diff);
|
|
16995
|
+
});
|
|
16996
|
+
if (fixedSince) return null;
|
|
16997
|
+
return {
|
|
16998
|
+
consecutiveRuns: PROVIDER_ACCOUNT_FAILURE_STREAK,
|
|
16999
|
+
latestRunId: newest.id,
|
|
17000
|
+
since,
|
|
17001
|
+
retryAfter: new Date(retryAfterMs).toISOString(),
|
|
17002
|
+
providers: Object.fromEntries(calling.map((provider) => [provider, streaks.get(provider).code]))
|
|
17003
|
+
};
|
|
17004
|
+
}
|
|
17005
|
+
function providersFailingError(projectName, failures) {
|
|
17006
|
+
const named = Object.entries(failures.providers).map(([provider, code]) => `${provider} (${code})`).join(", ");
|
|
17007
|
+
return providersFailing(
|
|
17008
|
+
`Not starting a run for '${projectName}': every provider it would call failed on its account (a rejected key, denied access, or no credit left) in each of its last ${failures.consecutiveRuns} runs: ${named}. Fix it in the provider's console or settings. Saving a new key, model or endpoint for the provider (canonry settings provider <name>) lets the next run through; otherwise one run is let through after ${failures.retryAfter}. Pass force (canonry run --force) to run now.`,
|
|
17009
|
+
{ projectName, ...failures }
|
|
17010
|
+
);
|
|
17011
|
+
}
|
|
16910
17012
|
function queueRunIfProjectIdle(db, params) {
|
|
16911
17013
|
const createdAt = params.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
16912
17014
|
const kind = params.kind ?? "answer-visibility";
|
|
@@ -16947,6 +17049,17 @@ function queueRunIfProjectIdle(db, params) {
|
|
|
16947
17049
|
}
|
|
16948
17050
|
const current = activeRun();
|
|
16949
17051
|
if (current) return { conflict: true, activeRunId: current.id };
|
|
17052
|
+
const refused = kind === RunKinds["answer-visibility"] ? providerAccountRefusal(tx, {
|
|
17053
|
+
projectId: params.projectId,
|
|
17054
|
+
trigger: stamp?.scope ? RunTriggers.probe : trigger,
|
|
17055
|
+
force: params.force ?? false,
|
|
17056
|
+
now: createdAt,
|
|
17057
|
+
providers: () => providersARunWouldCall(
|
|
17058
|
+
stamp?.identity.providers ?? providerRoster(tx, params),
|
|
17059
|
+
params.runnableProviders
|
|
17060
|
+
)
|
|
17061
|
+
}) : null;
|
|
17062
|
+
if (refused) return { conflict: false, refused };
|
|
16950
17063
|
const scoped = params.queries != null || stamp?.scope != null;
|
|
16951
17064
|
const basket = scoped ? null : ensureCurrentQueryBasketRevision(tx, params.projectId, createdAt);
|
|
16952
17065
|
tx.insert(runs).values({
|
|
@@ -16978,7 +17091,7 @@ function queueRunIfProjectIdle(db, params) {
|
|
|
16978
17091
|
}
|
|
16979
17092
|
|
|
16980
17093
|
// ../api-routes/src/provider-batches.ts
|
|
16981
|
-
import { and as and11, asc as asc2, eq as eq17, inArray as
|
|
17094
|
+
import { and as and11, asc as asc2, eq as eq17, inArray as inArray7 } from "drizzle-orm";
|
|
16982
17095
|
function formatProviderBatchSummary(row) {
|
|
16983
17096
|
return {
|
|
16984
17097
|
id: row.id,
|
|
@@ -17001,10 +17114,10 @@ function runHadProviderBatch(db, runId) {
|
|
|
17001
17114
|
return db.select({ id: providerBatches.id }).from(providerBatches).where(eq17(providerBatches.runId, runId)).limit(1).get() !== void 0;
|
|
17002
17115
|
}
|
|
17003
17116
|
function hasOutstandingProviderBatch(db, runId) {
|
|
17004
|
-
return db.select({ id: providerBatches.id }).from(providerBatches).where(and11(eq17(providerBatches.runId, runId),
|
|
17117
|
+
return db.select({ id: providerBatches.id }).from(providerBatches).where(and11(eq17(providerBatches.runId, runId), inArray7(providerBatches.status, [...OUTSTANDING_PROVIDER_BATCH_STATUSES]))).limit(1).get() !== void 0;
|
|
17005
17118
|
}
|
|
17006
17119
|
function readProjectRunsWithOutstandingProviderBatch(db, projectId) {
|
|
17007
|
-
return db.selectDistinct({ runId: providerBatches.runId }).from(providerBatches).where(and11(eq17(providerBatches.projectId, projectId),
|
|
17120
|
+
return db.selectDistinct({ runId: providerBatches.runId }).from(providerBatches).where(and11(eq17(providerBatches.projectId, projectId), inArray7(providerBatches.status, [...OUTSTANDING_PROVIDER_BATCH_STATUSES]))).orderBy(asc2(providerBatches.runId)).all().map((row) => row.runId);
|
|
17008
17121
|
}
|
|
17009
17122
|
|
|
17010
17123
|
// ../api-routes/src/projects.ts
|
|
@@ -17571,13 +17684,13 @@ function aliasArraysEqual(a, b) {
|
|
|
17571
17684
|
|
|
17572
17685
|
// ../api-routes/src/queries.ts
|
|
17573
17686
|
import crypto13 from "crypto";
|
|
17574
|
-
import { and as and14, eq as eq20, inArray as
|
|
17687
|
+
import { and as and14, eq as eq20, inArray as inArray9, sql as sql8 } from "drizzle-orm";
|
|
17575
17688
|
|
|
17576
17689
|
// ../api-routes/src/query-replace.ts
|
|
17577
17690
|
import crypto12 from "crypto";
|
|
17578
|
-
import { and as and13, eq as eq19, inArray as
|
|
17691
|
+
import { and as and13, eq as eq19, inArray as inArray8, isNull as isNull5 } from "drizzle-orm";
|
|
17579
17692
|
function preserveSnapshotQueryText(tx, projectId, queryIds) {
|
|
17580
|
-
const candidates = queryIds && queryIds.length > 0 ? tx.select({ id: queries.id, text: queries.query }).from(queries).where(and13(eq19(queries.projectId, projectId),
|
|
17693
|
+
const candidates = queryIds && queryIds.length > 0 ? tx.select({ id: queries.id, text: queries.query }).from(queries).where(and13(eq19(queries.projectId, projectId), inArray8(queries.id, queryIds))).all() : tx.select({ id: queries.id, text: queries.query }).from(queries).where(eq19(queries.projectId, projectId)).all();
|
|
17581
17694
|
for (const q of candidates) {
|
|
17582
17695
|
tx.update(querySnapshots).set({ queryText: q.text }).where(and13(eq19(querySnapshots.queryId, q.id), isNull5(querySnapshots.queryText))).run();
|
|
17583
17696
|
}
|
|
@@ -17640,7 +17753,7 @@ function assertNoActivePlanlessSweep(tx, scope) {
|
|
|
17640
17753
|
const activeRun = tx.select({ id: runs.id }).from(runs).where(and13(
|
|
17641
17754
|
eq19(runs.projectId, scope.projectId),
|
|
17642
17755
|
eq19(runs.kind, RunKinds["answer-visibility"]),
|
|
17643
|
-
|
|
17756
|
+
inArray8(runs.status, [RunStatuses.queued, RunStatuses.running]),
|
|
17644
17757
|
isNull5(runs.measurementPlanVersionId)
|
|
17645
17758
|
)).get();
|
|
17646
17759
|
if (activeRun) throw runInProgress(scope.projectName, RunKinds["answer-visibility"], activeRun.id);
|
|
@@ -17693,11 +17806,11 @@ function replaceProjectQueries(tx, projectId, incomingTexts, now) {
|
|
|
17693
17806
|
for (const dup of diff.duplicates) {
|
|
17694
17807
|
tx.update(querySnapshots).set({ queryId: dup.keptId }).where(eq19(querySnapshots.queryId, dup.id)).run();
|
|
17695
17808
|
}
|
|
17696
|
-
tx.delete(queries).where(
|
|
17809
|
+
tx.delete(queries).where(inArray8(queries.id, diff.duplicates.map((d) => d.id))).run();
|
|
17697
17810
|
}
|
|
17698
17811
|
if (diff.removed.length > 0) {
|
|
17699
17812
|
const removedIds = diff.removed.map((r) => r.id);
|
|
17700
|
-
tx.delete(queries).where(
|
|
17813
|
+
tx.delete(queries).where(inArray8(queries.id, removedIds)).run();
|
|
17701
17814
|
}
|
|
17702
17815
|
for (const keptRow of diff.kept) {
|
|
17703
17816
|
if (keptRow.currentText !== keptRow.incomingText) {
|
|
@@ -17792,9 +17905,9 @@ async function queryRoutes(app, opts) {
|
|
|
17792
17905
|
let snapshotsDetached = 0;
|
|
17793
17906
|
let affectedQueries = 0;
|
|
17794
17907
|
if (removedIds.length > 0) {
|
|
17795
|
-
const snapshotCount = app.db.select({ n: sql8`count(*)` }).from(querySnapshots).where(
|
|
17908
|
+
const snapshotCount = app.db.select({ n: sql8`count(*)` }).from(querySnapshots).where(inArray9(querySnapshots.queryId, removedIds)).get();
|
|
17796
17909
|
snapshotsDetached = snapshotCount?.n ?? 0;
|
|
17797
|
-
const distinctAffected = app.db.select({ n: sql8`count(distinct ${querySnapshots.queryId})` }).from(querySnapshots).where(
|
|
17910
|
+
const distinctAffected = app.db.select({ n: sql8`count(distinct ${querySnapshots.queryId})` }).from(querySnapshots).where(inArray9(querySnapshots.queryId, removedIds)).get();
|
|
17798
17911
|
affectedQueries = distinctAffected?.n ?? 0;
|
|
17799
17912
|
}
|
|
17800
17913
|
return reply.send({
|
|
@@ -18244,7 +18357,7 @@ function parseBody(schema, value, message) {
|
|
|
18244
18357
|
}
|
|
18245
18358
|
|
|
18246
18359
|
// ../api-routes/src/competitor-landscape.ts
|
|
18247
|
-
import { and as and17, desc as
|
|
18360
|
+
import { and as and17, desc as desc8, eq as eq24, gte as gte3, inArray as inArray10, isNull as isNull6 } from "drizzle-orm";
|
|
18248
18361
|
|
|
18249
18362
|
// ../api-routes/src/mention-share-inputs.ts
|
|
18250
18363
|
import { eq as eq22 } from "drizzle-orm";
|
|
@@ -19057,11 +19170,11 @@ function latestSweepRuns(db, projectId) {
|
|
|
19057
19170
|
const candidates = db.select().from(runs).where(and17(
|
|
19058
19171
|
eq24(runs.projectId, projectId),
|
|
19059
19172
|
eq24(runs.kind, RunKinds["answer-visibility"]),
|
|
19060
|
-
|
|
19173
|
+
inArray10(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
19061
19174
|
notProbeRun(),
|
|
19062
19175
|
// A scoped spot check is never the latest sweep.
|
|
19063
19176
|
isNull6(runs.measurementScope)
|
|
19064
|
-
)).orderBy(
|
|
19177
|
+
)).orderBy(desc8(runs.createdAt), desc8(runs.id)).all();
|
|
19065
19178
|
for (const group of groupRunsByCreatedAt(candidates)) {
|
|
19066
19179
|
const whole = group.filter((run) => measurementRunCompleteness(db, run.id).complete);
|
|
19067
19180
|
if (whole.length > 0) return whole;
|
|
@@ -19086,8 +19199,8 @@ function readCompetitorLandscape(app, projectName, query, selection) {
|
|
|
19086
19199
|
const candidateRuns = app.db.select().from(runs).where(and17(
|
|
19087
19200
|
eq24(runs.projectId, project.id),
|
|
19088
19201
|
eq24(runs.kind, RunKinds["answer-visibility"]),
|
|
19089
|
-
selection ?
|
|
19090
|
-
latestRunIds ?
|
|
19202
|
+
selection ? inArray10(runs.id, [...selection.runIds]) : void 0,
|
|
19203
|
+
latestRunIds ? inArray10(runs.id, latestRunIds) : filters.runId ? eq24(runs.id, filters.runId) : void 0,
|
|
19091
19204
|
cutoff ? gte3(runs.createdAt, cutoff) : void 0
|
|
19092
19205
|
)).all();
|
|
19093
19206
|
const advanced = filters.groupKey || filters.scope === "all-markets" ? resolveAdvancedScope(app, project.id, filters.groupKey ? "group" : "all-markets", filters.groupKey, candidateRuns) : null;
|
|
@@ -19115,7 +19228,7 @@ function readCompetitorLandscape(app, projectName, query, selection) {
|
|
|
19115
19228
|
location: querySnapshots.location,
|
|
19116
19229
|
measurementExecutionId: querySnapshots.measurementExecutionId,
|
|
19117
19230
|
createdAt: querySnapshots.createdAt
|
|
19118
|
-
}).from(querySnapshots).where(
|
|
19231
|
+
}).from(querySnapshots).where(inArray10(querySnapshots.runId, candidateRuns.map((run) => run.id))).all();
|
|
19119
19232
|
const runById = new Map(candidateRuns.map((run) => [run.id, run]));
|
|
19120
19233
|
const selectedIds = selection?.snapshotIds ? new Set(selection.snapshotIds) : null;
|
|
19121
19234
|
const inScope = allSnapshots.filter((snapshot) => (!selectedIds || selectedIds.has(snapshot.id)) && snapshotMatchesFilters({
|
|
@@ -19299,7 +19412,7 @@ function frozenRunScopes(db, projectId, kind, groupKey, candidateRuns) {
|
|
|
19299
19412
|
const planVersionIds = [...new Set(candidateRuns.map((run) => run.measurementPlanVersionId).filter((id) => typeof id === "string" && id.length > 0))];
|
|
19300
19413
|
const historicalVersions = planVersionIds.length === 0 ? [] : db.select().from(measurementPlanVersions).where(and17(
|
|
19301
19414
|
eq24(measurementPlanVersions.projectId, projectId),
|
|
19302
|
-
|
|
19415
|
+
inArray10(measurementPlanVersions.id, planVersionIds)
|
|
19303
19416
|
)).all();
|
|
19304
19417
|
const frozenByVersionId = new Map(historicalVersions.map((version) => [
|
|
19305
19418
|
version.id,
|
|
@@ -19437,12 +19550,12 @@ function mergePins(...collections) {
|
|
|
19437
19550
|
|
|
19438
19551
|
// ../api-routes/src/runs.ts
|
|
19439
19552
|
import crypto15 from "crypto";
|
|
19440
|
-
import { and as and19, eq as eq26, asc as asc3, desc as
|
|
19553
|
+
import { and as and19, eq as eq26, asc as asc3, desc as desc10, inArray as inArray12, or as or6, sql as sql10 } from "drizzle-orm";
|
|
19441
19554
|
import { gte as gte4 } from "drizzle-orm";
|
|
19442
19555
|
|
|
19443
19556
|
// ../api-routes/src/run-fill.ts
|
|
19444
19557
|
import crypto14 from "crypto";
|
|
19445
|
-
import { and as and18, desc as
|
|
19558
|
+
import { and as and18, desc as desc9, eq as eq25, gt as gt4, inArray as inArray11, isNull as isNull7, ne as ne5, or as or5, sql as sql9 } from "drizzle-orm";
|
|
19446
19559
|
var ACTIVE_STATUSES = ["queued", "running"];
|
|
19447
19560
|
function normalizeProvider(value) {
|
|
19448
19561
|
return value.trim().toLocaleLowerCase("en");
|
|
@@ -19470,12 +19583,12 @@ function newerFullSweep(db, run) {
|
|
|
19470
19583
|
ne5(runs.trigger, RunTriggers.probe),
|
|
19471
19584
|
isNull7(runs.measurementScope),
|
|
19472
19585
|
isNull7(runs.queries),
|
|
19473
|
-
|
|
19586
|
+
gt4(runs.createdAt, run.createdAt),
|
|
19474
19587
|
or5(
|
|
19475
|
-
|
|
19588
|
+
inArray11(runs.status, ["queued", "running", "completed", "partial"]),
|
|
19476
19589
|
sql9`EXISTS (SELECT 1 FROM ${querySnapshots} WHERE ${querySnapshots.runId} = ${runs.id})`
|
|
19477
19590
|
)
|
|
19478
|
-
)).orderBy(
|
|
19591
|
+
)).orderBy(desc9(runs.createdAt)).get();
|
|
19479
19592
|
}
|
|
19480
19593
|
function measuredOnRetiredModel(run, provider, missing) {
|
|
19481
19594
|
const recorded = run.measurementExecutionIdentity?.models[provider];
|
|
@@ -19611,16 +19724,16 @@ function evaluateRunFill(db, run, input = {}) {
|
|
|
19611
19724
|
return { kind: "fillable", slots, providers, missing };
|
|
19612
19725
|
}
|
|
19613
19726
|
function latestFillFor(db, runId) {
|
|
19614
|
-
return db.select().from(runFills).where(eq25(runFills.runId, runId)).orderBy(
|
|
19727
|
+
return db.select().from(runFills).where(eq25(runFills.runId, runId)).orderBy(desc9(runFills.createdAt), desc9(runFills.id)).get();
|
|
19615
19728
|
}
|
|
19616
19729
|
function activeFillFor(db, projectId) {
|
|
19617
|
-
return db.select().from(runFills).where(and18(eq25(runFills.projectId, projectId),
|
|
19730
|
+
return db.select().from(runFills).where(and18(eq25(runFills.projectId, projectId), inArray11(runFills.status, [...ACTIVE_STATUSES]))).get();
|
|
19618
19731
|
}
|
|
19619
19732
|
function activeSweepFor(db, projectId) {
|
|
19620
19733
|
return db.select({ id: runs.id }).from(runs).where(and18(
|
|
19621
19734
|
eq25(runs.projectId, projectId),
|
|
19622
19735
|
eq25(runs.kind, RunKinds["answer-visibility"]),
|
|
19623
|
-
|
|
19736
|
+
inArray11(runs.status, [...ACTIVE_STATUSES])
|
|
19624
19737
|
)).get();
|
|
19625
19738
|
}
|
|
19626
19739
|
function readRunCompleteness(db, run, input = {}) {
|
|
@@ -19793,6 +19906,22 @@ async function runRoutes(app, opts) {
|
|
|
19793
19906
|
if (activeRun) {
|
|
19794
19907
|
return { conflict: true, activeRunId: activeRun.id };
|
|
19795
19908
|
}
|
|
19909
|
+
const refused = providerAccountRefusal(tx, {
|
|
19910
|
+
projectId: project.id,
|
|
19911
|
+
trigger,
|
|
19912
|
+
force: body.force ?? false,
|
|
19913
|
+
now,
|
|
19914
|
+
providers: () => {
|
|
19915
|
+
const runnable = opts.getRunnableProviderNames?.();
|
|
19916
|
+
const roster = resolveRunnableProviderSelection({
|
|
19917
|
+
requestedProviders: providers,
|
|
19918
|
+
projectProviders: project.providers,
|
|
19919
|
+
runnableProviders: runnable
|
|
19920
|
+
}).selectedProviders;
|
|
19921
|
+
return providersARunWouldCall(roster, runnable);
|
|
19922
|
+
}
|
|
19923
|
+
});
|
|
19924
|
+
if (refused) return { conflict: false, refused };
|
|
19796
19925
|
const inserted = [];
|
|
19797
19926
|
for (const loc of projectLocations) {
|
|
19798
19927
|
const runId2 = crypto15.randomUUID();
|
|
@@ -19813,6 +19942,7 @@ async function runRoutes(app, opts) {
|
|
|
19813
19942
|
if (result.conflict) {
|
|
19814
19943
|
throw runInProgress(project.name, kind, result.activeRunId);
|
|
19815
19944
|
}
|
|
19945
|
+
if (result.refused) throw providersFailingError(project.name, result.refused);
|
|
19816
19946
|
const results = [];
|
|
19817
19947
|
for (const { runId: runId2, loc } of result.inserted) {
|
|
19818
19948
|
writeAuditLog(app.db, {
|
|
@@ -19843,9 +19973,11 @@ async function runRoutes(app, opts) {
|
|
|
19843
19973
|
providerModels: opts.getEffectiveProviderModels?.(),
|
|
19844
19974
|
measurementScope: body.measurementScope ?? null,
|
|
19845
19975
|
dispatchMode: body.dispatchMode ?? null,
|
|
19846
|
-
batchEligibleProviders: opts.getBatchEligibleProviderNames?.() ?? null
|
|
19976
|
+
batchEligibleProviders: opts.getBatchEligibleProviderNames?.() ?? null,
|
|
19977
|
+
force: body.force ?? false
|
|
19847
19978
|
});
|
|
19848
19979
|
if (queueResult.conflict) throw runInProgress(project.name, kind, queueResult.activeRunId);
|
|
19980
|
+
if (queueResult.refused) throw providersFailingError(project.name, queueResult.refused);
|
|
19849
19981
|
const runId = queueResult.runId;
|
|
19850
19982
|
writeAuditLog(app.db, {
|
|
19851
19983
|
projectId: project.id,
|
|
@@ -19869,14 +20001,14 @@ async function runRoutes(app, opts) {
|
|
|
19869
20001
|
if (kind) filters.push(eq26(runs.kind, kind));
|
|
19870
20002
|
if (status) filters.push(eq26(runs.status, status));
|
|
19871
20003
|
const where = and19(...filters);
|
|
19872
|
-
const rows = limit == null ? app.db.select().from(runs).where(where).orderBy(asc3(runs.createdAt)).all() : app.db.select().from(runs).where(where).orderBy(
|
|
20004
|
+
const rows = limit == null ? app.db.select().from(runs).where(where).orderBy(asc3(runs.createdAt)).all() : app.db.select().from(runs).where(where).orderBy(desc10(runs.createdAt)).limit(limit).all().reverse();
|
|
19873
20005
|
return reply.send(rows.map(formatRun));
|
|
19874
20006
|
});
|
|
19875
20007
|
app.get("/projects/:name/runs/latest", async (request, reply) => {
|
|
19876
20008
|
const project = resolveProject(app.db, request.params.name);
|
|
19877
20009
|
const countRow = app.db.select({ count: sql10`count(*)` }).from(runs).where(and19(eq26(runs.projectId, project.id), notProbeRun())).get();
|
|
19878
20010
|
const totalRuns = countRow?.count ?? 0;
|
|
19879
|
-
const latestRun = app.db.select().from(runs).where(and19(eq26(runs.projectId, project.id), notProbeRun())).orderBy(
|
|
20011
|
+
const latestRun = app.db.select().from(runs).where(and19(eq26(runs.projectId, project.id), notProbeRun())).orderBy(desc10(runs.createdAt), desc10(runs.id)).limit(1).get();
|
|
19880
20012
|
if (!latestRun) {
|
|
19881
20013
|
return reply.send({ totalRuns: 0, run: null });
|
|
19882
20014
|
}
|
|
@@ -19896,7 +20028,7 @@ async function runRoutes(app, opts) {
|
|
|
19896
20028
|
if (status) filters.push(eq26(runs.status, status));
|
|
19897
20029
|
const scopedProjectId = request.apiKey?.projectId;
|
|
19898
20030
|
if (scopedProjectId) filters.push(eq26(runs.projectId, scopedProjectId));
|
|
19899
|
-
const rows = app.db.select().from(runs).where(and19(...filters)).orderBy(
|
|
20031
|
+
const rows = app.db.select().from(runs).where(and19(...filters)).orderBy(desc10(runs.createdAt), desc10(runs.id)).limit(limit).all();
|
|
19900
20032
|
return reply.send(rows.map(formatRun));
|
|
19901
20033
|
});
|
|
19902
20034
|
app.post("/runs", async (request, reply) => {
|
|
@@ -19913,6 +20045,8 @@ async function runRoutes(app, opts) {
|
|
|
19913
20045
|
}
|
|
19914
20046
|
const dispatchMode = parsedDispatchMode.data ?? null;
|
|
19915
20047
|
const batchEligibleProviders = opts.getBatchEligibleProviderNames?.() ?? null;
|
|
20048
|
+
const force = request.body?.force;
|
|
20049
|
+
if (force !== void 0 && typeof force !== "boolean") throw validationError('"force" must be a boolean');
|
|
19916
20050
|
const rawProviders = request.body?.providers;
|
|
19917
20051
|
if (rawProviders?.length) {
|
|
19918
20052
|
const normalized = rawProviders.map((p) => p.trim().toLowerCase()).filter(Boolean);
|
|
@@ -20008,12 +20142,18 @@ async function runRoutes(app, opts) {
|
|
|
20008
20142
|
runnableProviders: runnableProviderNames,
|
|
20009
20143
|
providerModels: opts.getEffectiveProviderModels?.(),
|
|
20010
20144
|
dispatchMode,
|
|
20011
|
-
batchEligibleProviders
|
|
20145
|
+
batchEligibleProviders,
|
|
20146
|
+
force: force ?? false
|
|
20012
20147
|
});
|
|
20013
20148
|
if (queueResult.conflict) {
|
|
20014
20149
|
results.push({ projectName: project.name, projectId: project.id, status: "conflict", error: "run_in_progress" });
|
|
20015
20150
|
continue;
|
|
20016
20151
|
}
|
|
20152
|
+
if (queueResult.refused) {
|
|
20153
|
+
const refusal = providersFailingError(project.name, queueResult.refused);
|
|
20154
|
+
results.push({ projectName: project.name, projectId: project.id, status: "error", error: refusal.message, errorCode: refusal.code });
|
|
20155
|
+
continue;
|
|
20156
|
+
}
|
|
20017
20157
|
const runId = queueResult.runId;
|
|
20018
20158
|
writeAuditLog(app.db, {
|
|
20019
20159
|
projectId: project.id,
|
|
@@ -20037,7 +20177,7 @@ async function runRoutes(app, opts) {
|
|
|
20037
20177
|
const terminalStatuses = /* @__PURE__ */ new Set(["completed", "partial", "failed", "cancelled"]);
|
|
20038
20178
|
if (terminalStatuses.has(run.status)) throw runNotCancellable(run.id, run.status);
|
|
20039
20179
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
20040
|
-
const cancelled = app.db.update(runs).set({ status: "cancelled", finishedAt: now, error: serializeRunError({ message: "Cancelled by user" }) }).where(and19(eq26(runs.id, run.id),
|
|
20180
|
+
const cancelled = app.db.update(runs).set({ status: "cancelled", finishedAt: now, error: serializeRunError({ message: "Cancelled by user" }) }).where(and19(eq26(runs.id, run.id), inArray12(runs.status, ["queued", "running"]))).run();
|
|
20041
20181
|
if (cancelled.changes === 0) {
|
|
20042
20182
|
const current = app.db.select().from(runs).where(eq26(runs.id, run.id)).get();
|
|
20043
20183
|
if (!current) throw notFound("Run", run.id);
|
|
@@ -20303,7 +20443,7 @@ function loadRunDetail(app, run) {
|
|
|
20303
20443
|
|
|
20304
20444
|
// ../api-routes/src/measurement-plan.ts
|
|
20305
20445
|
import crypto16 from "crypto";
|
|
20306
|
-
import { and as and20, desc as
|
|
20446
|
+
import { and as and20, desc as desc11, eq as eq27 } from "drizzle-orm";
|
|
20307
20447
|
var MEASUREMENT_PLAN_WRITE_SCOPE = "measurement-plan.write";
|
|
20308
20448
|
function parseStoredPlanAnyVersion(canonicalJson3) {
|
|
20309
20449
|
return parseStoredMeasurementPlanAnyVersion(canonicalJson3);
|
|
@@ -20660,7 +20800,7 @@ async function measurementPlanRoutes(app, opts) {
|
|
|
20660
20800
|
app.get("/projects/:name/measurement-plan/versions", async (request) => {
|
|
20661
20801
|
const project = resolveProject(app.db, request.params.name);
|
|
20662
20802
|
const active = activePlanVersion(app, project.id);
|
|
20663
|
-
const versions = app.db.select().from(measurementPlanVersions).where(eq27(measurementPlanVersions.projectId, project.id)).orderBy(
|
|
20803
|
+
const versions = app.db.select().from(measurementPlanVersions).where(eq27(measurementPlanVersions.projectId, project.id)).orderBy(desc11(measurementPlanVersions.revision)).all();
|
|
20664
20804
|
return {
|
|
20665
20805
|
versions: versions.map((version) => versionMetadata(version, active?.version.id ?? null))
|
|
20666
20806
|
};
|
|
@@ -21401,7 +21541,7 @@ async function measurementServiceRoutes(app, opts) {
|
|
|
21401
21541
|
|
|
21402
21542
|
// ../api-routes/src/measurement-draft.ts
|
|
21403
21543
|
import crypto19 from "crypto";
|
|
21404
|
-
import { and as and21, asc as asc4, desc as
|
|
21544
|
+
import { and as and21, asc as asc4, desc as desc12, eq as eq28, inArray as inArray13 } from "drizzle-orm";
|
|
21405
21545
|
|
|
21406
21546
|
// ../api-routes/src/measurement-draft-compile.ts
|
|
21407
21547
|
var MEASUREMENT_DRAFT_MAX_TARGETS = 1e3;
|
|
@@ -23553,7 +23693,7 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
23553
23693
|
// The comparable chain, not the bare active id: a label-only
|
|
23554
23694
|
// republish must not flip setup back to awaiting_first_run while
|
|
23555
23695
|
// the overview keeps serving the prior run.
|
|
23556
|
-
|
|
23696
|
+
inArray13(runs.measurementPlanVersionId, comparableMeasurementVersionIds(app.db, project.id, active.id)),
|
|
23557
23697
|
eq28(runs.status, RunStatuses.completed)
|
|
23558
23698
|
)).get() : void 0;
|
|
23559
23699
|
const state = activeSchemaVersion === 1 ? "republish_required" : draft ? "setup_in_progress" : active ? completedRun ? "operational" : "awaiting_first_run" : "simple";
|
|
@@ -24038,7 +24178,7 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
24038
24178
|
}));
|
|
24039
24179
|
return settle(false, active, parseV2Plan(active));
|
|
24040
24180
|
}
|
|
24041
|
-
const latest = tx.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq28(measurementPlanVersions.projectId, gate.project.id)).orderBy(
|
|
24181
|
+
const latest = tx.select({ revision: measurementPlanVersions.revision }).from(measurementPlanVersions).where(eq28(measurementPlanVersions.projectId, gate.project.id)).orderBy(desc12(measurementPlanVersions.revision)).get();
|
|
24042
24182
|
const revision = (latest?.revision ?? 0) + 1;
|
|
24043
24183
|
const canonicalJson3 = canonicalMeasurementPlanV2Json(compiled.plan);
|
|
24044
24184
|
const versionId = crypto19.randomUUID();
|
|
@@ -24175,7 +24315,7 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
24175
24315
|
const sets = app.db.select().from(measurementQuerySets).where(eq28(measurementQuerySets.projectId, project.id)).orderBy(asc4(measurementQuerySets.name)).all();
|
|
24176
24316
|
const counts2 = /* @__PURE__ */ new Map();
|
|
24177
24317
|
if (sets.length) {
|
|
24178
|
-
for (const item2 of app.db.select({ querySetId: measurementQuerySetItems.querySetId }).from(measurementQuerySetItems).where(
|
|
24318
|
+
for (const item2 of app.db.select({ querySetId: measurementQuerySetItems.querySetId }).from(measurementQuerySetItems).where(inArray13(measurementQuerySetItems.querySetId, sets.map((set) => set.id))).all()) {
|
|
24179
24319
|
counts2.set(item2.querySetId, (counts2.get(item2.querySetId) ?? 0) + 1);
|
|
24180
24320
|
}
|
|
24181
24321
|
}
|
|
@@ -24404,7 +24544,7 @@ async function measurementDraftRoutes(app, opts = {}) {
|
|
|
24404
24544
|
diff: { created: created.length, existing: existing.length }
|
|
24405
24545
|
}));
|
|
24406
24546
|
if (!querySet) return;
|
|
24407
|
-
const highest = tx.select({ position: measurementQuerySetItems.position }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).orderBy(
|
|
24547
|
+
const highest = tx.select({ position: measurementQuerySetItems.position }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).orderBy(desc12(measurementQuerySetItems.position)).get();
|
|
24408
24548
|
let position = (highest?.position ?? -1) + 1;
|
|
24409
24549
|
const present = new Set(tx.select({ queryId: measurementQuerySetItems.queryId }).from(measurementQuerySetItems).where(eq28(measurementQuerySetItems.querySetId, querySet.id)).all().map((item2) => item2.queryId));
|
|
24410
24550
|
for (const entry of ordered) {
|
|
@@ -25077,10 +25217,10 @@ async function measurementPropertyEvidenceRoutes(app) {
|
|
|
25077
25217
|
}
|
|
25078
25218
|
|
|
25079
25219
|
// ../api-routes/src/measurement-portfolio-reads.ts
|
|
25080
|
-
import { and as and25, desc as
|
|
25220
|
+
import { and as and25, desc as desc13, eq as eq32, inArray as inArray15, lt as lt5, or as or7 } from "drizzle-orm";
|
|
25081
25221
|
|
|
25082
25222
|
// ../api-routes/src/measurement-question-reads.ts
|
|
25083
|
-
import { and as and24, eq as eq31, getTableColumns, inArray as
|
|
25223
|
+
import { and as and24, eq as eq31, getTableColumns, inArray as inArray14, sql as sql11 } from "drizzle-orm";
|
|
25084
25224
|
var DEFAULT_LIMIT2 = 50;
|
|
25085
25225
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
25086
25226
|
RunStatuses.completed,
|
|
@@ -25196,7 +25336,7 @@ function selectedQuestionSnapshots(db, runId, manifest, scope) {
|
|
|
25196
25336
|
if (scope !== void 0) {
|
|
25197
25337
|
const executionIds = [...new Set(manifest.expectedSlots.map((slot) => slot.executionId))];
|
|
25198
25338
|
if (executionIds.length === 0) return [];
|
|
25199
|
-
conditions.push(
|
|
25339
|
+
conditions.push(inArray14(querySnapshots.measurementExecutionId, executionIds));
|
|
25200
25340
|
}
|
|
25201
25341
|
if (scope?.provider !== void 0) {
|
|
25202
25342
|
conditions.push(sql11`lower(trim(${querySnapshots.provider})) = ${normalizeText(scope.provider)}`);
|
|
@@ -25211,7 +25351,7 @@ function rawResponsesForLegacyQuestionSnapshots(db, runId, snapshots) {
|
|
|
25211
25351
|
rawResponse: querySnapshots.rawResponse
|
|
25212
25352
|
}).from(querySnapshots).where(and24(
|
|
25213
25353
|
eq31(querySnapshots.runId, runId),
|
|
25214
|
-
|
|
25354
|
+
inArray14(querySnapshots.id, legacyIds)
|
|
25215
25355
|
)).all().map((snapshot) => [snapshot.id, snapshot.rawResponse]));
|
|
25216
25356
|
}
|
|
25217
25357
|
function withLegacyRawEvidence(db, runId, snapshots) {
|
|
@@ -26140,14 +26280,14 @@ function previousComparableRun(db, active, current) {
|
|
|
26140
26280
|
// republish: a run pinned to a comparable prior revision measured exactly
|
|
26141
26281
|
// the questions the active revision asks. The execution-identity and scope
|
|
26142
26282
|
// checks below still gate what actually compares.
|
|
26143
|
-
|
|
26283
|
+
inArray15(runs.measurementPlanVersionId, comparableMeasurementVersionIds(db, current.projectId, active.version.id)),
|
|
26144
26284
|
eq32(runs.kind, RunKinds["answer-visibility"]),
|
|
26145
|
-
|
|
26285
|
+
inArray15(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
26146
26286
|
or7(
|
|
26147
26287
|
lt5(runs.createdAt, current.createdAt),
|
|
26148
26288
|
and25(eq32(runs.createdAt, current.createdAt), lt5(runs.id, current.id))
|
|
26149
26289
|
)
|
|
26150
|
-
)).orderBy(
|
|
26290
|
+
)).orderBy(desc13(runs.createdAt), desc13(runs.id)).all().filter((candidate) => (
|
|
26151
26291
|
// Full reporting never admits probes. A plan slice is itself stored as a
|
|
26152
26292
|
// probe, so an explicitly selected slice compares only with other slices;
|
|
26153
26293
|
// the exact frozen scope check below then keeps the population identical.
|
|
@@ -26399,7 +26539,7 @@ function unattributedByClass(plan, run, materialized) {
|
|
|
26399
26539
|
return { branded: read("branded"), nonBrand: read("non-brand") };
|
|
26400
26540
|
}
|
|
26401
26541
|
function latestRunFill(db, runId) {
|
|
26402
|
-
const fill = db.select().from(runFills).where(eq32(runFills.runId, runId)).orderBy(
|
|
26542
|
+
const fill = db.select().from(runFills).where(eq32(runFills.runId, runId)).orderBy(desc13(runFills.createdAt), desc13(runFills.id)).get();
|
|
26403
26543
|
if (!fill) return null;
|
|
26404
26544
|
const { status, providers, expected, filled, createdAt, finishedAt } = formatRunFill(fill);
|
|
26405
26545
|
return { status, providers, expected, filled, createdAt, finishedAt };
|
|
@@ -26551,7 +26691,7 @@ async function measurementPortfolioReadRoutes(app) {
|
|
|
26551
26691
|
|
|
26552
26692
|
// ../api-routes/src/visibility-report.ts
|
|
26553
26693
|
import { createHash as createHash7 } from "crypto";
|
|
26554
|
-
import { and as and26, desc as
|
|
26694
|
+
import { and as and26, desc as desc14, eq as eq33, gte as gte5, inArray as inArray16, isNotNull as isNotNull4, isNull as isNull8, lt as lt6, lte as lte6, or as or8 } from "drizzle-orm";
|
|
26555
26695
|
|
|
26556
26696
|
// ../api-routes/src/measurement-scope-options.ts
|
|
26557
26697
|
function marketLinks(keys, settings) {
|
|
@@ -27370,7 +27510,7 @@ function loadVisibilitySnapshots(db, runIds) {
|
|
|
27370
27510
|
requestedContext: querySnapshots.requestedContext,
|
|
27371
27511
|
supportedContext: querySnapshots.supportedContext,
|
|
27372
27512
|
createdAt: querySnapshots.createdAt
|
|
27373
|
-
}).from(querySnapshots).where(
|
|
27513
|
+
}).from(querySnapshots).where(inArray16(querySnapshots.runId, [...runIds])).all();
|
|
27374
27514
|
for (const row of rows) {
|
|
27375
27515
|
const snapshots = byRun.get(row.runId) ?? [];
|
|
27376
27516
|
snapshots.push(row);
|
|
@@ -27783,7 +27923,7 @@ function completedVisibilityRuns(db, projectId, planless, query) {
|
|
|
27783
27923
|
return db.select().from(runs).where(and26(
|
|
27784
27924
|
eq33(runs.projectId, projectId),
|
|
27785
27925
|
eq33(runs.kind, RunKinds["answer-visibility"]),
|
|
27786
|
-
|
|
27926
|
+
inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
27787
27927
|
notProbeRun(),
|
|
27788
27928
|
planless ? isNull8(runs.measurementPlanVersionId) : isNotNull4(runs.measurementPlanVersionId),
|
|
27789
27929
|
// A scoped spot check is never a whole-project sweep. It can be inspected
|
|
@@ -27792,13 +27932,13 @@ function completedVisibilityRuns(db, projectId, planless, query) {
|
|
|
27792
27932
|
query.runId === void 0 ? void 0 : eq33(runs.id, query.runId),
|
|
27793
27933
|
query.from === void 0 ? void 0 : gte5(runs.createdAt, query.from),
|
|
27794
27934
|
query.to === void 0 ? void 0 : lte6(runs.createdAt, query.to)
|
|
27795
|
-
)).orderBy(
|
|
27935
|
+
)).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(VISIBILITY_REPORT_MAX_RUNS).all();
|
|
27796
27936
|
}
|
|
27797
27937
|
function previousEligibleVisibilityRun(db, projectId, planless, selected) {
|
|
27798
27938
|
return db.select().from(runs).where(and26(
|
|
27799
27939
|
eq33(runs.projectId, projectId),
|
|
27800
27940
|
eq33(runs.kind, RunKinds["answer-visibility"]),
|
|
27801
|
-
|
|
27941
|
+
inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
27802
27942
|
notProbeRun(),
|
|
27803
27943
|
planless ? isNull8(runs.measurementPlanVersionId) : isNotNull4(runs.measurementPlanVersionId),
|
|
27804
27944
|
isNull8(runs.measurementScope),
|
|
@@ -27806,7 +27946,7 @@ function previousEligibleVisibilityRun(db, projectId, planless, selected) {
|
|
|
27806
27946
|
lt6(runs.createdAt, selected.createdAt),
|
|
27807
27947
|
and26(eq33(runs.createdAt, selected.createdAt), lt6(runs.id, selected.id))
|
|
27808
27948
|
)
|
|
27809
|
-
)).orderBy(
|
|
27949
|
+
)).orderBy(desc14(runs.createdAt), desc14(runs.id)).limit(1).get();
|
|
27810
27950
|
}
|
|
27811
27951
|
function readPreviousSweep(read) {
|
|
27812
27952
|
try {
|
|
@@ -27937,7 +28077,7 @@ function frozenSimpleDefinitions(db, projectId, runIds) {
|
|
|
27937
28077
|
if (runIds.length === 0) return /* @__PURE__ */ new Map();
|
|
27938
28078
|
return new Map(db.select().from(simpleMeasurementDefinitions).where(and26(
|
|
27939
28079
|
eq33(simpleMeasurementDefinitions.projectId, projectId),
|
|
27940
|
-
|
|
28080
|
+
inArray16(simpleMeasurementDefinitions.runId, [...runIds])
|
|
27941
28081
|
)).all().map((row) => [row.runId, row.definition]));
|
|
27942
28082
|
}
|
|
27943
28083
|
function simpleRunInput(db, project, run, definition, includeEvidence) {
|
|
@@ -28006,7 +28146,7 @@ function readVisibilityComparisonRuns(db, projectId, since, until, includeEviden
|
|
|
28006
28146
|
const sourceRuns = db.select().from(runs).where(and26(
|
|
28007
28147
|
eq33(runs.projectId, projectId),
|
|
28008
28148
|
eq33(runs.kind, RunKinds["answer-visibility"]),
|
|
28009
|
-
|
|
28149
|
+
inArray16(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
28010
28150
|
notProbeRun(),
|
|
28011
28151
|
isNotNull4(runs.measurementPlanVersionId),
|
|
28012
28152
|
isNull8(runs.measurementScope),
|
|
@@ -28036,7 +28176,7 @@ function readVisibilityComparisonRuns(db, projectId, since, until, includeEviden
|
|
|
28036
28176
|
|
|
28037
28177
|
// ../api-routes/src/query-tracking.ts
|
|
28038
28178
|
import crypto21 from "crypto";
|
|
28039
|
-
import { and as and27, desc as
|
|
28179
|
+
import { and as and27, desc as desc15, eq as eq34, inArray as inArray17, isNotNull as isNotNull5, isNull as isNull9, ne as ne6 } from "drizzle-orm";
|
|
28040
28180
|
var SOURCE_LIMIT = 100;
|
|
28041
28181
|
var MAX_REVIEW_AGE_MS = 15 * 60 * 1e3;
|
|
28042
28182
|
var MAX_REVIEW_FUTURE_SKEW_MS = 60 * 1e3;
|
|
@@ -28222,11 +28362,11 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
|
|
|
28222
28362
|
}).from(runs).where(and27(
|
|
28223
28363
|
eq34(runs.projectId, project.id),
|
|
28224
28364
|
eq34(runs.kind, RunKinds["answer-visibility"]),
|
|
28225
|
-
|
|
28365
|
+
inArray17(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
28226
28366
|
ne6(runs.trigger, RunTriggers.probe),
|
|
28227
28367
|
isNull9(runs.measurementScope),
|
|
28228
28368
|
isNull9(runs.measurementPlanVersionId)
|
|
28229
|
-
)).orderBy(
|
|
28369
|
+
)).orderBy(desc15(runs.createdAt), desc15(runs.id)).limit(SOURCE_LIMIT).all();
|
|
28230
28370
|
if (eligibleRuns.length === 0) return /* @__PURE__ */ new Map();
|
|
28231
28371
|
const frozenByRun = /* @__PURE__ */ new Map();
|
|
28232
28372
|
for (const row of db.select({
|
|
@@ -28234,7 +28374,7 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
|
|
|
28234
28374
|
definition: simpleMeasurementDefinitions.definition
|
|
28235
28375
|
}).from(simpleMeasurementDefinitions).where(and27(
|
|
28236
28376
|
eq34(simpleMeasurementDefinitions.projectId, project.id),
|
|
28237
|
-
|
|
28377
|
+
inArray17(simpleMeasurementDefinitions.runId, eligibleRuns.map((run) => run.id))
|
|
28238
28378
|
)).all()) {
|
|
28239
28379
|
const parsed = simpleMeasurementDefinitionSchema.safeParse(row.definition);
|
|
28240
28380
|
if (parsed.success) frozenByRun.set(row.runId, parsed.data);
|
|
@@ -28246,7 +28386,7 @@ function simpleMeasuredAtByQuery(db, project, queryRows2, opts) {
|
|
|
28246
28386
|
queryId: querySnapshots.queryId,
|
|
28247
28387
|
queryText: querySnapshots.queryText,
|
|
28248
28388
|
provider: querySnapshots.provider
|
|
28249
|
-
}).from(querySnapshots).where(
|
|
28389
|
+
}).from(querySnapshots).where(inArray17(querySnapshots.runId, [...frozenByRun.keys()])).all()) {
|
|
28250
28390
|
if (!snapshot.queryId) continue;
|
|
28251
28391
|
const byQuery = snapshotsByRunQuery.get(snapshot.runId) ?? /* @__PURE__ */ new Map();
|
|
28252
28392
|
const rows = byQuery.get(snapshot.queryId) ?? [];
|
|
@@ -28344,11 +28484,11 @@ function measuredAtByQuery(db, state, opts) {
|
|
|
28344
28484
|
const eligibleRuns = db.select().from(runs).where(and27(
|
|
28345
28485
|
eq34(runs.projectId, project.id),
|
|
28346
28486
|
eq34(runs.kind, RunKinds["answer-visibility"]),
|
|
28347
|
-
|
|
28487
|
+
inArray17(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
28348
28488
|
ne6(runs.trigger, RunTriggers.probe),
|
|
28349
28489
|
isNull9(runs.measurementScope),
|
|
28350
28490
|
isNotNull5(runs.measurementPlanVersionId)
|
|
28351
|
-
)).orderBy(
|
|
28491
|
+
)).orderBy(desc15(runs.createdAt), desc15(runs.id)).limit(SOURCE_LIMIT).all();
|
|
28352
28492
|
if (eligibleRuns.length === 0) return /* @__PURE__ */ new Map();
|
|
28353
28493
|
const versionIds = unique2(eligibleRuns.flatMap((run) => run.measurementPlanVersionId ? [run.measurementPlanVersionId] : []));
|
|
28354
28494
|
const versionPlans = new Map(db.select({
|
|
@@ -28357,7 +28497,7 @@ function measuredAtByQuery(db, state, opts) {
|
|
|
28357
28497
|
canonicalJson: measurementPlanVersions.canonicalJson
|
|
28358
28498
|
}).from(measurementPlanVersions).where(and27(
|
|
28359
28499
|
eq34(measurementPlanVersions.projectId, project.id),
|
|
28360
|
-
|
|
28500
|
+
inArray17(measurementPlanVersions.id, versionIds)
|
|
28361
28501
|
)).all().flatMap((row) => {
|
|
28362
28502
|
const parsed = parseStoredMeasurementPlanAnyVersion(row.canonicalJson);
|
|
28363
28503
|
return parsed.schemaVersion === 2 ? [[row.id, { revision: row.revision, plan: parsed }]] : [];
|
|
@@ -28389,7 +28529,7 @@ function measuredAtByQuery(db, state, opts) {
|
|
|
28389
28529
|
measurementExecutionId: querySnapshots.measurementExecutionId,
|
|
28390
28530
|
requestedContext: querySnapshots.requestedContext,
|
|
28391
28531
|
supportedContext: querySnapshots.supportedContext
|
|
28392
|
-
}).from(querySnapshots).where(
|
|
28532
|
+
}).from(querySnapshots).where(inArray17(querySnapshots.runId, eligibleRuns.map((run) => run.id))).all();
|
|
28393
28533
|
for (const snapshot of snapshotRows) {
|
|
28394
28534
|
const snapshots = snapshotsByRun.get(snapshot.runId) ?? [];
|
|
28395
28535
|
snapshots.push(snapshot);
|
|
@@ -28537,13 +28677,13 @@ function savedSources(db, projectId) {
|
|
|
28537
28677
|
researchRunQueryId: researchRunQueries.id,
|
|
28538
28678
|
queryText: researchRunQueries.queryText,
|
|
28539
28679
|
createdAt: researchRunQueries.createdAt
|
|
28540
|
-
}).from(researchRunQueries).innerJoin(researchRuns, eq34(researchRunQueries.researchRunId, researchRuns.id)).where(eq34(researchRuns.projectId, projectId)).orderBy(
|
|
28680
|
+
}).from(researchRunQueries).innerJoin(researchRuns, eq34(researchRunQueries.researchRunId, researchRuns.id)).where(eq34(researchRuns.projectId, projectId)).orderBy(desc15(researchRunQueries.createdAt)).limit(SOURCE_LIMIT).all().filter((row) => row.queryText.trim().length > 0);
|
|
28541
28681
|
const discovery = db.select({
|
|
28542
28682
|
discoverySessionId: discoverySessions.id,
|
|
28543
28683
|
discoveryProbeId: discoveryProbes.id,
|
|
28544
28684
|
queryText: discoveryProbes.query,
|
|
28545
28685
|
createdAt: discoveryProbes.createdAt
|
|
28546
|
-
}).from(discoveryProbes).innerJoin(discoverySessions, eq34(discoveryProbes.sessionId, discoverySessions.id)).where(eq34(discoverySessions.projectId, projectId)).orderBy(
|
|
28686
|
+
}).from(discoveryProbes).innerJoin(discoverySessions, eq34(discoveryProbes.sessionId, discoverySessions.id)).where(eq34(discoverySessions.projectId, projectId)).orderBy(desc15(discoveryProbes.createdAt)).limit(SOURCE_LIMIT).all().filter((row) => row.queryText.trim().length > 0);
|
|
28547
28687
|
return { research, discovery };
|
|
28548
28688
|
}
|
|
28549
28689
|
function workspaceDto(db, state, opts) {
|
|
@@ -29398,7 +29538,7 @@ function writeAdvancedCandidate(tx, candidate, request, now) {
|
|
|
29398
29538
|
const removed = current.filter((row) => !candidate.queryRows.has(row.id));
|
|
29399
29539
|
if (removed.length > 0) {
|
|
29400
29540
|
preserveSnapshotQueryText(tx, candidate.state.project.id, removed.map((row) => row.id));
|
|
29401
|
-
tx.delete(queries).where(
|
|
29541
|
+
tx.delete(queries).where(inArray17(queries.id, removed.map((row) => row.id))).run();
|
|
29402
29542
|
}
|
|
29403
29543
|
for (const row of candidate.queryRows.values()) {
|
|
29404
29544
|
const previous = currentById.get(row.id);
|
|
@@ -29417,7 +29557,7 @@ function writeAdvancedCandidate(tx, candidate, request, now) {
|
|
|
29417
29557
|
if (!candidate.planChanged) return active;
|
|
29418
29558
|
const plan = candidate.plan;
|
|
29419
29559
|
const canonicalJson3 = canonicalMeasurementPlanV2Json(plan);
|
|
29420
|
-
const latest = tx.select().from(measurementPlanVersions).where(eq34(measurementPlanVersions.projectId, candidate.state.project.id)).orderBy(
|
|
29560
|
+
const latest = tx.select().from(measurementPlanVersions).where(eq34(measurementPlanVersions.projectId, candidate.state.project.id)).orderBy(desc15(measurementPlanVersions.revision)).get();
|
|
29421
29561
|
const revision = (latest?.revision ?? 0) + 1;
|
|
29422
29562
|
const versionId = crypto21.randomUUID();
|
|
29423
29563
|
tx.insert(measurementPlanVersions).values({
|
|
@@ -30226,7 +30366,7 @@ function aliasArraysEqual2(a, b) {
|
|
|
30226
30366
|
}
|
|
30227
30367
|
|
|
30228
30368
|
// ../api-routes/src/history.ts
|
|
30229
|
-
import { and as and29, asc as asc5, count, desc as
|
|
30369
|
+
import { and as and29, asc as asc5, count, desc as desc16, eq as eq36, gte as gte6, inArray as inArray18, like as like2, ne as ne7, or as or9 } from "drizzle-orm";
|
|
30230
30370
|
|
|
30231
30371
|
// ../api-routes/src/notification-redaction.ts
|
|
30232
30372
|
var REDACTED_URL = {
|
|
@@ -30278,27 +30418,27 @@ async function historyRoutes(app) {
|
|
|
30278
30418
|
if (!parsed.success) throw validationError("Invalid history cleanup request", { issues: parsed.error.issues });
|
|
30279
30419
|
const input = parsed.data;
|
|
30280
30420
|
return app.db.transaction((tx) => {
|
|
30281
|
-
const active = tx.select({ id: runs.id }).from(runs).where(and29(eq36(runs.projectId, project.id), eq36(runs.kind, RunKinds["answer-visibility"]),
|
|
30282
|
-
const activeResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id),
|
|
30421
|
+
const active = tx.select({ id: runs.id }).from(runs).where(and29(eq36(runs.projectId, project.id), eq36(runs.kind, RunKinds["answer-visibility"]), inArray18(runs.status, ["queued", "running"]))).get();
|
|
30422
|
+
const activeResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.status, ["queued", "running"]))).get();
|
|
30283
30423
|
if (active || activeResearch) throw runInProgress(project.name, active ? "answer-visibility" : "research", (active ?? activeResearch).id);
|
|
30284
|
-
const activeFill = tx.select({ id: runFills.id, runId: runFills.runId }).from(runFills).where(and29(eq36(runFills.projectId, project.id),
|
|
30424
|
+
const activeFill = tx.select({ id: runFills.id, runId: runFills.runId }).from(runFills).where(and29(eq36(runFills.projectId, project.id), inArray18(runFills.status, ["queued", "running"]))).get();
|
|
30285
30425
|
if (activeFill) throw runFillInProgress(activeFill.runId, activeFill.id);
|
|
30286
|
-
const selectedRuns = tx.select({ id: runs.id, kind: runs.kind }).from(runs).where(and29(eq36(runs.projectId, project.id),
|
|
30287
|
-
const selectedResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id),
|
|
30426
|
+
const selectedRuns = tx.select({ id: runs.id, kind: runs.kind }).from(runs).where(and29(eq36(runs.projectId, project.id), inArray18(runs.id, input.runIds))).all();
|
|
30427
|
+
const selectedResearch = tx.select({ id: researchRuns.id }).from(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.id, input.researchRunIds))).all();
|
|
30288
30428
|
if (selectedRuns.length !== input.runIds.length || selectedResearch.length !== input.researchRunIds.length) throw notFound("Selected saved run in project", project.name);
|
|
30289
30429
|
if (selectedRuns.some((run) => run.kind !== RunKinds["answer-visibility"])) throw validationError("Only answer-visibility runs and research batches can be cleared. Site Health and integration runs are preserved.");
|
|
30290
30430
|
const result = {
|
|
30291
30431
|
dryRun: !input.confirm,
|
|
30292
30432
|
runIds: input.runIds,
|
|
30293
30433
|
researchRunIds: input.researchRunIds,
|
|
30294
|
-
querySnapshots: tx.select({ value: count() }).from(querySnapshots).where(
|
|
30295
|
-
researchQueries: tx.select({ value: count() }).from(researchRunQueries).where(
|
|
30296
|
-
insights: tx.select({ value: count() }).from(insights).where(
|
|
30297
|
-
healthSnapshots: tx.select({ value: count() }).from(healthSnapshots).where(
|
|
30434
|
+
querySnapshots: tx.select({ value: count() }).from(querySnapshots).where(inArray18(querySnapshots.runId, input.runIds)).get().value,
|
|
30435
|
+
researchQueries: tx.select({ value: count() }).from(researchRunQueries).where(inArray18(researchRunQueries.researchRunId, input.researchRunIds)).get().value,
|
|
30436
|
+
insights: tx.select({ value: count() }).from(insights).where(inArray18(insights.runId, input.runIds)).get().value,
|
|
30437
|
+
healthSnapshots: tx.select({ value: count() }).from(healthSnapshots).where(inArray18(healthSnapshots.runId, input.runIds)).get().value
|
|
30298
30438
|
};
|
|
30299
30439
|
if (input.confirm) {
|
|
30300
|
-
tx.delete(researchRuns).where(and29(eq36(researchRuns.projectId, project.id),
|
|
30301
|
-
tx.delete(runs).where(and29(eq36(runs.projectId, project.id),
|
|
30440
|
+
tx.delete(researchRuns).where(and29(eq36(researchRuns.projectId, project.id), inArray18(researchRuns.id, input.researchRunIds))).run();
|
|
30441
|
+
tx.delete(runs).where(and29(eq36(runs.projectId, project.id), inArray18(runs.id, input.runIds))).run();
|
|
30302
30442
|
writeAuditLog(tx, { projectId: project.id, actor: "api", action: "results.cleared", entityType: "project", entityId: project.id, diff: result });
|
|
30303
30443
|
}
|
|
30304
30444
|
return result;
|
|
@@ -30309,7 +30449,7 @@ async function historyRoutes(app) {
|
|
|
30309
30449
|
const filters = [eq36(auditLog.projectId, project.id)];
|
|
30310
30450
|
if (request.operatorAccess !== true) filters.push(ne7(auditLog.entityType, "telemetry"));
|
|
30311
30451
|
addAuditHistoryFilters(filters, request.query);
|
|
30312
|
-
const rows = app.db.select().from(auditLog).where(and29(...filters)).orderBy(
|
|
30452
|
+
const rows = app.db.select().from(auditLog).where(and29(...filters)).orderBy(desc16(auditLog.createdAt), desc16(auditLog.id)).limit(parseBoundedInt(request.query.limit, 100, 500)).offset(parseBoundedInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER)).all();
|
|
30313
30453
|
return reply.send(rows.map(formatAuditEntry));
|
|
30314
30454
|
});
|
|
30315
30455
|
app.get("/history", async (request, reply) => {
|
|
@@ -30317,7 +30457,7 @@ async function historyRoutes(app) {
|
|
|
30317
30457
|
const filters = scopedProjectId ? [eq36(auditLog.projectId, scopedProjectId)] : [];
|
|
30318
30458
|
if (request.operatorAccess !== true) filters.push(ne7(auditLog.entityType, "telemetry"));
|
|
30319
30459
|
addAuditHistoryFilters(filters, request.query);
|
|
30320
|
-
const rows = app.db.select().from(auditLog).where(filters.length > 0 ? and29(...filters) : void 0).orderBy(
|
|
30460
|
+
const rows = app.db.select().from(auditLog).where(filters.length > 0 ? and29(...filters) : void 0).orderBy(desc16(auditLog.createdAt), desc16(auditLog.id)).limit(parseBoundedInt(request.query.limit, 100, 500)).offset(parseBoundedInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER)).all();
|
|
30321
30461
|
return reply.send(rows.map(formatAuditEntry));
|
|
30322
30462
|
});
|
|
30323
30463
|
app.get("/projects/:name/snapshots", async (request, reply) => {
|
|
@@ -30350,7 +30490,7 @@ async function historyRoutes(app) {
|
|
|
30350
30490
|
location: querySnapshots.location,
|
|
30351
30491
|
rawResponse: querySnapshots.rawResponse,
|
|
30352
30492
|
createdAt: querySnapshots.createdAt
|
|
30353
|
-
}).from(querySnapshots).leftJoin(queries, eq36(querySnapshots.queryId, queries.id)).where(
|
|
30493
|
+
}).from(querySnapshots).leftJoin(queries, eq36(querySnapshots.queryId, queries.id)).where(inArray18(querySnapshots.runId, projectRuns.map((r) => r.id))).orderBy(desc16(querySnapshots.createdAt)).all();
|
|
30354
30494
|
const locationFilter = request.query.location;
|
|
30355
30495
|
const filtered = locationFilter !== void 0 ? allSnapshots.filter((s) => s.location === (locationFilter || null)) : allSnapshots;
|
|
30356
30496
|
const total = filtered.length;
|
|
@@ -30405,12 +30545,12 @@ async function historyRoutes(app) {
|
|
|
30405
30545
|
eq36(runs.kind, RunKinds["answer-visibility"])
|
|
30406
30546
|
);
|
|
30407
30547
|
const requestedLimit = parseOptionalPositiveInt(request.query.limit, 100);
|
|
30408
|
-
const projectRuns = requestedLimit == null ? app.db.select().from(runs).where(runKindFilter).orderBy(asc5(runs.createdAt)).all() : app.db.select().from(runs).where(runKindFilter).orderBy(
|
|
30548
|
+
const projectRuns = requestedLimit == null ? app.db.select().from(runs).where(runKindFilter).orderBy(asc5(runs.createdAt)).all() : app.db.select().from(runs).where(runKindFilter).orderBy(desc16(runs.createdAt)).limit(requestedLimit).all().reverse();
|
|
30409
30549
|
if (projectRuns.length === 0 || projectQueries.length === 0) {
|
|
30410
30550
|
return reply.send([]);
|
|
30411
30551
|
}
|
|
30412
30552
|
const runIds = new Set(projectRuns.map((r) => r.id));
|
|
30413
|
-
const rawSnapshots = app.db.select().from(querySnapshots).where(
|
|
30553
|
+
const rawSnapshots = app.db.select().from(querySnapshots).where(inArray18(querySnapshots.runId, [...runIds])).all();
|
|
30414
30554
|
const timelineLocationFilter = request.query.location;
|
|
30415
30555
|
const filteredSnapshots = timelineLocationFilter !== void 0 ? rawSnapshots.filter((s) => s.location === (timelineLocationFilter || null)) : rawSnapshots;
|
|
30416
30556
|
const allSnapshots = filteredSnapshots.map((snapshot) => ({
|
|
@@ -30531,7 +30671,7 @@ async function historyRoutes(app) {
|
|
|
30531
30671
|
throw validationError("Both run1 and run2 query params are required");
|
|
30532
30672
|
}
|
|
30533
30673
|
const requestedRunIds = [.../* @__PURE__ */ new Set([run1, run2])];
|
|
30534
|
-
const runRows = app.db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(
|
|
30674
|
+
const runRows = app.db.select({ id: runs.id, projectId: runs.projectId }).from(runs).where(inArray18(runs.id, requestedRunIds)).all();
|
|
30535
30675
|
const runsById = new Map(runRows.map((row) => [row.id, row]));
|
|
30536
30676
|
for (const runId of requestedRunIds) {
|
|
30537
30677
|
const run = runsById.get(runId);
|
|
@@ -30636,7 +30776,7 @@ function parseOptionalPositiveInt(value, max2) {
|
|
|
30636
30776
|
}
|
|
30637
30777
|
|
|
30638
30778
|
// ../api-routes/src/analytics.ts
|
|
30639
|
-
import { and as and30, desc as
|
|
30779
|
+
import { and as and30, desc as desc17, eq as eq37, gte as gte7, inArray as inArray19, lt as lt7 } from "drizzle-orm";
|
|
30640
30780
|
|
|
30641
30781
|
// ../api-routes/src/analytics-model-attribution.ts
|
|
30642
30782
|
function logicalSweeps(observations) {
|
|
@@ -30732,10 +30872,10 @@ async function analyticsRoutes(app) {
|
|
|
30732
30872
|
const projectRuns = app.db.select().from(runs).where(and30(
|
|
30733
30873
|
eq37(runs.projectId, project.id),
|
|
30734
30874
|
eq37(runs.kind, RunKinds["answer-visibility"]),
|
|
30735
|
-
|
|
30875
|
+
inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
30736
30876
|
notProbeRun(),
|
|
30737
30877
|
cutoff ? gte7(runs.createdAt, cutoff) : void 0
|
|
30738
|
-
)).orderBy(
|
|
30878
|
+
)).orderBy(desc17(runs.createdAt)).all().filter((r) => measuredWhole(app.db, r)).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
30739
30879
|
if (projectRuns.length === 0) {
|
|
30740
30880
|
return reply.send({
|
|
30741
30881
|
window,
|
|
@@ -30777,7 +30917,7 @@ async function analyticsRoutes(app) {
|
|
|
30777
30917
|
citationState: querySnapshots.citationState,
|
|
30778
30918
|
answerMentioned: querySnapshots.answerMentioned,
|
|
30779
30919
|
answerText: querySnapshots.answerText
|
|
30780
|
-
}).from(querySnapshots).where(
|
|
30920
|
+
}).from(querySnapshots).where(inArray19(querySnapshots.runId, runIds)).all();
|
|
30781
30921
|
const rawSnapshots = referenceBasket ? loadedSnapshots.filter(
|
|
30782
30922
|
(s) => s.queryId !== null || s.queryText !== null && referenceBasket.has(normalizeQueryText(s.queryText))
|
|
30783
30923
|
) : filterTrackedSnapshots(loadedSnapshots);
|
|
@@ -30827,11 +30967,11 @@ async function analyticsRoutes(app) {
|
|
|
30827
30967
|
const anchorRunPredicate = and30(
|
|
30828
30968
|
eq37(runs.projectId, project.id),
|
|
30829
30969
|
eq37(runs.kind, RunKinds["answer-visibility"]),
|
|
30830
|
-
|
|
30970
|
+
inArray19(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
30831
30971
|
notProbeRun(),
|
|
30832
30972
|
lt7(runs.createdAt, cutoff)
|
|
30833
30973
|
);
|
|
30834
|
-
const anchorSweepTimes = app.db.selectDistinct({ createdAt: runs.createdAt }).from(runs).where(anchorRunPredicate).orderBy(
|
|
30974
|
+
const anchorSweepTimes = app.db.selectDistinct({ createdAt: runs.createdAt }).from(runs).where(anchorRunPredicate).orderBy(desc17(runs.createdAt)).limit(ANCHOR_SWEEP_SCAN_LIMIT + 1).all().map((row) => row.createdAt);
|
|
30835
30975
|
const anchorScanTruncated = anchorSweepTimes.length > ANCHOR_SWEEP_SCAN_LIMIT;
|
|
30836
30976
|
if (anchorScanTruncated) anchorSweepTimes.length = ANCHOR_SWEEP_SCAN_LIMIT;
|
|
30837
30977
|
if (anchorSweepTimes.length > 0) {
|
|
@@ -30857,7 +30997,7 @@ async function analyticsRoutes(app) {
|
|
|
30857
30997
|
provider: querySnapshots.provider,
|
|
30858
30998
|
model: querySnapshots.model,
|
|
30859
30999
|
servedModel: querySnapshots.servedModel
|
|
30860
|
-
}).from(querySnapshots).where(
|
|
31000
|
+
}).from(querySnapshots).where(inArray19(querySnapshots.runId, runIds2)).all())) {
|
|
30861
31001
|
if (pending.has(snapshot.provider)) {
|
|
30862
31002
|
const models = modelsByProvider.get(snapshot.provider) ?? [];
|
|
30863
31003
|
models.push(snapshot.model);
|
|
@@ -30986,7 +31126,7 @@ async function analyticsRoutes(app) {
|
|
|
30986
31126
|
const project = resolveProject(app.db, request.params.name);
|
|
30987
31127
|
const window = parseWindow(request.query.window);
|
|
30988
31128
|
const cutoff = windowCutoff(window);
|
|
30989
|
-
const completedRuns = app.db.select().from(runs).where(and30(eq37(runs.projectId, project.id), eq37(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(
|
|
31129
|
+
const completedRuns = app.db.select().from(runs).where(and30(eq37(runs.projectId, project.id), eq37(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc17(runs.createdAt), desc17(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => measuredWhole(app.db, r));
|
|
30990
31130
|
const latestGroup = groupRunsByCreatedAt(completedRuns)[0] ?? [];
|
|
30991
31131
|
const latestGroupRunIds = latestGroup.map((r) => r.id);
|
|
30992
31132
|
const latestRun = pickGroupRepresentative(latestGroup);
|
|
@@ -31009,7 +31149,7 @@ async function analyticsRoutes(app) {
|
|
|
31009
31149
|
citationState: querySnapshots.citationState,
|
|
31010
31150
|
answerMentioned: querySnapshots.answerMentioned,
|
|
31011
31151
|
answerText: querySnapshots.answerText
|
|
31012
|
-
}).from(querySnapshots).where(
|
|
31152
|
+
}).from(querySnapshots).where(inArray19(querySnapshots.runId, windowRunIds)).all());
|
|
31013
31153
|
for (const s of allWindowSnaps) {
|
|
31014
31154
|
const timePoint = runIdToCreatedAt.get(s.runId) ?? s.runId;
|
|
31015
31155
|
let entry = consistencyMap.get(s.queryId);
|
|
@@ -31030,7 +31170,7 @@ async function analyticsRoutes(app) {
|
|
|
31030
31170
|
answerMentioned: querySnapshots.answerMentioned,
|
|
31031
31171
|
answerText: querySnapshots.answerText,
|
|
31032
31172
|
citedDomains: querySnapshots.citedDomains
|
|
31033
|
-
}).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(
|
|
31173
|
+
}).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray19(querySnapshots.runId, latestGroupRunIds)).all());
|
|
31034
31174
|
const snapshots = rawSnapshots.map((s) => ({
|
|
31035
31175
|
...s,
|
|
31036
31176
|
resolvedMentioned: resolveSnapshotAnswerMentioned(s, project)
|
|
@@ -31197,8 +31337,8 @@ async function analyticsRoutes(app) {
|
|
|
31197
31337
|
eq37(runs.projectId, project.id),
|
|
31198
31338
|
eq37(runs.kind, RunKinds["answer-visibility"]),
|
|
31199
31339
|
notProbeRun(),
|
|
31200
|
-
latestRuns ?
|
|
31201
|
-
)).orderBy(
|
|
31340
|
+
latestRuns ? inArray19(runs.id, latestRuns.map((run) => run.id)) : requestedRunId ? eq37(runs.id, requestedRunId) : void 0
|
|
31341
|
+
)).orderBy(desc17(runs.createdAt), desc17(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => measuredWhole(app.db, r)).filter((r) => !cutoff || r.createdAt >= cutoff);
|
|
31202
31342
|
if (windowRuns.length === 0) {
|
|
31203
31343
|
return reply.send({
|
|
31204
31344
|
ranked: buildRankedList(/* @__PURE__ */ new Map(), limit, 0, 0),
|
|
@@ -31230,7 +31370,7 @@ async function analyticsRoutes(app) {
|
|
|
31230
31370
|
citedDomains: querySnapshots.citedDomains,
|
|
31231
31371
|
citedUrls: querySnapshots.citedUrls,
|
|
31232
31372
|
measurementExecutionId: querySnapshots.measurementExecutionId
|
|
31233
|
-
}).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(
|
|
31373
|
+
}).from(querySnapshots).leftJoin(queries, eq37(querySnapshots.queryId, queries.id)).where(inArray19(querySnapshots.runId, windowRunIds)).all();
|
|
31234
31374
|
let unclassifiedAnswers = 0;
|
|
31235
31375
|
let snapshots = loadedSnapshots;
|
|
31236
31376
|
if (splitByClass) {
|
|
@@ -31583,7 +31723,7 @@ function buildCategoryCounts(counts2) {
|
|
|
31583
31723
|
}
|
|
31584
31724
|
|
|
31585
31725
|
// ../api-routes/src/intelligence.ts
|
|
31586
|
-
import { eq as eq38, desc as
|
|
31726
|
+
import { eq as eq38, desc as desc18, and as and31, inArray as inArray20, like as like3 } from "drizzle-orm";
|
|
31587
31727
|
var SEVERITY_RANK = { low: 0, medium: 1, high: 2, critical: 3 };
|
|
31588
31728
|
function severitiesAtOrAbove(min2) {
|
|
31589
31729
|
const floor = SEVERITY_RANK[min2];
|
|
@@ -31713,7 +31853,7 @@ async function intelligenceRoutes(app) {
|
|
|
31713
31853
|
}
|
|
31714
31854
|
const severityFilter = request.query.severity?.trim();
|
|
31715
31855
|
if (severityFilter) {
|
|
31716
|
-
conditions.push(
|
|
31856
|
+
conditions.push(inArray20(insights.severity, severitiesAtOrAbove(severityFilter)));
|
|
31717
31857
|
}
|
|
31718
31858
|
let limit;
|
|
31719
31859
|
if (request.query.limit !== void 0) {
|
|
@@ -31723,7 +31863,7 @@ async function intelligenceRoutes(app) {
|
|
|
31723
31863
|
}
|
|
31724
31864
|
limit = parsed;
|
|
31725
31865
|
}
|
|
31726
|
-
const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and31(...conditions)).orderBy(
|
|
31866
|
+
const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and31(...conditions)).orderBy(desc18(insights.createdAt)).all();
|
|
31727
31867
|
const showDismissed = request.query.dismissed === "true";
|
|
31728
31868
|
let result = rows.filter((r) => showDismissed || !r.dismissed).map(mapInsightRow);
|
|
31729
31869
|
if (limit !== void 0) result = result.slice(0, limit);
|
|
@@ -31751,23 +31891,23 @@ async function intelligenceRoutes(app) {
|
|
|
31751
31891
|
const projectVisRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and31(
|
|
31752
31892
|
eq38(runs.projectId, project.id),
|
|
31753
31893
|
eq38(runs.kind, RunKinds["answer-visibility"]),
|
|
31754
|
-
|
|
31894
|
+
inArray20(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
31755
31895
|
// Health-latest is the dashboard headline; probe runs must not
|
|
31756
31896
|
// displace the most recent real visibility sweep.
|
|
31757
31897
|
notProbeRun()
|
|
31758
|
-
)).orderBy(
|
|
31898
|
+
)).orderBy(desc18(runs.createdAt), desc18(runs.id)).all();
|
|
31759
31899
|
const latestGroup = groupRunsByCreatedAt(projectVisRuns)[0] ?? [];
|
|
31760
31900
|
const latestGroupRunIds = latestGroup.map((r) => r.id);
|
|
31761
31901
|
if (latestGroupRunIds.length > 0) {
|
|
31762
31902
|
const groupRows = app.db.select().from(healthSnapshots).where(and31(
|
|
31763
31903
|
eq38(healthSnapshots.projectId, project.id),
|
|
31764
|
-
|
|
31904
|
+
inArray20(healthSnapshots.runId, latestGroupRunIds)
|
|
31765
31905
|
)).all();
|
|
31766
31906
|
if (groupRows.length > 0) {
|
|
31767
31907
|
return reply.send(aggregateHealthSnapshots(project.id, groupRows));
|
|
31768
31908
|
}
|
|
31769
31909
|
}
|
|
31770
|
-
const fallback = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(
|
|
31910
|
+
const fallback = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc18(healthSnapshots.createdAt)).limit(1).get();
|
|
31771
31911
|
if (!fallback) {
|
|
31772
31912
|
return reply.send(emptyHealthSnapshot(project.id));
|
|
31773
31913
|
}
|
|
@@ -31777,13 +31917,13 @@ async function intelligenceRoutes(app) {
|
|
|
31777
31917
|
const project = resolveProject(app.db, request.params.name);
|
|
31778
31918
|
const parsed = request.query.limit ? parseInt(request.query.limit, 10) : NaN;
|
|
31779
31919
|
const limit = Number.isNaN(parsed) ? 30 : Math.min(Math.max(parsed, 1), 100);
|
|
31780
|
-
const rows = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(
|
|
31920
|
+
const rows = app.db.select().from(healthSnapshots).where(eq38(healthSnapshots.projectId, project.id)).orderBy(desc18(healthSnapshots.createdAt)).limit(limit).all();
|
|
31781
31921
|
return reply.send(rows.map(mapHealthRow));
|
|
31782
31922
|
});
|
|
31783
31923
|
}
|
|
31784
31924
|
|
|
31785
31925
|
// ../api-routes/src/traffic-analytics.ts
|
|
31786
|
-
import { and as and33, desc as
|
|
31926
|
+
import { and as and33, desc as desc19, eq as eq39, gte as gte8, lt as lt8, lte as lte7, ne as ne8, sql as sql13 } from "drizzle-orm";
|
|
31787
31927
|
|
|
31788
31928
|
// ../api-routes/src/ai-referral-status.ts
|
|
31789
31929
|
import { and as and32, sql as sql12 } from "drizzle-orm";
|
|
@@ -31993,7 +32133,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
|
|
|
31993
32133
|
gte8(crawlerEventsHourly.tsHour, headlineStart),
|
|
31994
32134
|
lte7(crawlerEventsHourly.tsHour, headlineEnd)
|
|
31995
32135
|
)
|
|
31996
|
-
).groupBy(crawlerEventsHourly.pathNormalized).orderBy(
|
|
32136
|
+
).groupBy(crawlerEventsHourly.pathNormalized).orderBy(desc19(sql13`SUM(${crawlerEventsHourly.hits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
|
|
31997
32137
|
const topCrawledPaths = topPathsRows.map((r) => ({
|
|
31998
32138
|
path: r.path,
|
|
31999
32139
|
verifiedHits: Number(r.verifiedHits),
|
|
@@ -32011,7 +32151,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
|
|
|
32011
32151
|
gte8(aiReferralEventsHourly.tsHour, headlineStart),
|
|
32012
32152
|
lte7(aiReferralEventsHourly.tsHour, headlineEnd)
|
|
32013
32153
|
)
|
|
32014
|
-
).groupBy(aiReferralEventsHourly.product).orderBy(
|
|
32154
|
+
).groupBy(aiReferralEventsHourly.product).orderBy(desc19(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).all();
|
|
32015
32155
|
const referralProducts = referralProductsRows.map((r) => ({
|
|
32016
32156
|
product: r.product,
|
|
32017
32157
|
arrivals: Number(r.arrivals),
|
|
@@ -32028,7 +32168,7 @@ function readTrafficActivity(db, projectId, windowDays2) {
|
|
|
32028
32168
|
gte8(aiReferralEventsHourly.tsHour, headlineStart),
|
|
32029
32169
|
lte7(aiReferralEventsHourly.tsHour, headlineEnd)
|
|
32030
32170
|
)
|
|
32031
|
-
).groupBy(aiReferralEventsHourly.landingPathNormalized).orderBy(
|
|
32171
|
+
).groupBy(aiReferralEventsHourly.landingPathNormalized).orderBy(desc19(sql13`SUM(${aiReferralEventsHourly.sessionsOrHits})`)).limit(SERVER_ACTIVITY_TOP_PATHS_LIMIT).all();
|
|
32032
32172
|
const topReferralLandingPaths = topReferralRows.map((r) => ({
|
|
32033
32173
|
path: r.path,
|
|
32034
32174
|
arrivals: Number(r.arrivals),
|
|
@@ -32147,7 +32287,7 @@ async function trafficAnalyticsRoutes(app) {
|
|
|
32147
32287
|
}
|
|
32148
32288
|
|
|
32149
32289
|
// ../api-routes/src/referral-assessment.ts
|
|
32150
|
-
import { and as and34, desc as
|
|
32290
|
+
import { and as and34, desc as desc20, eq as eq40, gte as gte9, lte as lte8, ne as ne9, sql as sql14 } from "drizzle-orm";
|
|
32151
32291
|
|
|
32152
32292
|
// ../api-routes/src/ga-ai-referral-aggregation.ts
|
|
32153
32293
|
function normalizeAiTrafficClass(value) {
|
|
@@ -32296,7 +32436,7 @@ function buildAiReferralDailySeries(rows) {
|
|
|
32296
32436
|
var DEFAULT_BURST_THRESHOLD = 100;
|
|
32297
32437
|
var DEFAULT_RATIO_THRESHOLD = 3;
|
|
32298
32438
|
function latestGaSyncQueriedWindow(db, projectId, startDate, endDate) {
|
|
32299
|
-
const summary3 = db.select({ start: gaTrafficSummaries.periodStart, end: gaTrafficSummaries.periodEnd, syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq40(gaTrafficSummaries.projectId, projectId)).orderBy(
|
|
32439
|
+
const summary3 = db.select({ start: gaTrafficSummaries.periodStart, end: gaTrafficSummaries.periodEnd, syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq40(gaTrafficSummaries.projectId, projectId)).orderBy(desc20(gaTrafficSummaries.syncedAt)).limit(1).get();
|
|
32300
32440
|
if (!summary3 || startDate < summary3.start || endDate > summary3.end) return false;
|
|
32301
32441
|
const leftByAnotherSync = db.select({ id: gaAiReferrals.id }).from(gaAiReferrals).where(and34(
|
|
32302
32442
|
eq40(gaAiReferrals.projectId, projectId),
|
|
@@ -32414,7 +32554,7 @@ async function referralAssessmentRoutes(app) {
|
|
|
32414
32554
|
}
|
|
32415
32555
|
|
|
32416
32556
|
// ../api-routes/src/organic-evidence.ts
|
|
32417
|
-
import { and as and36, desc as
|
|
32557
|
+
import { and as and36, desc as desc21, eq as eq42, gte as gte11, lte as lte10, or as or11, sql as sql16 } from "drizzle-orm";
|
|
32418
32558
|
|
|
32419
32559
|
// ../api-routes/src/ga-measurement-analysis.ts
|
|
32420
32560
|
import { and as and35, eq as eq41, gte as gte10, lte as lte9, or as or10, sql as sql15 } from "drizzle-orm";
|
|
@@ -33136,7 +33276,7 @@ function buildOrganicEvidence(db, projectName, periodDays) {
|
|
|
33136
33276
|
eq42(runs.kind, RunKinds["answer-visibility"]),
|
|
33137
33277
|
eq42(runs.status, RunStatuses.completed),
|
|
33138
33278
|
notProbeRun()
|
|
33139
|
-
)).orderBy(
|
|
33279
|
+
)).orderBy(desc21(runs.createdAt)).get();
|
|
33140
33280
|
const snapshots = latest ? db.select().from(querySnapshots).where(eq42(querySnapshots.runId, latest.id)).all() : [];
|
|
33141
33281
|
const completedAt = latest ? latest.finishedAt ?? latest.createdAt : null;
|
|
33142
33282
|
const visibility = latest && completedAt ? {
|
|
@@ -33376,7 +33516,7 @@ async function organicEvidenceRoutes(app) {
|
|
|
33376
33516
|
}
|
|
33377
33517
|
|
|
33378
33518
|
// ../api-routes/src/citations.ts
|
|
33379
|
-
import { and as and37, eq as eq43, inArray as
|
|
33519
|
+
import { and as and37, eq as eq43, inArray as inArray21 } from "drizzle-orm";
|
|
33380
33520
|
async function citationRoutes(app) {
|
|
33381
33521
|
app.get("/projects/:name/citations/visibility", async (request, reply) => {
|
|
33382
33522
|
const project = resolveProject(app.db, request.params.name);
|
|
@@ -33400,7 +33540,7 @@ async function citationRoutes(app) {
|
|
|
33400
33540
|
competitorOverlap: querySnapshots.competitorOverlap,
|
|
33401
33541
|
answerMentioned: querySnapshots.answerMentioned,
|
|
33402
33542
|
createdAt: querySnapshots.createdAt
|
|
33403
|
-
}).from(querySnapshots).where(
|
|
33543
|
+
}).from(querySnapshots).where(inArray21(querySnapshots.runId, projectRuns.map((r) => r.id))).all();
|
|
33404
33544
|
if (rawSnapshots.length === 0) {
|
|
33405
33545
|
return reply.send(emptyCitationVisibility("no-runs-yet"));
|
|
33406
33546
|
}
|
|
@@ -33537,7 +33677,7 @@ function computeCitationVisibility(input) {
|
|
|
33537
33677
|
}
|
|
33538
33678
|
|
|
33539
33679
|
// ../api-routes/src/visibility-stats.ts
|
|
33540
|
-
import { and as and38, desc as
|
|
33680
|
+
import { and as and38, desc as desc22, eq as eq44, inArray as inArray22 } from "drizzle-orm";
|
|
33541
33681
|
|
|
33542
33682
|
// ../api-routes/src/visibility-compare.ts
|
|
33543
33683
|
var VISIBILITY_COMPARE_MIN_RUNS = 5;
|
|
@@ -34007,7 +34147,7 @@ async function visibilityStatsRoutes(app) {
|
|
|
34007
34147
|
lastRuns = n;
|
|
34008
34148
|
}
|
|
34009
34149
|
const projectQueries = app.db.select({ id: queries.id, query: queries.query }).from(queries).where(eq44(queries.projectId, project.id)).all();
|
|
34010
|
-
let projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt, status: runs.status }).from(runs).where(and38(eq44(runs.projectId, project.id), eq44(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(
|
|
34150
|
+
let projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt, status: runs.status }).from(runs).where(and38(eq44(runs.projectId, project.id), eq44(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc22(runs.createdAt)).all().filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial);
|
|
34011
34151
|
if (sinceMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) >= sinceMs);
|
|
34012
34152
|
if (untilMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) <= untilMs);
|
|
34013
34153
|
if (lastRuns !== null) projectRuns = projectRuns.slice(0, lastRuns);
|
|
@@ -34020,7 +34160,7 @@ async function visibilityStatsRoutes(app) {
|
|
|
34020
34160
|
citationState: querySnapshots.citationState,
|
|
34021
34161
|
answerMentioned: querySnapshots.answerMentioned,
|
|
34022
34162
|
createdAt: querySnapshots.createdAt
|
|
34023
|
-
}).from(querySnapshots).where(
|
|
34163
|
+
}).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
|
|
34024
34164
|
const stats = computeVisibilityStats({ queries: projectQueries, snapshots, groupBy });
|
|
34025
34165
|
const queryAttribution = buildQueryAttribution(projectQueries);
|
|
34026
34166
|
let shareOfVoice;
|
|
@@ -34031,7 +34171,7 @@ async function visibilityStatsRoutes(app) {
|
|
|
34031
34171
|
queryText: querySnapshots.queryText,
|
|
34032
34172
|
answerMentioned: querySnapshots.answerMentioned,
|
|
34033
34173
|
answerText: querySnapshots.answerText
|
|
34034
|
-
}).from(querySnapshots).where(
|
|
34174
|
+
}).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
|
|
34035
34175
|
const attributedSovSnapshots = sovSnapshots.filter((s) => resolveCurrentQuery(queryAttribution, s) !== void 0);
|
|
34036
34176
|
const advanced = activeMeasurementPlan(app.db, project.id)?.plan.schemaVersion === 2;
|
|
34037
34177
|
const queryClass = advanced || projectQueryClassifier(project) ? requestedQueryClass : "all";
|
|
@@ -34128,7 +34268,7 @@ function readVisibilityCompare(db, projectName, query) {
|
|
|
34128
34268
|
answerText: querySnapshots.answerText,
|
|
34129
34269
|
citedDomains: querySnapshots.citedDomains,
|
|
34130
34270
|
location: querySnapshots.location
|
|
34131
|
-
}).from(querySnapshots).where(
|
|
34271
|
+
}).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
|
|
34132
34272
|
return {
|
|
34133
34273
|
runCount: runIds.length,
|
|
34134
34274
|
snapshots: snapshots.filter((snapshot) => (providerKey2 === void 0 || normalizeText3(snapshot.provider) === providerKey2) && (locationKey2 === void 0 || (locationKey2 === "none" ? snapshot.location === null : snapshot.location !== null && normalizeText3(snapshot.location) === locationKey2)))
|
|
@@ -34239,7 +34379,7 @@ function readVisibilityContinuity(db, projectName, months) {
|
|
|
34239
34379
|
const trackedQueries = db.select({ id: queries.id, query: queries.query }).from(queries).where(eq44(queries.projectId, project.id)).all();
|
|
34240
34380
|
const loadProjectMonth = (bounds) => {
|
|
34241
34381
|
const runIds = legacyCompareRunIds(db, project.id, bounds);
|
|
34242
|
-
const rows = runIds.length > 0 && trackedQueries.length > 0 ? db.select({ queryId: querySnapshots.queryId, queryText: querySnapshots.queryText, provider: querySnapshots.provider, model: querySnapshots.model }).from(querySnapshots).where(
|
|
34382
|
+
const rows = runIds.length > 0 && trackedQueries.length > 0 ? db.select({ queryId: querySnapshots.queryId, queryText: querySnapshots.queryText, provider: querySnapshots.provider, model: querySnapshots.model }).from(querySnapshots).where(inArray22(querySnapshots.runId, runIds)).all() : [];
|
|
34243
34383
|
return { runCount: runIds.length, snapshots: rows.map(bare) };
|
|
34244
34384
|
};
|
|
34245
34385
|
const frames = [{ frame: "project", continuity: gate(trackedQueries, loadProjectMonth(fromBounds), loadProjectMonth(toBounds)) }];
|
|
@@ -34496,7 +34636,7 @@ async function resultsExportRoutes(app) {
|
|
|
34496
34636
|
}
|
|
34497
34637
|
|
|
34498
34638
|
// ../api-routes/src/composites.ts
|
|
34499
|
-
import { eq as eq47, and as and41, desc as
|
|
34639
|
+
import { eq as eq47, and as and41, desc as desc23, sql as sql18, like as like4, or as or12, inArray as inArray23 } from "drizzle-orm";
|
|
34500
34640
|
|
|
34501
34641
|
// ../api-routes/src/gsc-totals.ts
|
|
34502
34642
|
import { and as and40, asc as asc7, eq as eq46, sql as sql17, max, min } from "drizzle-orm";
|
|
@@ -34772,7 +34912,7 @@ async function compositeRoutes(app, options) {
|
|
|
34772
34912
|
const project = resolveProject(app.db, request.params.name);
|
|
34773
34913
|
const filterLocation = (request.query.location ?? "").trim() || null;
|
|
34774
34914
|
const sinceIso = parseSinceFilter(request.query.since);
|
|
34775
|
-
const allRunsRaw = app.db.select().from(runs).where(and41(eq47(runs.projectId, project.id), notProbeRun())).orderBy(
|
|
34915
|
+
const allRunsRaw = app.db.select().from(runs).where(and41(eq47(runs.projectId, project.id), notProbeRun())).orderBy(desc23(runs.createdAt), desc23(runs.id)).all();
|
|
34776
34916
|
const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
|
|
34777
34917
|
const totalRuns = allRuns.length;
|
|
34778
34918
|
const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
|
|
@@ -34785,9 +34925,9 @@ async function compositeRoutes(app, options) {
|
|
|
34785
34925
|
const previousVisibilityRun = pickGroupRepresentative(previousVisRunGroup);
|
|
34786
34926
|
const latestRunRow = allRuns[0] ?? null;
|
|
34787
34927
|
const latestRun = latestRunRow ? { totalRuns, run: summarizeRun(latestRunRow) } : { totalRuns: 0, run: null };
|
|
34788
|
-
const healthRow = app.db.select().from(healthSnapshots).where(eq47(healthSnapshots.projectId, project.id)).orderBy(
|
|
34928
|
+
const healthRow = app.db.select().from(healthSnapshots).where(eq47(healthSnapshots.projectId, project.id)).orderBy(desc23(healthSnapshots.createdAt)).limit(1).get();
|
|
34789
34929
|
const health = healthRow ? mapHealthRow2(healthRow) : null;
|
|
34790
|
-
const insightRows = app.db.select().from(insights).where(eq47(insights.projectId, project.id)).orderBy(
|
|
34930
|
+
const insightRows = app.db.select().from(insights).where(eq47(insights.projectId, project.id)).orderBy(desc23(insights.createdAt)).all();
|
|
34791
34931
|
const topInsights = insightRows.filter((row) => !row.dismissed).slice(0, TOP_INSIGHT_LIMIT).map(mapInsightRow2);
|
|
34792
34932
|
const sparklineRunIds = visibilityRuns.slice(0, DEFAULT_RUN_HISTORY_LIMIT).map((r) => r.id);
|
|
34793
34933
|
const snapshotRunIds = new Set(sparklineRunIds);
|
|
@@ -34959,7 +35099,7 @@ async function compositeRoutes(app, options) {
|
|
|
34959
35099
|
like4(queries.query, pattern)
|
|
34960
35100
|
)
|
|
34961
35101
|
)
|
|
34962
|
-
).orderBy(
|
|
35102
|
+
).orderBy(desc23(querySnapshots.createdAt)).limit(limit + 1).all());
|
|
34963
35103
|
const insightMatches = app.db.select().from(insights).where(
|
|
34964
35104
|
and41(
|
|
34965
35105
|
eq47(insights.projectId, project.id),
|
|
@@ -34970,7 +35110,7 @@ async function compositeRoutes(app, options) {
|
|
|
34970
35110
|
sql18`${insights.cause} LIKE ${pattern} ESCAPE '\\'`
|
|
34971
35111
|
)
|
|
34972
35112
|
)
|
|
34973
|
-
).orderBy(
|
|
35113
|
+
).orderBy(desc23(insights.createdAt)).limit(limit + 1).all();
|
|
34974
35114
|
const hits = [];
|
|
34975
35115
|
for (const row of snapshotMatches) {
|
|
34976
35116
|
hits.push(buildSnapshotHit(row, rawQuery));
|
|
@@ -35042,7 +35182,7 @@ function loadSnapshotsByRunIds(app, runIds, queryIdByText) {
|
|
|
35042
35182
|
rawResponse: querySnapshots.rawResponse,
|
|
35043
35183
|
competitorOverlap: querySnapshots.competitorOverlap,
|
|
35044
35184
|
citedDomains: querySnapshots.citedDomains
|
|
35045
|
-
}).from(querySnapshots).where(
|
|
35185
|
+
}).from(querySnapshots).where(inArray23(querySnapshots.runId, [...runIds])).all();
|
|
35046
35186
|
for (const row of rows) {
|
|
35047
35187
|
const queryText = row.queryText?.trim() || null;
|
|
35048
35188
|
let queryId;
|
|
@@ -35194,8 +35334,8 @@ function buildIndexCoverageScore(app, projectId) {
|
|
|
35194
35334
|
tooltip,
|
|
35195
35335
|
trend: []
|
|
35196
35336
|
};
|
|
35197
|
-
const gscRow = app.db.select().from(gscCoverageSnapshots).where(eq47(gscCoverageSnapshots.projectId, projectId)).orderBy(
|
|
35198
|
-
const bingRow = app.db.select().from(bingCoverageSnapshots).where(eq47(bingCoverageSnapshots.projectId, projectId)).orderBy(
|
|
35337
|
+
const gscRow = app.db.select().from(gscCoverageSnapshots).where(eq47(gscCoverageSnapshots.projectId, projectId)).orderBy(desc23(gscCoverageSnapshots.date)).limit(1).get();
|
|
35338
|
+
const bingRow = app.db.select().from(bingCoverageSnapshots).where(eq47(bingCoverageSnapshots.projectId, projectId)).orderBy(desc23(bingCoverageSnapshots.date)).limit(1).get();
|
|
35199
35339
|
const chosen = pickIndexCoverageRow(gscRow, bingRow);
|
|
35200
35340
|
if (!chosen) return empty;
|
|
35201
35341
|
const total = chosen.indexed + chosen.notIndexed;
|
|
@@ -35221,7 +35361,7 @@ function countGoogleDeindexedUrls(app, projectId) {
|
|
|
35221
35361
|
url: gscUrlInspections.url,
|
|
35222
35362
|
indexingState: gscUrlInspections.indexingState,
|
|
35223
35363
|
inspectedAt: gscUrlInspections.inspectedAt
|
|
35224
|
-
}).from(gscUrlInspections).where(eq47(gscUrlInspections.projectId, projectId)).orderBy(
|
|
35364
|
+
}).from(gscUrlInspections).where(eq47(gscUrlInspections.projectId, projectId)).orderBy(desc23(gscUrlInspections.inspectedAt)).all();
|
|
35225
35365
|
if (rows.length === 0) return 0;
|
|
35226
35366
|
const canonicalUrl = (url) => url.replace(/^http:\/\//, "https://");
|
|
35227
35367
|
const historyByUrl = /* @__PURE__ */ new Map();
|
|
@@ -35477,10 +35617,10 @@ function makeSnippet(text2, query) {
|
|
|
35477
35617
|
|
|
35478
35618
|
// ../api-routes/src/content.ts
|
|
35479
35619
|
import crypto24 from "crypto";
|
|
35480
|
-
import { and as and43, desc as
|
|
35620
|
+
import { and as and43, desc as desc25, eq as eq49 } from "drizzle-orm";
|
|
35481
35621
|
|
|
35482
35622
|
// ../api-routes/src/content-data.ts
|
|
35483
|
-
import { and as and42, eq as eq48, desc as
|
|
35623
|
+
import { and as and42, eq as eq48, desc as desc24, gte as gte13, inArray as inArray24, lte as lte12 } from "drizzle-orm";
|
|
35484
35624
|
var RECENT_RUNS_WINDOW = 5;
|
|
35485
35625
|
function loadOrchestratorInput(db, project, locationFilter = void 0, gscWindowDays = DEFAULT_CONTENT_GSC_WINDOW_DAYS) {
|
|
35486
35626
|
const projectId = project.id;
|
|
@@ -35620,12 +35760,12 @@ function listRecentAnswerVisibilityRunIds(db, projectId, limit, locationFilter)
|
|
|
35620
35760
|
// Queued/running/failed/cancelled runs may have partial or no
|
|
35621
35761
|
// snapshots; including them risks pointing latestRunId at a run with
|
|
35622
35762
|
// no usable evidence.
|
|
35623
|
-
|
|
35763
|
+
inArray24(runs.status, [RunStatuses.completed, RunStatuses.partial]),
|
|
35624
35764
|
// Probe runs are operator/agent test runs; they must not poison the
|
|
35625
35765
|
// recent-runs window the content engine uses to recommend actions.
|
|
35626
35766
|
notProbeRun()
|
|
35627
35767
|
)
|
|
35628
|
-
).orderBy(
|
|
35768
|
+
).orderBy(desc24(runs.createdAt)).all();
|
|
35629
35769
|
const filtered = locationFilter === void 0 ? rows : rows.filter((r) => (r.location ?? null) === locationFilter);
|
|
35630
35770
|
return filtered.slice(0, limit).map((r) => r.id);
|
|
35631
35771
|
}
|
|
@@ -35660,7 +35800,7 @@ function buildGaTrafficByPage(db, projectId, window) {
|
|
|
35660
35800
|
return map;
|
|
35661
35801
|
}
|
|
35662
35802
|
function resolveContentGaWindow(db, projectId, windowDays2) {
|
|
35663
|
-
const latest = db.select({ date: gaTrafficSnapshots.date }).from(gaTrafficSnapshots).where(eq48(gaTrafficSnapshots.projectId, projectId)).orderBy(
|
|
35803
|
+
const latest = db.select({ date: gaTrafficSnapshots.date }).from(gaTrafficSnapshots).where(eq48(gaTrafficSnapshots.projectId, projectId)).orderBy(desc24(gaTrafficSnapshots.date)).limit(1).get();
|
|
35664
35804
|
if (!latest?.date) return null;
|
|
35665
35805
|
const end = /* @__PURE__ */ new Date(`${latest.date}T00:00:00Z`);
|
|
35666
35806
|
end.setUTCDate(end.getUTCDate() - (Math.max(1, windowDays2) - 1));
|
|
@@ -35688,7 +35828,7 @@ function buildCandidateQueries(opts) {
|
|
|
35688
35828
|
const queryRows2 = opts.db.select({ id: queries.id, text: queries.query }).from(queries).where(eq48(queries.projectId, opts.projectId)).all();
|
|
35689
35829
|
const queryIdByText = new Map(queryRows2.map((r) => [r.text, r.id]));
|
|
35690
35830
|
const candidateQueryIds = opts.candidateQueryStrings.map((q) => queryIdByText.get(q)).filter((id) => Boolean(id));
|
|
35691
|
-
const snapshotRows = filterTrackedSnapshots(opts.db.select().from(querySnapshots).where(
|
|
35831
|
+
const snapshotRows = filterTrackedSnapshots(opts.db.select().from(querySnapshots).where(inArray24(querySnapshots.runId, opts.recentRunIds)).all()).filter((r) => candidateQueryIds.includes(r.queryId));
|
|
35692
35832
|
const snapshotsByQuery = /* @__PURE__ */ new Map();
|
|
35693
35833
|
for (const row of snapshotRows) {
|
|
35694
35834
|
const list = snapshotsByQuery.get(row.queryId) ?? [];
|
|
@@ -36088,7 +36228,7 @@ async function contentRoutes(app, opts = {}) {
|
|
|
36088
36228
|
const row = app.db.select().from(recommendationExplanations).where(and43(
|
|
36089
36229
|
eq49(recommendationExplanations.projectId, project.id),
|
|
36090
36230
|
eq49(recommendationExplanations.targetRef, request.params.targetRef)
|
|
36091
|
-
)).orderBy(
|
|
36231
|
+
)).orderBy(desc25(recommendationExplanations.generatedAt)).limit(1).get();
|
|
36092
36232
|
if (!row) {
|
|
36093
36233
|
return reply.status(404).send({ error: { code: "NOT_FOUND", message: "No cached explanation for this targetRef." } });
|
|
36094
36234
|
}
|
|
@@ -36116,7 +36256,7 @@ async function contentRoutes(app, opts = {}) {
|
|
|
36116
36256
|
const cached = app.db.select().from(recommendationExplanations).where(and43(
|
|
36117
36257
|
eq49(recommendationExplanations.projectId, project.id),
|
|
36118
36258
|
eq49(recommendationExplanations.targetRef, targetRef)
|
|
36119
|
-
)).orderBy(
|
|
36259
|
+
)).orderBy(desc25(recommendationExplanations.generatedAt)).limit(1).get();
|
|
36120
36260
|
if (cached) return reply.send(formatExplanationRow(cached));
|
|
36121
36261
|
}
|
|
36122
36262
|
const result = await explainer({
|
|
@@ -36246,7 +36386,7 @@ async function contentRoutes(app, opts = {}) {
|
|
|
36246
36386
|
});
|
|
36247
36387
|
app.get("/projects/:name/content/domain-classifications", async (request) => {
|
|
36248
36388
|
const project = resolveProject(app.db, request.params.name);
|
|
36249
|
-
const rows = app.db.select().from(domainClassifications).where(eq49(domainClassifications.projectId, project.id)).orderBy(
|
|
36389
|
+
const rows = app.db.select().from(domainClassifications).where(eq49(domainClassifications.projectId, project.id)).orderBy(desc25(domainClassifications.hits)).all();
|
|
36250
36390
|
const response = {
|
|
36251
36391
|
classifications: rows.map((r) => ({
|
|
36252
36392
|
domain: r.domain,
|
|
@@ -36266,7 +36406,7 @@ function lookupCachedBrief(db, projectId, targetRef, promptVersion) {
|
|
|
36266
36406
|
if (promptVersion !== void 0) {
|
|
36267
36407
|
conditions.push(eq49(recommendationBriefs.promptVersion, promptVersion));
|
|
36268
36408
|
}
|
|
36269
|
-
return db.select().from(recommendationBriefs).where(and43(...conditions)).orderBy(
|
|
36409
|
+
return db.select().from(recommendationBriefs).where(and43(...conditions)).orderBy(desc25(recommendationBriefs.generatedAt)).limit(1).get();
|
|
36270
36410
|
}
|
|
36271
36411
|
function parseLimitParam(raw) {
|
|
36272
36412
|
if (raw === void 0) return void 0;
|
|
@@ -38832,7 +38972,11 @@ var routeCatalog = [
|
|
|
38832
38972
|
location: stringSchema,
|
|
38833
38973
|
allLocations: booleanSchema,
|
|
38834
38974
|
noLocation: booleanSchema,
|
|
38835
|
-
dispatchMode: dispatchModeRequestSchema
|
|
38975
|
+
dispatchMode: dispatchModeRequestSchema,
|
|
38976
|
+
force: {
|
|
38977
|
+
type: "boolean",
|
|
38978
|
+
description: "Queue the run even when it would be refused with PROVIDERS_FAILING. Admission only; never stored."
|
|
38979
|
+
}
|
|
38836
38980
|
}
|
|
38837
38981
|
}
|
|
38838
38982
|
}
|
|
@@ -38843,7 +38987,9 @@ var routeCatalog = [
|
|
|
38843
38987
|
400: errorResponse(
|
|
38844
38988
|
'Invalid request: an untracked query, a measurement scope naming a group/target/question the published plan does not contain, a scope combined with a query list, a per-run location on a plan project, a provider roster the plan was not published for, or `dispatchMode: "batch"` when no provider of the run can batch (`details.ineligible` names each provider\'s reason).'
|
|
38845
38989
|
),
|
|
38846
|
-
422: errorResponse(
|
|
38990
|
+
422: errorResponse(
|
|
38991
|
+
`NO_QUERIES: the project has no tracked queries. PROVIDERS_FAILING: every provider the run would call failed on its account (rejected key, denied access, no credit) in each of its last ${PROVIDER_ACCOUNT_FAILURE_STREAK} runs. \`details.providers\` names each provider's code and \`details.retryAfter\` when one run is let through again (${PROVIDER_ACCOUNT_RETRY_HOURS}h after the newest failure). Saving a new key, model or endpoint in a provider's settings lets the next run through at once, a probe is never refused, and \`force: true\` overrides.`
|
|
38992
|
+
),
|
|
38847
38993
|
409: errorResponse("Run already in progress."),
|
|
38848
38994
|
503: errorResponse("No runnable answer provider is configured.")
|
|
38849
38995
|
}
|
|
@@ -38897,7 +39043,11 @@ var routeCatalog = [
|
|
|
38897
39043
|
properties: {
|
|
38898
39044
|
kind: stringSchema,
|
|
38899
39045
|
providers: stringArraySchema,
|
|
38900
|
-
dispatchMode: dispatchModeRequestSchema
|
|
39046
|
+
dispatchMode: dispatchModeRequestSchema,
|
|
39047
|
+
force: {
|
|
39048
|
+
type: "boolean",
|
|
39049
|
+
description: "Queue projects that would be refused with PROVIDERS_FAILING. Admission only; never stored."
|
|
39050
|
+
}
|
|
38901
39051
|
}
|
|
38902
39052
|
}
|
|
38903
39053
|
}
|
|
@@ -38906,7 +39056,7 @@ var routeCatalog = [
|
|
|
38906
39056
|
responses: {
|
|
38907
39057
|
// TODO: Add `TriggerAllRunsResponse` Zod schema in contracts.
|
|
38908
39058
|
207: rawJsonResponse(
|
|
38909
|
-
"One row per project: either a queued run or an error for that project alone. A project that cannot be measured (for example one whose published measurement plan expects a different number of answers per question) never prevents or hides the others.",
|
|
39059
|
+
"One row per project: either a queued run or an error for that project alone. A project that cannot be measured (for example one whose published measurement plan expects a different number of answers per question, or one whose providers all keep failing on their accounts: `errorCode: PROVIDERS_FAILING`) never prevents or hides the others.",
|
|
38910
39060
|
{ type: "array", items: looseObjectSchema }
|
|
38911
39061
|
),
|
|
38912
39062
|
400: errorResponse("Invalid request: an unknown provider name, or an unsupported run kind.")
|
|
@@ -44154,7 +44304,7 @@ function buildOperationId(method, path8) {
|
|
|
44154
44304
|
|
|
44155
44305
|
// ../api-routes/src/keys.ts
|
|
44156
44306
|
import crypto25 from "crypto";
|
|
44157
|
-
import { desc as
|
|
44307
|
+
import { desc as desc26, eq as eq50 } from "drizzle-orm";
|
|
44158
44308
|
var KEYS_WRITE_SCOPE = "keys.write";
|
|
44159
44309
|
function toApiKeyDto(row, projectNames) {
|
|
44160
44310
|
const scopes = Array.isArray(row.scopes) ? row.scopes : [];
|
|
@@ -44179,7 +44329,7 @@ async function keysRoutes(app) {
|
|
|
44179
44329
|
app.get("/keys", async (request) => {
|
|
44180
44330
|
requireAdminSession(request);
|
|
44181
44331
|
const scopedProjectId = request.apiKey?.projectId;
|
|
44182
|
-
const rows = scopedProjectId ? app.db.select().from(apiKeys).where(eq50(apiKeys.projectId, scopedProjectId)).orderBy(
|
|
44332
|
+
const rows = scopedProjectId ? app.db.select().from(apiKeys).where(eq50(apiKeys.projectId, scopedProjectId)).orderBy(desc26(apiKeys.createdAt)).all() : app.db.select().from(apiKeys).orderBy(desc26(apiKeys.createdAt)).all();
|
|
44183
44333
|
const names = projectNameById(app.db);
|
|
44184
44334
|
return { keys: rows.map((row) => toApiKeyDto(row, names)) };
|
|
44185
44335
|
});
|
|
@@ -45181,7 +45331,7 @@ function formatNotification(row) {
|
|
|
45181
45331
|
|
|
45182
45332
|
// ../api-routes/src/google.ts
|
|
45183
45333
|
import crypto33 from "crypto";
|
|
45184
|
-
import { eq as eq54, and as and45, desc as
|
|
45334
|
+
import { eq as eq54, and as and45, desc as desc27, sql as sql19, inArray as inArray25 } from "drizzle-orm";
|
|
45185
45335
|
|
|
45186
45336
|
// ../api-routes/src/gsc-period-comparison.ts
|
|
45187
45337
|
var DAY_MS = 864e5;
|
|
@@ -47692,9 +47842,9 @@ async function googleRoutes(app, opts) {
|
|
|
47692
47842
|
const limitVal = Math.max(parseInt(limit ?? "500", 10) || 0, 1);
|
|
47693
47843
|
const offsetVal = Math.max(parseInt(offset ?? "0", 10) || 0, 0);
|
|
47694
47844
|
const orderColumns = {
|
|
47695
|
-
clicks: [
|
|
47696
|
-
impressions: [
|
|
47697
|
-
date: [
|
|
47845
|
+
clicks: [desc27(gscSearchData.clicks), desc27(gscSearchData.date), gscSearchData.query],
|
|
47846
|
+
impressions: [desc27(gscSearchData.impressions), desc27(gscSearchData.date), gscSearchData.query],
|
|
47847
|
+
date: [desc27(gscSearchData.date), desc27(gscSearchData.clicks), gscSearchData.query]
|
|
47698
47848
|
}[orderBy];
|
|
47699
47849
|
const rows = app.db.select().from(gscSearchData).where(and45(...conditions)).orderBy(...orderColumns).limit(limitVal).offset(offsetVal).all();
|
|
47700
47850
|
const totalMatching = app.db.select({ total: sql19`COUNT(*)` }).from(gscSearchData).where(and45(...conditions)).get()?.total ?? 0;
|
|
@@ -47853,7 +48003,7 @@ async function googleRoutes(app, opts) {
|
|
|
47853
48003
|
page: gscSearchData.page,
|
|
47854
48004
|
clicks: sql19`COALESCE(SUM(${gscSearchData.clicks}), 0)`,
|
|
47855
48005
|
impressions: sql19`COALESCE(SUM(${gscSearchData.impressions}), 0)`
|
|
47856
|
-
}).from(gscSearchData).where(and45(...conditions)).groupBy(gscSearchData.page).orderBy(
|
|
48006
|
+
}).from(gscSearchData).where(and45(...conditions)).groupBy(gscSearchData.page).orderBy(desc27(sql19`SUM(${gscSearchData.clicks})`), desc27(sql19`SUM(${gscSearchData.impressions})`)).limit(limitVal).all();
|
|
47857
48007
|
const windowStart = startDate ?? cutoffDate ?? "";
|
|
47858
48008
|
const windowEnd = endDate ?? resolvedWindow.endDate ?? "9999-12-31";
|
|
47859
48009
|
const dailyTotals = readGscDailyTotals(app.db, project.id, windowStart, windowEnd);
|
|
@@ -47996,7 +48146,7 @@ async function googleRoutes(app, opts) {
|
|
|
47996
48146
|
const { url, limit } = request.query;
|
|
47997
48147
|
const conditions = [eq54(gscUrlInspections.projectId, project.id)];
|
|
47998
48148
|
if (url) conditions.push(eq54(gscUrlInspections.url, url));
|
|
47999
|
-
const rows = app.db.select().from(gscUrlInspections).where(and45(...conditions)).orderBy(
|
|
48149
|
+
const rows = app.db.select().from(gscUrlInspections).where(and45(...conditions)).orderBy(desc27(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
|
|
48000
48150
|
return rows.map((r) => ({
|
|
48001
48151
|
id: r.id,
|
|
48002
48152
|
url: r.url,
|
|
@@ -48015,7 +48165,7 @@ async function googleRoutes(app, opts) {
|
|
|
48015
48165
|
});
|
|
48016
48166
|
app.get("/projects/:name/google/gsc/deindexed", async (request) => {
|
|
48017
48167
|
const project = resolveProject(app.db, request.params.name);
|
|
48018
|
-
const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(
|
|
48168
|
+
const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
|
|
48019
48169
|
const byUrl = /* @__PURE__ */ new Map();
|
|
48020
48170
|
for (const row of allInspections) {
|
|
48021
48171
|
const existing = byUrl.get(row.url);
|
|
@@ -48043,7 +48193,7 @@ async function googleRoutes(app, opts) {
|
|
|
48043
48193
|
});
|
|
48044
48194
|
app.get("/projects/:name/google/gsc/coverage", async (request) => {
|
|
48045
48195
|
const project = resolveProject(app.db, request.params.name);
|
|
48046
|
-
const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(
|
|
48196
|
+
const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
|
|
48047
48197
|
const canonicalUrl = (url) => url.replace(/^http:\/\//, "https://");
|
|
48048
48198
|
const latestByUrl = /* @__PURE__ */ new Map();
|
|
48049
48199
|
const historyByUrl = /* @__PURE__ */ new Map();
|
|
@@ -48092,7 +48242,7 @@ async function googleRoutes(app, opts) {
|
|
|
48092
48242
|
const total = latestByUrl.size;
|
|
48093
48243
|
const indexed = indexedUrls.length;
|
|
48094
48244
|
const notIndexed = notIndexedUrls.length;
|
|
48095
|
-
const latestSnapshot = app.db.select({ createdAt: gscCoverageSnapshots.createdAt }).from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(
|
|
48245
|
+
const latestSnapshot = app.db.select({ createdAt: gscCoverageSnapshots.createdAt }).from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc27(gscCoverageSnapshots.createdAt)).limit(1).get();
|
|
48096
48246
|
const lastSyncedAt = latestSnapshot?.createdAt ?? null;
|
|
48097
48247
|
const formatRow = (r) => ({
|
|
48098
48248
|
id: r.id,
|
|
@@ -48148,7 +48298,7 @@ async function googleRoutes(app, opts) {
|
|
|
48148
48298
|
const project = resolveProject(app.db, request.params.name);
|
|
48149
48299
|
const parsed = parseInt(request.query.limit ?? "90", 10);
|
|
48150
48300
|
const limit = Number.isNaN(parsed) || parsed <= 0 ? 90 : parsed;
|
|
48151
|
-
const rows = app.db.select().from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(
|
|
48301
|
+
const rows = app.db.select().from(gscCoverageSnapshots).where(eq54(gscCoverageSnapshots.projectId, project.id)).orderBy(desc27(gscCoverageSnapshots.date)).limit(limit).all();
|
|
48152
48302
|
return rows.map((r) => ({
|
|
48153
48303
|
date: r.date,
|
|
48154
48304
|
indexed: r.indexed,
|
|
@@ -48362,7 +48512,7 @@ async function googleRoutes(app, opts) {
|
|
|
48362
48512
|
const { accessToken } = await getValidToken(store, project.canonicalDomain, "gsc", googleClientId, googleClientSecret);
|
|
48363
48513
|
let urlsToNotify = request.body?.urls ?? [];
|
|
48364
48514
|
if (request.body?.allUnindexed) {
|
|
48365
|
-
const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(
|
|
48515
|
+
const allInspections = app.db.select().from(gscUrlInspections).where(eq54(gscUrlInspections.projectId, project.id)).orderBy(desc27(gscUrlInspections.inspectedAt)).all();
|
|
48366
48516
|
const latestByUrl = /* @__PURE__ */ new Map();
|
|
48367
48517
|
for (const row of allInspections) {
|
|
48368
48518
|
if (!latestByUrl.has(row.url)) {
|
|
@@ -48729,7 +48879,7 @@ async function googleRoutes(app, opts) {
|
|
|
48729
48879
|
const conditions = [eq54(gbpDailyMetrics.projectId, project.id)];
|
|
48730
48880
|
if (request.query.locationName) conditions.push(eq54(gbpDailyMetrics.locationName, request.query.locationName));
|
|
48731
48881
|
if (request.query.metric) conditions.push(eq54(gbpDailyMetrics.metric, request.query.metric));
|
|
48732
|
-
const rows = app.db.select().from(gbpDailyMetrics).where(and45(...conditions)).orderBy(
|
|
48882
|
+
const rows = app.db.select().from(gbpDailyMetrics).where(and45(...conditions)).orderBy(desc27(gbpDailyMetrics.date)).all();
|
|
48733
48883
|
return {
|
|
48734
48884
|
metrics: rows.map((r) => ({ locationName: r.locationName, date: r.date, metric: r.metric, value: r.value })),
|
|
48735
48885
|
total: rows.length
|
|
@@ -48776,7 +48926,7 @@ async function googleRoutes(app, opts) {
|
|
|
48776
48926
|
const project = resolveProject(app.db, request.params.name);
|
|
48777
48927
|
const conditions = [eq54(gbpLodgingSnapshots.projectId, project.id)];
|
|
48778
48928
|
if (request.query.locationName) conditions.push(eq54(gbpLodgingSnapshots.locationName, request.query.locationName));
|
|
48779
|
-
const rows = app.db.select().from(gbpLodgingSnapshots).where(and45(...conditions)).orderBy(
|
|
48929
|
+
const rows = app.db.select().from(gbpLodgingSnapshots).where(and45(...conditions)).orderBy(desc27(gbpLodgingSnapshots.syncedAt)).all();
|
|
48780
48930
|
const latestByLocation = /* @__PURE__ */ new Map();
|
|
48781
48931
|
for (const row of rows) {
|
|
48782
48932
|
if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
|
|
@@ -48793,7 +48943,7 @@ async function googleRoutes(app, opts) {
|
|
|
48793
48943
|
const project = resolveProject(app.db, request.params.name);
|
|
48794
48944
|
const conditions = [eq54(gbpAttributesSnapshots.projectId, project.id)];
|
|
48795
48945
|
if (request.query.locationName) conditions.push(eq54(gbpAttributesSnapshots.locationName, request.query.locationName));
|
|
48796
|
-
const rows = app.db.select().from(gbpAttributesSnapshots).where(and45(...conditions)).orderBy(
|
|
48946
|
+
const rows = app.db.select().from(gbpAttributesSnapshots).where(and45(...conditions)).orderBy(desc27(gbpAttributesSnapshots.syncedAt)).all();
|
|
48797
48947
|
const latestByLocation = /* @__PURE__ */ new Map();
|
|
48798
48948
|
for (const row of rows) {
|
|
48799
48949
|
if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
|
|
@@ -48813,7 +48963,7 @@ async function googleRoutes(app, opts) {
|
|
|
48813
48963
|
const project = resolveProject(app.db, request.params.name);
|
|
48814
48964
|
const conditions = [eq54(gbpPlaceDetails.projectId, project.id)];
|
|
48815
48965
|
if (request.query.locationName) conditions.push(eq54(gbpPlaceDetails.locationName, request.query.locationName));
|
|
48816
|
-
const rows = app.db.select().from(gbpPlaceDetails).where(and45(...conditions)).orderBy(
|
|
48966
|
+
const rows = app.db.select().from(gbpPlaceDetails).where(and45(...conditions)).orderBy(desc27(gbpPlaceDetails.syncedAt)).all();
|
|
48817
48967
|
const latestByLocation = /* @__PURE__ */ new Map();
|
|
48818
48968
|
for (const row of rows) {
|
|
48819
48969
|
if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
|
|
@@ -48840,7 +48990,7 @@ async function googleRoutes(app, opts) {
|
|
|
48840
48990
|
locationName ? eq54(gbpLocations.locationName, locationName) : eq54(gbpLocations.selected, true)
|
|
48841
48991
|
)).orderBy(gbpLocations.displayName).all();
|
|
48842
48992
|
const latestRating = /* @__PURE__ */ new Map();
|
|
48843
|
-
for (const row of app.db.select().from(gbpReviewRatings).where(eq54(gbpReviewRatings.projectId, project.id)).orderBy(
|
|
48993
|
+
for (const row of app.db.select().from(gbpReviewRatings).where(eq54(gbpReviewRatings.projectId, project.id)).orderBy(desc27(gbpReviewRatings.observedAt)).all()) {
|
|
48844
48994
|
if (!latestRating.has(row.locationName)) latestRating.set(row.locationName, row);
|
|
48845
48995
|
}
|
|
48846
48996
|
const locations = locationRows.map((loc) => {
|
|
@@ -48861,7 +49011,7 @@ async function googleRoutes(app, opts) {
|
|
|
48861
49011
|
if (locationName) conditions.push(eq54(gbpReviews.locationName, locationName));
|
|
48862
49012
|
if (negativeOnly) conditions.push(sql19`${gbpReviews.starRating} BETWEEN 1 AND ${negativeMaxStars}`);
|
|
48863
49013
|
const total = app.db.select({ n: sql19`count(*)` }).from(gbpReviews).where(and45(...conditions)).get()?.n ?? 0;
|
|
48864
|
-
const reviews = app.db.select().from(gbpReviews).where(and45(...conditions)).orderBy(
|
|
49014
|
+
const reviews = app.db.select().from(gbpReviews).where(and45(...conditions)).orderBy(desc27(gbpReviews.updateTime), gbpReviews.reviewName).limit(limit).all().map((r) => ({
|
|
48865
49015
|
locationName: r.locationName,
|
|
48866
49016
|
origin: r.origin,
|
|
48867
49017
|
reviewName: r.reviewName,
|
|
@@ -48900,10 +49050,10 @@ async function googleRoutes(app, opts) {
|
|
|
48900
49050
|
locationProfiles: []
|
|
48901
49051
|
});
|
|
48902
49052
|
}
|
|
48903
|
-
const metricRows = app.db.select().from(gbpDailyMetrics).where(and45(eq54(gbpDailyMetrics.projectId, project.id),
|
|
48904
|
-
const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and45(eq54(gbpKeywordImpressions.projectId, project.id),
|
|
48905
|
-
const placeActionRows = app.db.select().from(gbpPlaceActions).where(and45(eq54(gbpPlaceActions.projectId, project.id),
|
|
48906
|
-
const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and45(eq54(gbpLodgingSnapshots.projectId, project.id),
|
|
49053
|
+
const metricRows = app.db.select().from(gbpDailyMetrics).where(and45(eq54(gbpDailyMetrics.projectId, project.id), inArray25(gbpDailyMetrics.locationName, locationNames))).all();
|
|
49054
|
+
const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and45(eq54(gbpKeywordImpressions.projectId, project.id), inArray25(gbpKeywordImpressions.locationName, locationNames))).all();
|
|
49055
|
+
const placeActionRows = app.db.select().from(gbpPlaceActions).where(and45(eq54(gbpPlaceActions.projectId, project.id), inArray25(gbpPlaceActions.locationName, locationNames))).all();
|
|
49056
|
+
const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and45(eq54(gbpLodgingSnapshots.projectId, project.id), inArray25(gbpLodgingSnapshots.locationName, locationNames))).orderBy(desc27(gbpLodgingSnapshots.syncedAt)).all();
|
|
48907
49057
|
const latestLodgingByLocation = /* @__PURE__ */ new Map();
|
|
48908
49058
|
for (const row of lodgingRows) {
|
|
48909
49059
|
if (!latestLodgingByLocation.has(row.locationName)) {
|
|
@@ -48917,7 +49067,7 @@ async function googleRoutes(app, opts) {
|
|
|
48917
49067
|
regularHours: gbpLocations.regularHours,
|
|
48918
49068
|
primaryPhone: gbpLocations.primaryPhone,
|
|
48919
49069
|
openStatus: gbpLocations.openStatus
|
|
48920
|
-
}).from(gbpLocations).where(and45(eq54(gbpLocations.projectId, project.id),
|
|
49070
|
+
}).from(gbpLocations).where(and45(eq54(gbpLocations.projectId, project.id), inArray25(gbpLocations.locationName, locationNames))).all();
|
|
48921
49071
|
return buildGbpSummary({
|
|
48922
49072
|
locationName,
|
|
48923
49073
|
locationCount: locationNames.length,
|
|
@@ -48948,7 +49098,7 @@ function parseReviewLimit(value) {
|
|
|
48948
49098
|
|
|
48949
49099
|
// ../api-routes/src/google-marketing.ts
|
|
48950
49100
|
import crypto34 from "crypto";
|
|
48951
|
-
import { and as and46, desc as
|
|
49101
|
+
import { and as and46, desc as desc28, eq as eq55, isNull as isNull10, lt as lt9, ne as ne10, or as or13, sql as sql20 } from "drizzle-orm";
|
|
48952
49102
|
import { z as z4 } from "zod";
|
|
48953
49103
|
var snapshotPageQuerySchema = z4.object({
|
|
48954
49104
|
limit: z4.coerce.number().int().min(1).max(GOOGLE_MARKETING_STORED_SNAPSHOT_PAGE_MAX).optional(),
|
|
@@ -50164,7 +50314,7 @@ async function googleMarketingRoutes(app, opts) {
|
|
|
50164
50314
|
eq55(runs.projectId, project.id),
|
|
50165
50315
|
eq55(runs.kind, RunKinds["google-ads-sync"]),
|
|
50166
50316
|
or13(eq55(runs.status, RunStatuses.queued), eq55(runs.status, RunStatuses.running))
|
|
50167
|
-
)).orderBy(
|
|
50317
|
+
)).orderBy(desc28(runs.createdAt)).get();
|
|
50168
50318
|
if (existing) {
|
|
50169
50319
|
run = existing;
|
|
50170
50320
|
return;
|
|
@@ -50200,7 +50350,7 @@ async function googleMarketingRoutes(app, opts) {
|
|
|
50200
50350
|
eq55(runs.projectId, project.id),
|
|
50201
50351
|
eq55(runs.kind, RunKinds["gtm-sync"]),
|
|
50202
50352
|
or13(eq55(runs.status, RunStatuses.queued), eq55(runs.status, RunStatuses.running))
|
|
50203
|
-
)).orderBy(
|
|
50353
|
+
)).orderBy(desc28(runs.createdAt)).get();
|
|
50204
50354
|
if (existing) {
|
|
50205
50355
|
run = existing;
|
|
50206
50356
|
return;
|
|
@@ -50235,7 +50385,7 @@ async function googleMarketingRoutes(app, opts) {
|
|
|
50235
50385
|
));
|
|
50236
50386
|
}
|
|
50237
50387
|
const limit = query.limit ?? 50;
|
|
50238
|
-
const rows = app.db.select().from(googleAdsRawSnapshots).where(and46(...conditions)).orderBy(
|
|
50388
|
+
const rows = app.db.select().from(googleAdsRawSnapshots).where(and46(...conditions)).orderBy(desc28(googleAdsRawSnapshots.capturedAt), desc28(googleAdsRawSnapshots.id)).limit(limit + 1).all();
|
|
50239
50389
|
const page3 = rows.slice(0, limit);
|
|
50240
50390
|
const total = app.db.select({ total: sql20`COUNT(*)`.mapWith(Number).as("total") }).from(googleAdsRawSnapshots).where(eq55(googleAdsRawSnapshots.projectId, project.id)).get();
|
|
50241
50391
|
return {
|
|
@@ -50267,7 +50417,7 @@ async function googleMarketingRoutes(app, opts) {
|
|
|
50267
50417
|
));
|
|
50268
50418
|
}
|
|
50269
50419
|
const limit = query.limit ?? 50;
|
|
50270
|
-
const rows = app.db.select().from(gtmRawSnapshots).where(and46(...conditions)).orderBy(
|
|
50420
|
+
const rows = app.db.select().from(gtmRawSnapshots).where(and46(...conditions)).orderBy(desc28(gtmRawSnapshots.capturedAt), desc28(gtmRawSnapshots.id)).limit(limit + 1).all();
|
|
50271
50421
|
const page3 = rows.slice(0, limit);
|
|
50272
50422
|
const total = app.db.select({ total: sql20`COUNT(*)`.mapWith(Number).as("total") }).from(gtmRawSnapshots).where(eq55(gtmRawSnapshots.projectId, project.id)).get();
|
|
50273
50423
|
return {
|
|
@@ -50538,7 +50688,7 @@ async function googleMarketingRoutes(app, opts) {
|
|
|
50538
50688
|
|
|
50539
50689
|
// ../api-routes/src/ads.ts
|
|
50540
50690
|
import crypto37 from "crypto";
|
|
50541
|
-
import { eq as eq57, and as and48, asc as asc11, desc as
|
|
50691
|
+
import { eq as eq57, and as and48, asc as asc11, desc as desc29, gt as gt6, gte as gte14, lt as lt10, lte as lte14, ne as ne11, inArray as inArray26, or as or15, isNull as isNull12, isNotNull as isNotNull7, sql as sql22 } from "drizzle-orm";
|
|
50542
50692
|
|
|
50543
50693
|
// ../api-routes/src/ads-activation.ts
|
|
50544
50694
|
import crypto35 from "crypto";
|
|
@@ -51924,7 +52074,7 @@ async function executeApprovedAdsActivation(dependencies, request) {
|
|
|
51924
52074
|
|
|
51925
52075
|
// ../api-routes/src/ads-activation-routes.ts
|
|
51926
52076
|
import crypto36 from "crypto";
|
|
51927
|
-
import { and as and47, asc as asc10, eq as eq56, gt as
|
|
52077
|
+
import { and as and47, asc as asc10, eq as eq56, gt as gt5, isNotNull as isNotNull6, isNull as isNull11, lte as lte13, or as or14, sql as sql21 } from "drizzle-orm";
|
|
51928
52078
|
var MAX_ACTIVATION_GRANT_LIFETIME_MS = 24 * 60 * 60 * 1e3;
|
|
51929
52079
|
var ACTIVATION_LEASE_MS = 5 * 6e4;
|
|
51930
52080
|
var ACTIVATION_REVOCATION_SETTLEMENT_MS = ACTIVATION_LEASE_MS;
|
|
@@ -52145,7 +52295,7 @@ function createActivationStore(app, request) {
|
|
|
52145
52295
|
eq56(adsOperations.id, input.operationId),
|
|
52146
52296
|
eq56(adsOperations.state, AdsOperationStates.pending),
|
|
52147
52297
|
eq56(adsOperations.leaseOwner, input.leaseOwner),
|
|
52148
|
-
|
|
52298
|
+
gt5(adsOperations.leaseExpiresAt, input.now)
|
|
52149
52299
|
)).run();
|
|
52150
52300
|
const operation = loadActivationOperation(tx, input.operationId);
|
|
52151
52301
|
if (!operation) throw internalError("Ads activation receipt was not found");
|
|
@@ -52201,7 +52351,7 @@ function createActivationStore(app, request) {
|
|
|
52201
52351
|
eq56(adsOperations.id, input.operationId),
|
|
52202
52352
|
eq56(adsOperations.state, AdsOperationStates.pending),
|
|
52203
52353
|
eq56(adsOperations.leaseOwner, input.leaseOwner),
|
|
52204
|
-
|
|
52354
|
+
gt5(adsOperations.leaseExpiresAt, input.next.updatedAt)
|
|
52205
52355
|
)).run();
|
|
52206
52356
|
if (lease.changes !== 1 || existing.state !== input.fromState) {
|
|
52207
52357
|
const current2 = loadActivationOperation(tx, input.operationId);
|
|
@@ -52243,7 +52393,7 @@ function createActivationStore(app, request) {
|
|
|
52243
52393
|
eq56(adsOperations.id, input.operationId),
|
|
52244
52394
|
eq56(adsOperations.state, AdsOperationStates.pending),
|
|
52245
52395
|
eq56(adsOperations.leaseOwner, input.leaseOwner),
|
|
52246
|
-
|
|
52396
|
+
gt5(adsOperations.leaseExpiresAt, input.next.updatedAt)
|
|
52247
52397
|
)).run();
|
|
52248
52398
|
if (lease.changes !== 1 || existing.state !== input.fromState) {
|
|
52249
52399
|
const operation2 = loadActivationOperation(tx, input.operationId);
|
|
@@ -52306,7 +52456,7 @@ function createActivationStore(app, request) {
|
|
|
52306
52456
|
eq56(adsOperations.id, input.operationId),
|
|
52307
52457
|
eq56(adsOperations.state, AdsOperationStates.pending),
|
|
52308
52458
|
eq56(adsOperations.leaseOwner, input.leaseOwner),
|
|
52309
|
-
|
|
52459
|
+
gt5(adsOperations.leaseExpiresAt, input.now)
|
|
52310
52460
|
)).run();
|
|
52311
52461
|
if (operationUpdate.changes === 1) {
|
|
52312
52462
|
const grantUpdate = tx.update(adsActivationGrants).set({
|
|
@@ -53582,7 +53732,7 @@ function semanticallyMatchesMaterializedEntity(app, input) {
|
|
|
53582
53732
|
eq57(adsOperations.projectId, input.projectId),
|
|
53583
53733
|
eq57(adsOperations.entityType, input.entityType),
|
|
53584
53734
|
eq57(adsOperations.entityId, input.entityId),
|
|
53585
|
-
|
|
53735
|
+
inArray26(adsOperations.kind, [createKind, updateKind])
|
|
53586
53736
|
)).orderBy(asc11(adsOperations.createdAt), asc11(adsOperations.id)).all();
|
|
53587
53737
|
if (rows.some((row) => row.state === AdsOperationStates.pending || row.state === AdsOperationStates.reconciling || row.state === AdsOperationStates.unknown || row.kind === updateKind && row.state === AdsOperationStates.succeeded)) {
|
|
53588
53738
|
return false;
|
|
@@ -54019,7 +54169,7 @@ function quarantineExhaustedReconciliation(app, row, now, policy, context) {
|
|
|
54019
54169
|
eq57(adsOperations.id, row.id),
|
|
54020
54170
|
eq57(adsOperations.projectId, row.projectId),
|
|
54021
54171
|
gte14(adsOperations.reconcileAttempts, policy.maxAttempts),
|
|
54022
|
-
|
|
54172
|
+
inArray26(adsOperations.state, [
|
|
54023
54173
|
AdsOperationStates.pending,
|
|
54024
54174
|
AdsOperationStates.unknown,
|
|
54025
54175
|
AdsOperationStates.reconciling
|
|
@@ -54243,7 +54393,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
|
|
|
54243
54393
|
eq57(adsOperations.reconcileStrategy, AdsReconcileStrategies.create_fingerprint),
|
|
54244
54394
|
or15(
|
|
54245
54395
|
isNotNull7(adsOperations.entityId),
|
|
54246
|
-
|
|
54396
|
+
inArray26(adsOperations.state, [
|
|
54247
54397
|
AdsOperationStates.pending,
|
|
54248
54398
|
AdsOperationStates.reconciling
|
|
54249
54399
|
])
|
|
@@ -54291,7 +54441,7 @@ async function sweepAdsOperationsOnce(app, opts, config) {
|
|
|
54291
54441
|
const eligibleProjectIds = [...credentialsByProjectId.keys()];
|
|
54292
54442
|
if (eligibleProjectIds.length === 0) return;
|
|
54293
54443
|
const rows = app.db.select().from(adsOperations).where(and48(
|
|
54294
|
-
|
|
54444
|
+
inArray26(adsOperations.projectId, eligibleProjectIds),
|
|
54295
54445
|
staleReconcileWhere
|
|
54296
54446
|
)).orderBy(asc11(adsOperations.updatedAt)).limit(config.batchSize).all();
|
|
54297
54447
|
for (const row of rows) {
|
|
@@ -54613,12 +54763,12 @@ async function adsRoutes(app, opts) {
|
|
|
54613
54763
|
const cursor = parsed.data.cursor ? decodeAdsOperationCursor(parsed.data.cursor, project.id, parsed.data.state) : void 0;
|
|
54614
54764
|
const rows = app.db.select().from(adsOperations).where(and48(
|
|
54615
54765
|
eq57(adsOperations.projectId, project.id),
|
|
54616
|
-
|
|
54766
|
+
inArray26(adsOperations.state, parsed.data.state),
|
|
54617
54767
|
cursor ? or15(
|
|
54618
|
-
|
|
54768
|
+
gt6(adsOperations.createdAt, cursor.createdAt),
|
|
54619
54769
|
and48(
|
|
54620
54770
|
eq57(adsOperations.createdAt, cursor.createdAt),
|
|
54621
|
-
|
|
54771
|
+
gt6(adsOperations.id, cursor.id)
|
|
54622
54772
|
)
|
|
54623
54773
|
) : void 0
|
|
54624
54774
|
)).orderBy(asc11(adsOperations.createdAt), asc11(adsOperations.id)).limit(parsed.data.limit + 1).all();
|
|
@@ -55047,7 +55197,7 @@ async function adsRoutes(app, opts) {
|
|
|
55047
55197
|
const inFlight = app.db.select({ id: runs.id, status: runs.status }).from(runs).where(and48(
|
|
55048
55198
|
eq57(runs.projectId, project.id),
|
|
55049
55199
|
eq57(runs.kind, RunKinds["ads-sync"]),
|
|
55050
|
-
|
|
55200
|
+
inArray26(runs.status, [RunStatuses.queued, RunStatuses.running])
|
|
55051
55201
|
)).get();
|
|
55052
55202
|
if (inFlight) {
|
|
55053
55203
|
const existing = { runId: inFlight.id, status: inFlight.status };
|
|
@@ -55178,7 +55328,7 @@ async function adsRoutes(app, opts) {
|
|
|
55178
55328
|
const latestAdsSync = app.db.select({ id: runs.id, kind: runs.kind, status: runs.status }).from(runs).where(and48(
|
|
55179
55329
|
eq57(runs.projectId, project.id),
|
|
55180
55330
|
eq57(runs.kind, RunKinds["ads-sync"])
|
|
55181
|
-
)).orderBy(
|
|
55331
|
+
)).orderBy(desc29(runs.createdAt)).get();
|
|
55182
55332
|
const snapshot = storedSnapshotProvenance({
|
|
55183
55333
|
connected: Boolean(connection),
|
|
55184
55334
|
connectionLastSyncedAt: connection?.lastSyncedAt ?? null,
|
|
@@ -55582,7 +55732,7 @@ async function adsRoutes(app, opts) {
|
|
|
55582
55732
|
|
|
55583
55733
|
// ../api-routes/src/bing.ts
|
|
55584
55734
|
import crypto39 from "crypto";
|
|
55585
|
-
import { eq as eq58, and as and49, desc as
|
|
55735
|
+
import { eq as eq58, and as and49, desc as desc30 } from "drizzle-orm";
|
|
55586
55736
|
|
|
55587
55737
|
// ../integration-bing/src/bing-client.ts
|
|
55588
55738
|
import crypto38 from "crypto";
|
|
@@ -56001,7 +56151,7 @@ async function bingRoutes(app, opts) {
|
|
|
56001
56151
|
const store = requireConnectionStore();
|
|
56002
56152
|
const project = resolveProject(app.db, request.params.name);
|
|
56003
56153
|
requireConnection(store, project.canonicalDomain);
|
|
56004
|
-
const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(
|
|
56154
|
+
const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc30(bingUrlInspections.inspectedAt)).all();
|
|
56005
56155
|
const latestByUrl = /* @__PURE__ */ new Map();
|
|
56006
56156
|
const definitiveByUrl = /* @__PURE__ */ new Map();
|
|
56007
56157
|
for (const row of allInspections) {
|
|
@@ -56090,7 +56240,7 @@ async function bingRoutes(app, opts) {
|
|
|
56090
56240
|
const project = resolveProject(app.db, request.params.name);
|
|
56091
56241
|
const parsed = parseInt(request.query.limit ?? "90", 10);
|
|
56092
56242
|
const limit = Number.isNaN(parsed) || parsed <= 0 ? 90 : parsed;
|
|
56093
|
-
const rows = app.db.select().from(bingCoverageSnapshots).where(eq58(bingCoverageSnapshots.projectId, project.id)).orderBy(
|
|
56243
|
+
const rows = app.db.select().from(bingCoverageSnapshots).where(eq58(bingCoverageSnapshots.projectId, project.id)).orderBy(desc30(bingCoverageSnapshots.date)).limit(limit).all();
|
|
56094
56244
|
return rows.map((r) => ({
|
|
56095
56245
|
date: r.date,
|
|
56096
56246
|
indexed: r.indexed,
|
|
@@ -56103,7 +56253,7 @@ async function bingRoutes(app, opts) {
|
|
|
56103
56253
|
const project = resolveProject(app.db, request.params.name);
|
|
56104
56254
|
const { url, limit } = request.query;
|
|
56105
56255
|
const whereClause = url ? and49(eq58(bingUrlInspections.projectId, project.id), eq58(bingUrlInspections.url, url)) : eq58(bingUrlInspections.projectId, project.id);
|
|
56106
|
-
const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(
|
|
56256
|
+
const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(desc30(bingUrlInspections.inspectedAt)).limit(Math.max(1, Math.min(parseInt(limit ?? "100", 10) || 100, 1e3))).all();
|
|
56107
56257
|
return filtered.map((r) => ({
|
|
56108
56258
|
id: r.id,
|
|
56109
56259
|
url: r.url,
|
|
@@ -56247,7 +56397,7 @@ async function bingRoutes(app, opts) {
|
|
|
56247
56397
|
}
|
|
56248
56398
|
let urlsToSubmit = request.body?.urls ?? [];
|
|
56249
56399
|
if (request.body?.allUnindexed) {
|
|
56250
|
-
const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(
|
|
56400
|
+
const allInspections = app.db.select().from(bingUrlInspections).where(eq58(bingUrlInspections.projectId, project.id)).orderBy(desc30(bingUrlInspections.inspectedAt)).all();
|
|
56251
56401
|
const latestByUrl = /* @__PURE__ */ new Map();
|
|
56252
56402
|
for (const row of allInspections) {
|
|
56253
56403
|
if (!latestByUrl.has(row.url)) {
|
|
@@ -56506,7 +56656,7 @@ async function cdpRoutes(app, opts) {
|
|
|
56506
56656
|
|
|
56507
56657
|
// ../api-routes/src/ga.ts
|
|
56508
56658
|
import crypto40 from "crypto";
|
|
56509
|
-
import { eq as eq60, desc as
|
|
56659
|
+
import { eq as eq60, desc as desc31, and as and51, sql as sql23 } from "drizzle-orm";
|
|
56510
56660
|
|
|
56511
56661
|
// ../api-routes/src/ga-session-history.ts
|
|
56512
56662
|
function buildSessionHistory(landingPageDays, dailyTotals) {
|
|
@@ -56982,7 +57132,7 @@ async function ga4Routes(app, opts) {
|
|
|
56982
57132
|
if (!connected) {
|
|
56983
57133
|
return { connected: false, propertyId: null, clientEmail: null, authMethod: null, lastSyncedAt: null };
|
|
56984
57134
|
}
|
|
56985
|
-
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(
|
|
57135
|
+
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc31(gaTrafficSummaries.syncedAt)).limit(1).get();
|
|
56986
57136
|
return {
|
|
56987
57137
|
connected: true,
|
|
56988
57138
|
propertyId: saConn?.propertyId ?? oauthConn?.propertyId ?? null,
|
|
@@ -57412,7 +57562,7 @@ async function ga4Routes(app, opts) {
|
|
|
57412
57562
|
const socialTotals = app.db.select({
|
|
57413
57563
|
sessions: sql23`SUM(${gaSocialReferrals.sessions})`
|
|
57414
57564
|
}).from(gaSocialReferrals).where(and51(...socialConditions)).get();
|
|
57415
|
-
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(
|
|
57565
|
+
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq60(gaTrafficSummaries.projectId, project.id)).orderBy(desc31(gaTrafficSummaries.syncedAt)).limit(1).get();
|
|
57416
57566
|
const total = summaryRow?.totalSessions ?? 0;
|
|
57417
57567
|
const totalDirectSessions = directTotalRow?.totalDirectSessions ?? 0;
|
|
57418
57568
|
const totalOrganicSessions = summaryRow?.totalOrganicSessions ?? 0;
|
|
@@ -59364,7 +59514,7 @@ async function wordpressRoutes(app, opts) {
|
|
|
59364
59514
|
|
|
59365
59515
|
// ../api-routes/src/backlinks.ts
|
|
59366
59516
|
import crypto42 from "crypto";
|
|
59367
|
-
import { and as and53, asc as asc12, desc as
|
|
59517
|
+
import { and as and53, asc as asc12, desc as desc32, eq as eq61, sql as sql24 } from "drizzle-orm";
|
|
59368
59518
|
|
|
59369
59519
|
// ../integration-commoncrawl/src/constants.ts
|
|
59370
59520
|
import os2 from "os";
|
|
@@ -59865,7 +60015,7 @@ function latestSummaryForProject(db, projectId, source, release) {
|
|
|
59865
60015
|
eq61(backlinkSummaries.source, source)
|
|
59866
60016
|
];
|
|
59867
60017
|
if (release) conditions.push(eq61(backlinkSummaries.release, release));
|
|
59868
|
-
return db.select().from(backlinkSummaries).where(and53(...conditions)).orderBy(
|
|
60018
|
+
return db.select().from(backlinkSummaries).where(and53(...conditions)).orderBy(desc32(backlinkSummaries.queriedAt)).limit(1).get();
|
|
59869
60019
|
}
|
|
59870
60020
|
function parseExcludeCrawlers(value) {
|
|
59871
60021
|
if (!value) return false;
|
|
@@ -59887,7 +60037,7 @@ function computeFilteredSummary(db, base) {
|
|
|
59887
60037
|
count: sql24`count(*)`,
|
|
59888
60038
|
total: sql24`coalesce(sum(${backlinkDomains.numHosts}), 0)`
|
|
59889
60039
|
}).from(backlinkDomains).where(filteredCondition).get();
|
|
59890
|
-
const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(
|
|
60040
|
+
const top10Rows = db.select({ numHosts: backlinkDomains.numHosts }).from(backlinkDomains).where(filteredCondition).orderBy(desc32(backlinkDomains.numHosts)).limit(10).all();
|
|
59891
60041
|
const totalLinkingDomains = Number(filteredAgg?.count ?? 0);
|
|
59892
60042
|
const totalHosts = Number(filteredAgg?.total ?? 0);
|
|
59893
60043
|
const unfilteredLinkingDomains = Number(unfilteredAgg?.count ?? 0);
|
|
@@ -59908,7 +60058,7 @@ function computeFilteredSummary(db, base) {
|
|
|
59908
60058
|
};
|
|
59909
60059
|
}
|
|
59910
60060
|
function buildSourceAvailability(db, projectId, source, connected, excludeCrawlers) {
|
|
59911
|
-
const summary3 = db.select().from(backlinkSummaries).where(and53(eq61(backlinkSummaries.projectId, projectId), eq61(backlinkSummaries.source, source))).orderBy(
|
|
60061
|
+
const summary3 = db.select().from(backlinkSummaries).where(and53(eq61(backlinkSummaries.projectId, projectId), eq61(backlinkSummaries.source, source))).orderBy(desc32(backlinkSummaries.queriedAt)).limit(1).get();
|
|
59912
60062
|
let totalLinkingDomains = summary3?.totalLinkingDomains ?? 0;
|
|
59913
60063
|
if (summary3 && excludeCrawlers) {
|
|
59914
60064
|
const filtered = db.select({ count: sql24`count(*)` }).from(backlinkDomains).where(and53(
|
|
@@ -60013,11 +60163,11 @@ async function backlinksRoutes(app, opts) {
|
|
|
60013
60163
|
return reply.status(201).send(mapSyncRow(inserted));
|
|
60014
60164
|
});
|
|
60015
60165
|
app.get("/backlinks/syncs/latest", async (_request, reply) => {
|
|
60016
|
-
const row = app.db.select().from(ccReleaseSyncs).orderBy(
|
|
60166
|
+
const row = app.db.select().from(ccReleaseSyncs).orderBy(desc32(ccReleaseSyncs.updatedAt)).limit(1).get();
|
|
60017
60167
|
return reply.send(row ? mapSyncRow(row) : null);
|
|
60018
60168
|
});
|
|
60019
60169
|
app.get("/backlinks/syncs", async (_request, reply) => {
|
|
60020
|
-
const rows = app.db.select().from(ccReleaseSyncs).orderBy(
|
|
60170
|
+
const rows = app.db.select().from(ccReleaseSyncs).orderBy(desc32(ccReleaseSyncs.updatedAt)).all();
|
|
60021
60171
|
return reply.send(rows.map(mapSyncRow));
|
|
60022
60172
|
});
|
|
60023
60173
|
app.get("/backlinks/releases", async (_request, reply) => {
|
|
@@ -60104,7 +60254,7 @@ async function backlinksRoutes(app, opts) {
|
|
|
60104
60254
|
linkingDomain: backlinkDomains.linkingDomain,
|
|
60105
60255
|
numHosts: backlinkDomains.numHosts,
|
|
60106
60256
|
source: backlinkDomains.source
|
|
60107
|
-
}).from(backlinkDomains).where(domainCondition).orderBy(
|
|
60257
|
+
}).from(backlinkDomains).where(domainCondition).orderBy(desc32(backlinkDomains.numHosts)).limit(limit).offset(offset).all();
|
|
60108
60258
|
let summary3 = null;
|
|
60109
60259
|
if (summaryRow) {
|
|
60110
60260
|
summary3 = excludeCrawlers ? computeFilteredSummary(app.db, summaryRow) : mapSummaryRow(summaryRow);
|
|
@@ -60150,7 +60300,7 @@ import crypto45 from "crypto";
|
|
|
60150
60300
|
import { isIP } from "net";
|
|
60151
60301
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
60152
60302
|
import { Agent as UndiciAgent } from "undici";
|
|
60153
|
-
import { and as and57, desc as
|
|
60303
|
+
import { and as and57, desc as desc33, eq as eq65, gte as gte16, inArray as inArray27, lte as lte17, sql as sql27 } from "drizzle-orm";
|
|
60154
60304
|
|
|
60155
60305
|
// ../api-routes/src/cloudflare-worker-version.ts
|
|
60156
60306
|
var CURRENT_CLOUDFLARE_WORKER_VERSION = "1.0.1";
|
|
@@ -79892,7 +80042,7 @@ async function trafficRoutes(app, opts) {
|
|
|
79892
80042
|
eq65(runs.kind, RunKinds["traffic-sync"]),
|
|
79893
80043
|
eq65(runs.sourceId, row.id)
|
|
79894
80044
|
)
|
|
79895
|
-
).orderBy(
|
|
80045
|
+
).orderBy(desc33(runs.startedAt)).limit(1).get();
|
|
79896
80046
|
return {
|
|
79897
80047
|
...rowToDto(row),
|
|
79898
80048
|
totals24h: {
|
|
@@ -79971,14 +80121,14 @@ async function trafficRoutes(app, opts) {
|
|
|
79971
80121
|
});
|
|
79972
80122
|
app.get("/projects/:name/traffic/sources", async (request) => {
|
|
79973
80123
|
const project = resolveProject(app.db, request.params.name);
|
|
79974
|
-
const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(
|
|
80124
|
+
const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc33(trafficSources.createdAt)).all();
|
|
79975
80125
|
const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map(rowToDto);
|
|
79976
80126
|
const response = { sources };
|
|
79977
80127
|
return response;
|
|
79978
80128
|
});
|
|
79979
80129
|
app.get("/projects/:name/traffic/status", async (request) => {
|
|
79980
80130
|
const project = resolveProject(app.db, request.params.name);
|
|
79981
|
-
const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(
|
|
80131
|
+
const rows = app.db.select().from(trafficSources).where(eq65(trafficSources.projectId, project.id)).orderBy(desc33(trafficSources.createdAt)).all();
|
|
79982
80132
|
const since = new Date(Date.now() - 24 * 60 * 6e4).toISOString();
|
|
79983
80133
|
const sources = rows.filter((row) => row.status !== TrafficSourceStatuses.archived).map((row) => buildSourceDetail(project.id, row, since));
|
|
79984
80134
|
const response = { sources };
|
|
@@ -80089,7 +80239,7 @@ async function trafficRoutes(app, opts) {
|
|
|
80089
80239
|
const listed = useContentList ? contentPaths : infraPaths;
|
|
80090
80240
|
const IN_LIST_CAP = 2e4;
|
|
80091
80241
|
const listFitsInSql = listed.length <= IN_LIST_CAP;
|
|
80092
|
-
const contentExpr = listed.length === 0 ? useContentList ? sql27`0` : sql27`${crawlerEventsHourly.hits}` : useContentList ? sql27`CASE WHEN ${
|
|
80242
|
+
const contentExpr = listed.length === 0 ? useContentList ? sql27`0` : sql27`${crawlerEventsHourly.hits}` : useContentList ? sql27`CASE WHEN ${inArray27(crawlerEventsHourly.pathNormalized, listed)} THEN ${crawlerEventsHourly.hits} ELSE 0 END` : sql27`CASE WHEN ${inArray27(crawlerEventsHourly.pathNormalized, listed)} THEN 0 ELSE ${crawlerEventsHourly.hits} END`;
|
|
80093
80243
|
if (listFitsInSql) {
|
|
80094
80244
|
const crawlerSeries = app.db.select({
|
|
80095
80245
|
bucket: crawlerSeriesBucket,
|
|
@@ -80116,7 +80266,7 @@ async function trafficRoutes(app, opts) {
|
|
|
80116
80266
|
if (useContentList ? inList : !inList) point.crawlerContentHits += hits;
|
|
80117
80267
|
}
|
|
80118
80268
|
}
|
|
80119
|
-
const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(
|
|
80269
|
+
const rows = app.db.select().from(crawlerEventsHourly).where(crawlerWhere).orderBy(desc33(crawlerEventsHourly.tsHour)).limit(limit).all();
|
|
80120
80270
|
for (const r of rows) {
|
|
80121
80271
|
events.push({
|
|
80122
80272
|
kind: TrafficEventKinds.crawler,
|
|
@@ -80156,7 +80306,7 @@ async function trafficRoutes(app, opts) {
|
|
|
80156
80306
|
for (const row of userFetchSeries) {
|
|
80157
80307
|
trafficSeriesPoint(seriesByBucket, row.bucket).aiUserFetchHits = Number(row.hits);
|
|
80158
80308
|
}
|
|
80159
|
-
const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(
|
|
80309
|
+
const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(desc33(aiUserFetchEventsHourly.tsHour)).limit(limit).all();
|
|
80160
80310
|
for (const r of rows) {
|
|
80161
80311
|
events.push({
|
|
80162
80312
|
kind: TrafficEventKinds["ai-user-fetch"],
|
|
@@ -80209,7 +80359,7 @@ async function trafficRoutes(app, opts) {
|
|
|
80209
80359
|
point.aiReferralHits = Number(row.hits);
|
|
80210
80360
|
point.aiReferralLandedHits = Number(row.landed);
|
|
80211
80361
|
}
|
|
80212
|
-
const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(
|
|
80362
|
+
const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc33(aiReferralEventsHourly.tsHour)).limit(limit).all();
|
|
80213
80363
|
for (const r of rows) {
|
|
80214
80364
|
const counts2 = aiReferralClassCounts(r.sessionsOrHits, r.paidSessionsOrHits, r.organicSessionsOrHits);
|
|
80215
80365
|
events.push({
|
|
@@ -80478,7 +80628,7 @@ var reportSweepsCheck = {
|
|
|
80478
80628
|
};
|
|
80479
80629
|
|
|
80480
80630
|
// ../api-routes/src/doctor/checks/report-models.ts
|
|
80481
|
-
import { and as and59, eq as eq67, gte as gte18, inArray as
|
|
80631
|
+
import { and as and59, eq as eq67, gte as gte18, inArray as inArray28, lte as lte19 } from "drizzle-orm";
|
|
80482
80632
|
var reportModelsCheck = {
|
|
80483
80633
|
id: "report.models",
|
|
80484
80634
|
category: CheckCategories.providers,
|
|
@@ -80493,7 +80643,7 @@ var reportModelsCheck = {
|
|
|
80493
80643
|
const months = reportMonths.flatMap((month) => {
|
|
80494
80644
|
const bounds = calendarMonthBounds(month);
|
|
80495
80645
|
const previous = new Date(Date.parse(bounds.since) - 1).toISOString().slice(0, 7);
|
|
80496
|
-
const observations = ctx.db.select({ provider: querySnapshots.provider, model: querySnapshots.model, at: runs.createdAt }).from(querySnapshots).innerJoin(runs, eq67(runs.id, querySnapshots.runId)).where(and59(eq67(runs.projectId, ctx.project.id), eq67(runs.kind, RunKinds["answer-visibility"]),
|
|
80646
|
+
const observations = ctx.db.select({ provider: querySnapshots.provider, model: querySnapshots.model, at: runs.createdAt }).from(querySnapshots).innerJoin(runs, eq67(runs.id, querySnapshots.runId)).where(and59(eq67(runs.projectId, ctx.project.id), eq67(runs.kind, RunKinds["answer-visibility"]), inArray28(runs.status, [RunStatuses.completed, RunStatuses.partial]), notProbeRun(), gte18(runs.createdAt, bounds.since), lte19(runs.createdAt, bounds.until))).all();
|
|
80497
80647
|
return readVisibilityContinuity(ctx.db, ctx.project.name, { from: previous, to: month }).map(({ frame, continuity: continuity2 }) => ({
|
|
80498
80648
|
month,
|
|
80499
80649
|
previousMonth: previous,
|
|
@@ -81570,7 +81720,7 @@ var ga4ConnectionCheck = {
|
|
|
81570
81720
|
var GA_AUTH_CHECKS = [ga4ConnectionCheck];
|
|
81571
81721
|
|
|
81572
81722
|
// ../api-routes/src/doctor/checks/data-freshness.ts
|
|
81573
|
-
import { and as and62, desc as
|
|
81723
|
+
import { and as and62, desc as desc34, eq as eq73, inArray as inArray29 } from "drizzle-orm";
|
|
81574
81724
|
var GA_DATA_AGING_DAYS = 3;
|
|
81575
81725
|
var GA_DATA_STALE_DAYS = 5;
|
|
81576
81726
|
var GSC_DATA_AGING_DAYS = 5;
|
|
@@ -81598,7 +81748,7 @@ function skipped(code, summary3) {
|
|
|
81598
81748
|
return { status: CheckStatuses.skipped, code, summary: summary3, remediation: null };
|
|
81599
81749
|
}
|
|
81600
81750
|
function lastSyncAgeDays(ctx, kinds) {
|
|
81601
|
-
const row = ctx.db.select({ createdAt: runs.createdAt }).from(runs).where(and62(eq73(runs.projectId, ctx.project.id),
|
|
81751
|
+
const row = ctx.db.select({ createdAt: runs.createdAt }).from(runs).where(and62(eq73(runs.projectId, ctx.project.id), inArray29(runs.kind, kinds), eq73(runs.status, "completed"))).orderBy(desc34(runs.createdAt)).limit(1).get();
|
|
81602
81752
|
if (!row?.createdAt) return null;
|
|
81603
81753
|
const age = Math.floor((Date.now() - Date.parse(row.createdAt)) / DAY_MS2);
|
|
81604
81754
|
return Number.isFinite(age) ? age : null;
|
|
@@ -81694,7 +81844,7 @@ var gaRecentDataCheck = {
|
|
|
81694
81844
|
const connection = gaConnected(ctx);
|
|
81695
81845
|
if (connection === "store-unavailable") return skipped("ga.data.store-unavailable", "No GA4 credential store configured for this deployment.");
|
|
81696
81846
|
if (connection === "not-connected") return skipped("ga.data.not-connected", "GA4 is not connected for this project.");
|
|
81697
|
-
const newest = ctx.db.select({ date: gaDailyTotals.date }).from(gaDailyTotals).where(eq73(gaDailyTotals.projectId, ctx.project.id)).orderBy(
|
|
81847
|
+
const newest = ctx.db.select({ date: gaDailyTotals.date }).from(gaDailyTotals).where(eq73(gaDailyTotals.projectId, ctx.project.id)).orderBy(desc34(gaDailyTotals.date)).limit(1).get();
|
|
81698
81848
|
return grade(ctx, GA_SPEC, newest?.date);
|
|
81699
81849
|
}
|
|
81700
81850
|
};
|
|
@@ -81711,7 +81861,7 @@ var gscRecentDataCheck = {
|
|
|
81711
81861
|
}
|
|
81712
81862
|
const watermark = ctx.db.select({ dataThroughDate: gscDataWatermarks.dataThroughDate }).from(gscDataWatermarks).where(eq73(gscDataWatermarks.projectId, ctx.project.id)).get();
|
|
81713
81863
|
if (watermark?.dataThroughDate) return grade(ctx, GSC_SPEC, watermark.dataThroughDate);
|
|
81714
|
-
const newest = ctx.db.select({ date: gscDailyTotals.date }).from(gscDailyTotals).where(eq73(gscDailyTotals.projectId, ctx.project.id)).orderBy(
|
|
81864
|
+
const newest = ctx.db.select({ date: gscDailyTotals.date }).from(gscDailyTotals).where(eq73(gscDailyTotals.projectId, ctx.project.id)).orderBy(desc34(gscDailyTotals.date)).limit(1).get();
|
|
81715
81865
|
return grade(ctx, GSC_SPEC, newest?.date);
|
|
81716
81866
|
}
|
|
81717
81867
|
};
|
|
@@ -82967,7 +83117,7 @@ var RUNTIME_STATE_CHECKS = [
|
|
|
82967
83117
|
];
|
|
82968
83118
|
|
|
82969
83119
|
// ../api-routes/src/doctor/checks/traffic-source.ts
|
|
82970
|
-
import { and as and65, eq as eq77, gte as gte19, inArray as
|
|
83120
|
+
import { and as and65, eq as eq77, gte as gte19, inArray as inArray30, ne as ne14, sql as sql28 } from "drizzle-orm";
|
|
82971
83121
|
var RECENT_DATA_WARN_DAYS = 7;
|
|
82972
83122
|
var RECENT_DATA_FAIL_DAYS = 30;
|
|
82973
83123
|
function isCloudflareDirectPush(source) {
|
|
@@ -83115,7 +83265,7 @@ var recentDataCheck = {
|
|
|
83115
83265
|
ctx.db.select({ total: sql28`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
|
|
83116
83266
|
and65(
|
|
83117
83267
|
eq77(crawlerEventsHourly.projectId, ctx.project.id),
|
|
83118
|
-
|
|
83268
|
+
inArray30(crawlerEventsHourly.sourceId, activeSourceIds),
|
|
83119
83269
|
gte19(crawlerEventsHourly.tsHour, warnCutoff)
|
|
83120
83270
|
)
|
|
83121
83271
|
).get()?.total ?? 0
|
|
@@ -83124,7 +83274,7 @@ var recentDataCheck = {
|
|
|
83124
83274
|
ctx.db.select({ total: sql28`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
|
|
83125
83275
|
and65(
|
|
83126
83276
|
eq77(aiReferralEventsHourly.projectId, ctx.project.id),
|
|
83127
|
-
|
|
83277
|
+
inArray30(aiReferralEventsHourly.sourceId, activeSourceIds),
|
|
83128
83278
|
gte19(aiReferralEventsHourly.tsHour, warnCutoff)
|
|
83129
83279
|
)
|
|
83130
83280
|
).get()?.total ?? 0
|
|
@@ -83133,7 +83283,7 @@ var recentDataCheck = {
|
|
|
83133
83283
|
ctx.db.select({ total: sql28`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
|
|
83134
83284
|
and65(
|
|
83135
83285
|
eq77(aiUserFetchEventsHourly.projectId, ctx.project.id),
|
|
83136
|
-
|
|
83286
|
+
inArray30(aiUserFetchEventsHourly.sourceId, activeSourceIds),
|
|
83137
83287
|
gte19(aiUserFetchEventsHourly.tsHour, warnCutoff)
|
|
83138
83288
|
)
|
|
83139
83289
|
).get()?.total ?? 0
|
|
@@ -83159,7 +83309,7 @@ var recentDataCheck = {
|
|
|
83159
83309
|
ctx.db.select({ total: sql28`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
|
|
83160
83310
|
and65(
|
|
83161
83311
|
eq77(crawlerEventsHourly.projectId, ctx.project.id),
|
|
83162
|
-
|
|
83312
|
+
inArray30(crawlerEventsHourly.sourceId, activeSourceIds),
|
|
83163
83313
|
gte19(crawlerEventsHourly.tsHour, failCutoff)
|
|
83164
83314
|
)
|
|
83165
83315
|
).get()?.total ?? 0
|
|
@@ -83168,7 +83318,7 @@ var recentDataCheck = {
|
|
|
83168
83318
|
ctx.db.select({ total: sql28`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
|
|
83169
83319
|
and65(
|
|
83170
83320
|
eq77(aiReferralEventsHourly.projectId, ctx.project.id),
|
|
83171
|
-
|
|
83321
|
+
inArray30(aiReferralEventsHourly.sourceId, activeSourceIds),
|
|
83172
83322
|
gte19(aiReferralEventsHourly.tsHour, failCutoff)
|
|
83173
83323
|
)
|
|
83174
83324
|
).get()?.total ?? 0
|
|
@@ -83177,7 +83327,7 @@ var recentDataCheck = {
|
|
|
83177
83327
|
ctx.db.select({ total: sql28`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
|
|
83178
83328
|
and65(
|
|
83179
83329
|
eq77(aiUserFetchEventsHourly.projectId, ctx.project.id),
|
|
83180
|
-
|
|
83330
|
+
inArray30(aiUserFetchEventsHourly.sourceId, activeSourceIds),
|
|
83181
83331
|
gte19(aiUserFetchEventsHourly.tsHour, failCutoff)
|
|
83182
83332
|
)
|
|
83183
83333
|
).get()?.total ?? 0
|
|
@@ -84184,7 +84334,7 @@ async function doctorRoutes(app, opts) {
|
|
|
84184
84334
|
|
|
84185
84335
|
// ../api-routes/src/discovery/routes.ts
|
|
84186
84336
|
import crypto47 from "crypto";
|
|
84187
|
-
import { and as and66, desc as
|
|
84337
|
+
import { and as and66, desc as desc35, eq as eq78, gte as gte20, inArray as inArray31, isNull as isNull14, or as or17 } from "drizzle-orm";
|
|
84188
84338
|
var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
|
|
84189
84339
|
async function discoveryRoutes(app, opts) {
|
|
84190
84340
|
app.post("/projects/:name/discover/run", async (request, reply) => {
|
|
@@ -84239,13 +84389,13 @@ async function discoveryRoutes(app, opts) {
|
|
|
84239
84389
|
// must never reuse another set's session. Null (= Gemini-only
|
|
84240
84390
|
// default, including explicit ['gemini']) matches legacy rows.
|
|
84241
84391
|
seedProviders == null ? isNull14(discoverySessions.seedProviders) : eq78(discoverySessions.seedProviders, seedProviders),
|
|
84242
|
-
|
|
84392
|
+
inArray31(discoverySessions.status, [
|
|
84243
84393
|
DiscoverySessionStatuses.queued,
|
|
84244
84394
|
DiscoverySessionStatuses.seeding,
|
|
84245
84395
|
DiscoverySessionStatuses.probing
|
|
84246
84396
|
]),
|
|
84247
84397
|
gte20(discoverySessions.createdAt, ageFloorIso)
|
|
84248
|
-
)).orderBy(
|
|
84398
|
+
)).orderBy(desc35(discoverySessions.createdAt)).get();
|
|
84249
84399
|
if (existing && existing.runId) {
|
|
84250
84400
|
return { reused: true, sessionId: existing.id, runId: existing.runId };
|
|
84251
84401
|
}
|
|
@@ -84314,7 +84464,7 @@ async function discoveryRoutes(app, opts) {
|
|
|
84314
84464
|
const project = resolveProject(app.db, request.params.name);
|
|
84315
84465
|
const parsedLimit = parseInt(request.query.limit ?? "", 10);
|
|
84316
84466
|
const limit = Number.isNaN(parsedLimit) || parsedLimit <= 0 ? 50 : parsedLimit;
|
|
84317
|
-
const rows = app.db.select().from(discoverySessions).where(eq78(discoverySessions.projectId, project.id)).orderBy(
|
|
84467
|
+
const rows = app.db.select().from(discoverySessions).where(eq78(discoverySessions.projectId, project.id)).orderBy(desc35(discoverySessions.createdAt)).limit(limit).all();
|
|
84318
84468
|
return reply.send(rows.map(serializeSession));
|
|
84319
84469
|
}
|
|
84320
84470
|
);
|
|
@@ -84938,7 +85088,7 @@ function dedupeStrings(input) {
|
|
|
84938
85088
|
|
|
84939
85089
|
// ../api-routes/src/technical-aeo.ts
|
|
84940
85090
|
import crypto49 from "crypto";
|
|
84941
|
-
import { and as and67, asc as asc14, count as count2, desc as
|
|
85091
|
+
import { and as and67, asc as asc14, count as count2, desc as desc36, eq as eq80, inArray as inArray32, isNotNull as isNotNull8, isNull as isNull15, lt as lt13, or as or18, sql as sql29 } from "drizzle-orm";
|
|
84942
85092
|
import { alias } from "drizzle-orm/sqlite-core";
|
|
84943
85093
|
var FETCHED_SITE_CRAWL_STATES = /* @__PURE__ */ new Set([
|
|
84944
85094
|
...SiteCrawlFetchedStates,
|
|
@@ -85263,11 +85413,11 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85263
85413
|
eq80(siteCrawlSnapshots.projectId, projectId),
|
|
85264
85414
|
eq80(runs.projectId, projectId),
|
|
85265
85415
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
85266
|
-
|
|
85416
|
+
inArray32(runs.status, SURFACEABLE_STATUSES),
|
|
85267
85417
|
notProbeRun()
|
|
85268
85418
|
];
|
|
85269
85419
|
if (runId) filters.push(eq80(siteCrawlSnapshots.runId, runId));
|
|
85270
|
-
return app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...filters)).orderBy(
|
|
85420
|
+
return app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...filters)).orderBy(desc36(siteCrawlSnapshots.createdAt), desc36(siteCrawlSnapshots.runId)).limit(1).get();
|
|
85271
85421
|
};
|
|
85272
85422
|
const detailScopeFor = (projectId, snapshot) => snapshot.detailsAvailable && snapshot.attemptId ? { projectId, runId: snapshot.runId, attemptId: snapshot.attemptId } : null;
|
|
85273
85423
|
const completenessOf = (snapshot) => ({
|
|
@@ -85294,7 +85444,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85294
85444
|
eq80(runs.id, runId),
|
|
85295
85445
|
eq80(runs.projectId, projectId),
|
|
85296
85446
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
85297
|
-
|
|
85447
|
+
inArray32(runs.status, SURFACEABLE_STATUSES),
|
|
85298
85448
|
notProbeRun()
|
|
85299
85449
|
)).limit(1).get());
|
|
85300
85450
|
const assertKnownAuditRun = (projectId, runId) => {
|
|
@@ -85304,7 +85454,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85304
85454
|
eq80(siteAuditSnapshots.projectId, projectId),
|
|
85305
85455
|
eq80(runs.projectId, projectId),
|
|
85306
85456
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
85307
|
-
|
|
85457
|
+
inArray32(runs.status, SURFACEABLE_STATUSES),
|
|
85308
85458
|
notProbeRun()
|
|
85309
85459
|
)).limit(1).get());
|
|
85310
85460
|
const emptyCrawlSummary = (projectName, legacyAuditAvailable) => ({
|
|
@@ -85328,17 +85478,17 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85328
85478
|
eq80(siteAuditSnapshots.projectId, project.id),
|
|
85329
85479
|
eq80(runs.projectId, project.id),
|
|
85330
85480
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
85331
|
-
|
|
85481
|
+
inArray32(runs.status, SURFACEABLE_STATUSES),
|
|
85332
85482
|
notProbeRun()
|
|
85333
85483
|
];
|
|
85334
85484
|
const targetFilters = request.query.runId ? [...baseFilters, eq80(siteAuditSnapshots.runId, request.query.runId)] : baseFilters;
|
|
85335
|
-
const latest = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(
|
|
85485
|
+
const latest = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(1).get();
|
|
85336
85486
|
if (!latest) {
|
|
85337
85487
|
if (request.query.runId) throw notFound("Site audit run", request.query.runId);
|
|
85338
85488
|
return emptyScore(project.name);
|
|
85339
85489
|
}
|
|
85340
85490
|
const snap = latest.snap;
|
|
85341
|
-
const previous = app.db.select({ snap: siteAuditSnapshots }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...baseFilters, lt13(siteAuditSnapshots.createdAt, snap.createdAt))).orderBy(
|
|
85491
|
+
const previous = app.db.select({ snap: siteAuditSnapshots }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...baseFilters, lt13(siteAuditSnapshots.createdAt, snap.createdAt))).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(1).get()?.snap ?? null;
|
|
85342
85492
|
const deltaScore = previous ? snap.aggregateScore - previous.aggregateScore : null;
|
|
85343
85493
|
const trend = deltaScore == null ? null : deltaScore > 0 ? SiteAuditTrendDirections.up : deltaScore < 0 ? SiteAuditTrendDirections.down : SiteAuditTrendDirections.flat;
|
|
85344
85494
|
return {
|
|
@@ -85368,11 +85518,11 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85368
85518
|
eq80(siteAuditSnapshots.projectId, project.id),
|
|
85369
85519
|
eq80(runs.projectId, project.id),
|
|
85370
85520
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
85371
|
-
|
|
85521
|
+
inArray32(runs.status, SURFACEABLE_STATUSES),
|
|
85372
85522
|
notProbeRun()
|
|
85373
85523
|
];
|
|
85374
85524
|
if (request.query.runId) targetFilters.push(eq80(siteAuditSnapshots.runId, request.query.runId));
|
|
85375
|
-
const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(
|
|
85525
|
+
const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq80(siteAuditSnapshots.runId, runs.id)).where(and67(...targetFilters)).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(1).get();
|
|
85376
85526
|
if (!latest && request.query.runId) {
|
|
85377
85527
|
throw notFound("Site audit run", request.query.runId);
|
|
85378
85528
|
}
|
|
@@ -85387,7 +85537,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85387
85537
|
const total = totalRow?.value ?? 0;
|
|
85388
85538
|
const limit = parsePositiveInt(request.query.limit, 100, 500);
|
|
85389
85539
|
const offset = parsePositiveInt(request.query.offset, 0, Number.MAX_SAFE_INTEGER);
|
|
85390
|
-
const orderBy = request.query.sort === "score-desc" ?
|
|
85540
|
+
const orderBy = request.query.sort === "score-desc" ? desc36(siteAuditPages.overallScore) : request.query.sort === "url" ? asc14(siteAuditPages.url) : asc14(siteAuditPages.overallScore);
|
|
85391
85541
|
const rows = app.db.select().from(siteAuditPages).where(where).orderBy(orderBy).limit(limit).offset(offset).all();
|
|
85392
85542
|
const pages = rows.map((row) => ({
|
|
85393
85543
|
url: row.url,
|
|
@@ -85410,9 +85560,9 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85410
85560
|
eq80(siteAuditSnapshots.projectId, project.id),
|
|
85411
85561
|
eq80(runs.projectId, project.id),
|
|
85412
85562
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
85413
|
-
|
|
85563
|
+
inArray32(runs.status, SURFACEABLE_STATUSES),
|
|
85414
85564
|
notProbeRun()
|
|
85415
|
-
)).orderBy(
|
|
85565
|
+
)).orderBy(desc36(siteAuditSnapshots.createdAt)).limit(limit).all();
|
|
85416
85566
|
return { project: project.name, points: rows.reverse() };
|
|
85417
85567
|
});
|
|
85418
85568
|
app.get("/projects/:name/technical-aeo/crawl", async (request) => {
|
|
@@ -85718,8 +85868,8 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85718
85868
|
eq80(siteCrawlEdges.internal, true),
|
|
85719
85869
|
isNotNull8(siteCrawlEdges.targetNodeKey),
|
|
85720
85870
|
or18(
|
|
85721
|
-
|
|
85722
|
-
|
|
85871
|
+
inArray32(siteCrawlEdges.sourceNodeKey, frontier),
|
|
85872
|
+
inArray32(siteCrawlEdges.targetNodeKey, frontier)
|
|
85723
85873
|
)
|
|
85724
85874
|
)).orderBy(asc14(siteCrawlEdges.edgeKey)).limit(maxEdges + maxNodes + 1).all();
|
|
85725
85875
|
if (candidates.length > maxEdges + maxNodes) queryTruncated = true;
|
|
@@ -85756,7 +85906,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85756
85906
|
eq80(siteCrawlPages.projectId, scope.projectId),
|
|
85757
85907
|
eq80(siteCrawlPages.runId, scope.runId),
|
|
85758
85908
|
eq80(siteCrawlPages.attemptId, scope.attemptId),
|
|
85759
|
-
|
|
85909
|
+
inArray32(siteCrawlPages.nodeKey, nodeKeys)
|
|
85760
85910
|
)).all();
|
|
85761
85911
|
const persistedNodeKeys = new Set(pageRows.map((row) => row.nodeKey));
|
|
85762
85912
|
const outermostNodeKeys = pageRows.filter((row) => distances.get(row.nodeKey) === hops).map((row) => row.nodeKey);
|
|
@@ -85766,8 +85916,8 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85766
85916
|
eq80(siteCrawlEdges.attemptId, scope.attemptId),
|
|
85767
85917
|
eq80(siteCrawlEdges.internal, true),
|
|
85768
85918
|
isNotNull8(siteCrawlEdges.targetNodeKey),
|
|
85769
|
-
|
|
85770
|
-
|
|
85919
|
+
inArray32(siteCrawlEdges.sourceNodeKey, outermostNodeKeys),
|
|
85920
|
+
inArray32(siteCrawlEdges.targetNodeKey, outermostNodeKeys)
|
|
85771
85921
|
)).limit(1).get();
|
|
85772
85922
|
if (omittedOutermostEdge && !seenEdgeKeys.has(omittedOutermostEdge.edgeKey)) {
|
|
85773
85923
|
omittedEdgeKeys.add(omittedOutermostEdge.edgeKey);
|
|
@@ -85870,7 +86020,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85870
86020
|
eq80(siteCrawlEdges.followable, true),
|
|
85871
86021
|
eq80(siteCrawlEdges.relation, "anchor"),
|
|
85872
86022
|
isNotNull8(siteCrawlEdges.targetNodeKey),
|
|
85873
|
-
|
|
86023
|
+
inArray32(siteCrawlEdges.sourceNodeKey, frontier)
|
|
85874
86024
|
)).orderBy(asc14(siteCrawlEdges.edgeKey)).limit(SITE_HEALTH_PATH_MAX_VISITED_NODES + 1).all();
|
|
85875
86025
|
if (candidates.length > SITE_HEALTH_PATH_MAX_VISITED_NODES) truncated = true;
|
|
85876
86026
|
const candidateTargetKeys = [...new Set(candidates.map((edge) => edge.targetNodeKey).filter((nodeKey) => nodeKey != null))];
|
|
@@ -85878,7 +86028,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85878
86028
|
eq80(siteCrawlPages.projectId, scope.projectId),
|
|
85879
86029
|
eq80(siteCrawlPages.runId, scope.runId),
|
|
85880
86030
|
eq80(siteCrawlPages.attemptId, scope.attemptId),
|
|
85881
|
-
|
|
86031
|
+
inArray32(siteCrawlPages.nodeKey, candidateTargetKeys)
|
|
85882
86032
|
)).all().map((row) => row.nodeKey));
|
|
85883
86033
|
const next = /* @__PURE__ */ new Set();
|
|
85884
86034
|
for (const edge of candidates.slice(0, SITE_HEALTH_PATH_MAX_VISITED_NODES)) {
|
|
@@ -85924,7 +86074,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85924
86074
|
eq80(siteCrawlPages.projectId, scope.projectId),
|
|
85925
86075
|
eq80(siteCrawlPages.runId, scope.runId),
|
|
85926
86076
|
eq80(siteCrawlPages.attemptId, scope.attemptId),
|
|
85927
|
-
|
|
86077
|
+
inArray32(siteCrawlPages.nodeKey, pathKeys)
|
|
85928
86078
|
)).all();
|
|
85929
86079
|
const pageByKey = new Map(pathRows.map((row) => [row.nodeKey, row]));
|
|
85930
86080
|
const pathDetection = templateDetectionOf(snapshot.templateDetection);
|
|
@@ -85960,7 +86110,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85960
86110
|
eq80(siteCrawlSnapshots.complete, true),
|
|
85961
86111
|
notProbeRun()
|
|
85962
86112
|
];
|
|
85963
|
-
const afterTarget = request.query.toRunId ? resolveCrawl(project.id, request.query.toRunId) : app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...completeSnapshotFilters)).orderBy(
|
|
86113
|
+
const afterTarget = request.query.toRunId ? resolveCrawl(project.id, request.query.toRunId) : app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(...completeSnapshotFilters)).orderBy(desc36(siteCrawlSnapshots.createdAt), desc36(siteCrawlSnapshots.runId)).limit(1).get();
|
|
85964
86114
|
if (request.query.toRunId && !afterTarget) throw notFound("Site crawl run", request.query.toRunId);
|
|
85965
86115
|
const beforeTarget = request.query.fromRunId ? resolveCrawl(project.id, request.query.fromRunId) : afterTarget ? app.db.select({ snapshot: siteCrawlSnapshots, runStatus: runs.status }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(
|
|
85966
86116
|
...completeSnapshotFilters,
|
|
@@ -85971,7 +86121,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
85971
86121
|
lt13(siteCrawlSnapshots.runId, afterTarget.snapshot.runId)
|
|
85972
86122
|
)
|
|
85973
86123
|
)
|
|
85974
|
-
)).orderBy(
|
|
86124
|
+
)).orderBy(desc36(siteCrawlSnapshots.createdAt), desc36(siteCrawlSnapshots.runId)).limit(1).get() : void 0;
|
|
85975
86125
|
if (request.query.fromRunId && !beforeTarget) throw notFound("Site crawl run", request.query.fromRunId);
|
|
85976
86126
|
if (!afterTarget) {
|
|
85977
86127
|
const latestCrawl = resolveCrawl(project.id);
|
|
@@ -86216,14 +86366,14 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
86216
86366
|
eq80(siteCrawlPages.projectId, scope.projectId),
|
|
86217
86367
|
eq80(siteCrawlPages.runId, scope.runId),
|
|
86218
86368
|
eq80(siteCrawlPages.attemptId, scope.attemptId),
|
|
86219
|
-
|
|
86369
|
+
inArray32(siteCrawlPages.nodeKey, pageKeys)
|
|
86220
86370
|
)).all();
|
|
86221
86371
|
const edgeRowsFor = (scope) => linkKeys.length === 0 ? [] : app.db.select().from(siteCrawlEdges).where(and67(
|
|
86222
86372
|
eq80(siteCrawlEdges.projectId, scope.projectId),
|
|
86223
86373
|
eq80(siteCrawlEdges.runId, scope.runId),
|
|
86224
86374
|
eq80(siteCrawlEdges.attemptId, scope.attemptId),
|
|
86225
86375
|
eq80(siteCrawlEdges.internal, true),
|
|
86226
|
-
|
|
86376
|
+
inArray32(siteCrawlEdges.edgeKey, linkKeys)
|
|
86227
86377
|
)).all();
|
|
86228
86378
|
const beforePages = new Map(pageRowsFor(beforeScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
|
|
86229
86379
|
const afterPages = new Map(pageRowsFor(afterScope).map((row) => [row.nodeKey, mapCrawlPage(row)]));
|
|
@@ -86361,7 +86511,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
86361
86511
|
const healthState = parseSiteHealthState(request.query.healthState);
|
|
86362
86512
|
const limit = parseBoundedLimit(request.query.limit, 100, 200);
|
|
86363
86513
|
const offset = decodeCursor(request.query.cursor);
|
|
86364
|
-
const orderBy = request.query.sort === "score-desc" ? [
|
|
86514
|
+
const orderBy = request.query.sort === "score-desc" ? [desc36(siteCrawlPages.auditScore), asc14(siteCrawlPages.nodeKey)] : request.query.sort === "score-asc" ? [asc14(siteCrawlPages.auditScore), asc14(siteCrawlPages.nodeKey)] : request.query.sort === "path" ? [asc14(siteCrawlPages.path), asc14(siteCrawlPages.nodeKey)] : [asc14(siteCrawlPages.url), asc14(siteCrawlPages.nodeKey)];
|
|
86365
86515
|
let healthStateFilter = null;
|
|
86366
86516
|
if (healthState) {
|
|
86367
86517
|
const legacyRow = app.db.select({ id: siteCrawlPages.id }).from(siteCrawlPages).where(and67(
|
|
@@ -86674,15 +86824,15 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
86674
86824
|
eq80(runs.projectId, project.id),
|
|
86675
86825
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
86676
86826
|
notProbeRun()
|
|
86677
|
-
)).orderBy(
|
|
86827
|
+
)).orderBy(desc36(runs.createdAt), desc36(runs.id)).limit(limit).all();
|
|
86678
86828
|
const runIds = rows.map((row) => row.runId);
|
|
86679
86829
|
const crawlRunIds = new Set(runIds.length === 0 ? [] : app.db.select({ runId: siteCrawlSnapshots.runId }).from(siteCrawlSnapshots).innerJoin(runs, eq80(siteCrawlSnapshots.runId, runs.id)).where(and67(
|
|
86680
86830
|
eq80(siteCrawlSnapshots.projectId, project.id),
|
|
86681
86831
|
eq80(runs.projectId, project.id),
|
|
86682
86832
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
86683
|
-
|
|
86833
|
+
inArray32(runs.status, SURFACEABLE_STATUSES),
|
|
86684
86834
|
notProbeRun(),
|
|
86685
|
-
|
|
86835
|
+
inArray32(siteCrawlSnapshots.runId, runIds)
|
|
86686
86836
|
)).all().map((row) => row.runId));
|
|
86687
86837
|
return {
|
|
86688
86838
|
project: project.name,
|
|
@@ -86705,7 +86855,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
86705
86855
|
const attempt = app.db.select().from(siteCrawlAttempts).where(and67(
|
|
86706
86856
|
eq80(siteCrawlAttempts.projectId, project.id),
|
|
86707
86857
|
eq80(siteCrawlAttempts.runId, run.id)
|
|
86708
|
-
)).orderBy(
|
|
86858
|
+
)).orderBy(desc36(siteCrawlAttempts.attemptNumber), desc36(siteCrawlAttempts.updatedAt)).limit(1).get();
|
|
86709
86859
|
const persistedLayout = attempt ? app.db.select().from(siteCrawlGraphLayouts).where(and67(
|
|
86710
86860
|
eq80(siteCrawlGraphLayouts.projectId, project.id),
|
|
86711
86861
|
eq80(siteCrawlGraphLayouts.runId, run.id),
|
|
@@ -86752,7 +86902,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
86752
86902
|
const attempt = tx.select().from(siteCrawlAttempts).where(and67(
|
|
86753
86903
|
eq80(siteCrawlAttempts.projectId, project.id),
|
|
86754
86904
|
eq80(siteCrawlAttempts.runId, run.id)
|
|
86755
|
-
)).orderBy(
|
|
86905
|
+
)).orderBy(desc36(siteCrawlAttempts.attemptNumber), desc36(siteCrawlAttempts.updatedAt)).limit(1).get();
|
|
86756
86906
|
const state = run.status === RunStatuses.queued ? "waiting" : run.status === RunStatuses.running ? "collecting" : "terminal";
|
|
86757
86907
|
const base = {
|
|
86758
86908
|
project: project.name,
|
|
@@ -86822,7 +86972,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
86822
86972
|
)).where(and67(
|
|
86823
86973
|
eq80(runs.projectId, project.id),
|
|
86824
86974
|
eq80(runs.kind, RunKinds["site-audit"]),
|
|
86825
|
-
|
|
86975
|
+
inArray32(runs.status, [RunStatuses.queued, RunStatuses.running])
|
|
86826
86976
|
)).get();
|
|
86827
86977
|
if (existing) {
|
|
86828
86978
|
if (existing.identityKey === identityKey) {
|
|
@@ -86876,7 +87026,7 @@ async function technicalAeoRoutes(app, opts) {
|
|
|
86876
87026
|
// ../api-routes/src/research.ts
|
|
86877
87027
|
import crypto50 from "crypto";
|
|
86878
87028
|
import { z as z5 } from "zod";
|
|
86879
|
-
import { and as and68, count as count3, desc as
|
|
87029
|
+
import { and as and68, count as count3, desc as desc37, eq as eq81, gte as gte21, lt as lt14, or as or19, sql as sql30 } from "drizzle-orm";
|
|
86880
87030
|
var sameLocation = (a, b) => a.label === b.label && a.city === b.city && a.region === b.region && a.country === b.country && a.timezone === b.timezone;
|
|
86881
87031
|
var BATCH_RECEIPT_PREFIX = "__canonry_research_batch__:";
|
|
86882
87032
|
async function researchRoutes(app, opts) {
|
|
@@ -87047,7 +87197,7 @@ async function researchRoutes(app, opts) {
|
|
|
87047
87197
|
const rows = app.db.select().from(researchRuns).where(and68(
|
|
87048
87198
|
eq81(researchRuns.projectId, project.id),
|
|
87049
87199
|
cursor ? or19(lt14(researchRuns.createdAt, cursor.createdAt), and68(eq81(researchRuns.createdAt, cursor.createdAt), lt14(researchRuns.id, cursor.id))) : void 0
|
|
87050
|
-
)).orderBy(
|
|
87200
|
+
)).orderBy(desc37(researchRuns.createdAt), desc37(researchRuns.id)).limit(limit + 1).all();
|
|
87051
87201
|
const runs2 = rows.slice(0, limit).map(serializeRun);
|
|
87052
87202
|
const last = runs2.at(-1);
|
|
87053
87203
|
const nextCursor = rows.length > limit && last ? Buffer.from(JSON.stringify({ projectId: project.id, createdAt: last.createdAt, id: last.id })).toString("base64url") : null;
|
|
@@ -87228,7 +87378,7 @@ function utcDayBounds(now) {
|
|
|
87228
87378
|
}
|
|
87229
87379
|
|
|
87230
87380
|
// ../api-routes/src/snapshot-competitor-refresh.ts
|
|
87231
|
-
import { and as and69, eq as eq82, inArray as
|
|
87381
|
+
import { and as and69, eq as eq82, inArray as inArray33 } from "drizzle-orm";
|
|
87232
87382
|
var SNAPSHOT_BATCH_SIZE = 500;
|
|
87233
87383
|
function backfillProjectAnswerMentions(db, projectId, opts) {
|
|
87234
87384
|
const isDryRun = opts?.dryRun === true;
|
|
@@ -87272,7 +87422,7 @@ function backfillProjectAnswerMentions(db, projectId, opts) {
|
|
|
87272
87422
|
competitorOverlap: querySnapshots.competitorOverlap,
|
|
87273
87423
|
recommendedCompetitors: querySnapshots.recommendedCompetitors,
|
|
87274
87424
|
rawResponse: querySnapshots.rawResponse
|
|
87275
|
-
}).from(querySnapshots).where(
|
|
87425
|
+
}).from(querySnapshots).where(inArray33(querySnapshots.runId, batchRunIds)).all();
|
|
87276
87426
|
const pendingUpdates = [];
|
|
87277
87427
|
for (const snapshot of snapshotRows) {
|
|
87278
87428
|
if (competitorFieldsOnly && snapshot.answerText == null) continue;
|
|
@@ -88328,7 +88478,7 @@ var IntelligenceService = class {
|
|
|
88328
88478
|
this.db.select({ one: sql31`1` }).from(querySnapshots).where(eq84(querySnapshots.runId, runs.id))
|
|
88329
88479
|
)
|
|
88330
88480
|
)
|
|
88331
|
-
).orderBy(
|
|
88481
|
+
).orderBy(desc38(runs.finishedAt), desc38(runs.createdAt)).limit(HISTORY_WINDOW_RUNS).all();
|
|
88332
88482
|
const trackedCompetitors = this.loadTrackedCompetitors(projectId);
|
|
88333
88483
|
const currentRun = this.buildRunData(
|
|
88334
88484
|
runId,
|
|
@@ -88447,10 +88597,10 @@ var IntelligenceService = class {
|
|
|
88447
88597
|
buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
|
|
88448
88598
|
const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and71(eq84(gbpDailyMetrics.projectId, projectId), eq84(gbpDailyMetrics.locationName, locationName))).all();
|
|
88449
88599
|
const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and71(eq84(gbpPlaceActions.projectId, projectId), eq84(gbpPlaceActions.locationName, locationName))).all();
|
|
88450
|
-
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and71(eq84(gbpLodgingSnapshots.projectId, projectId), eq84(gbpLodgingSnapshots.locationName, locationName))).orderBy(
|
|
88600
|
+
const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and71(eq84(gbpLodgingSnapshots.projectId, projectId), eq84(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc38(gbpLodgingSnapshots.syncedAt)).limit(1).get();
|
|
88451
88601
|
const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and71(eq84(gbpLocations.projectId, projectId), eq84(gbpLocations.locationName, locationName))).get();
|
|
88452
88602
|
const descriptionMissing = !(ownerRow?.description ?? "").trim();
|
|
88453
|
-
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and71(eq84(gbpPlaceDetails.projectId, projectId), eq84(gbpPlaceDetails.locationName, locationName))).orderBy(
|
|
88603
|
+
const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and71(eq84(gbpPlaceDetails.projectId, projectId), eq84(gbpPlaceDetails.locationName, locationName))).orderBy(desc38(gbpPlaceDetails.syncedAt)).limit(1).get();
|
|
88454
88604
|
const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
|
|
88455
88605
|
const summary3 = buildGbpSummary({
|
|
88456
88606
|
locationName,
|
|
@@ -88657,7 +88807,7 @@ var IntelligenceService = class {
|
|
|
88657
88807
|
let wouldDeleteTotal = 0;
|
|
88658
88808
|
const existingByRunId = /* @__PURE__ */ new Map();
|
|
88659
88809
|
if (isDryRun && targetRuns.length > 0) {
|
|
88660
|
-
const rows = this.db.select({ runId: insights.runId }).from(insights).where(
|
|
88810
|
+
const rows = this.db.select({ runId: insights.runId }).from(insights).where(inArray34(insights.runId, targetRuns.map((r) => r.id))).all();
|
|
88661
88811
|
for (const r of rows) {
|
|
88662
88812
|
if (r.runId == null) continue;
|
|
88663
88813
|
existingByRunId.set(r.runId, (existingByRunId.get(r.runId) ?? 0) + 1);
|
|
@@ -88712,7 +88862,7 @@ var IntelligenceService = class {
|
|
|
88712
88862
|
*/
|
|
88713
88863
|
runIdsWithSnapshots(runIds) {
|
|
88714
88864
|
if (runIds.length === 0) return /* @__PURE__ */ new Set();
|
|
88715
|
-
const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(
|
|
88865
|
+
const rows = this.db.select({ runId: querySnapshots.runId }).from(querySnapshots).where(inArray34(querySnapshots.runId, [...runIds])).groupBy(querySnapshots.runId).all();
|
|
88716
88866
|
return new Set(rows.map((r) => r.runId));
|
|
88717
88867
|
}
|
|
88718
88868
|
/**
|
|
@@ -88857,7 +89007,7 @@ var IntelligenceService = class {
|
|
|
88857
89007
|
// Defensive — see top of file.
|
|
88858
89008
|
ne15(runs.trigger, RunTriggers.probe)
|
|
88859
89009
|
)
|
|
88860
|
-
).orderBy(
|
|
89010
|
+
).orderBy(desc38(runs.createdAt), desc38(runs.id)).limit((RECURRENCE_LOOKBACK_RUNS + 1) * ROWS_PER_GROUP_BUDGET).all();
|
|
88861
89011
|
const recentGroups = groupRunsByCreatedAt(recentRunRows);
|
|
88862
89012
|
const recentRunIds = [];
|
|
88863
89013
|
const recentRunIdToCreatedAt = /* @__PURE__ */ new Map();
|
|
@@ -88873,7 +89023,7 @@ var IntelligenceService = class {
|
|
|
88873
89023
|
const haveHistory = recentRunIds.length > 0;
|
|
88874
89024
|
const priorRegressionsByPair = /* @__PURE__ */ new Map();
|
|
88875
89025
|
if (haveHistory) {
|
|
88876
|
-
const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and71(eq84(insights.type, "regression"),
|
|
89026
|
+
const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and71(eq84(insights.type, "regression"), inArray34(insights.runId, recentRunIds))).all();
|
|
88877
89027
|
const regressionGroups = /* @__PURE__ */ new Map();
|
|
88878
89028
|
for (const row of priorRows) {
|
|
88879
89029
|
if (!row.runId) continue;
|