@ainyc/canonry 4.112.6 → 4.113.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.
Files changed (26) hide show
  1. package/assets/assets/BacklinksPage-AYTE7he1.js +1 -0
  2. package/assets/assets/{ChartPrimitives-CFWAHPcS.js → ChartPrimitives-J0xH87kk.js} +1 -1
  3. package/assets/assets/ProjectPage-BcqfsS5X.js +7 -0
  4. package/assets/assets/{RunRow-Qyzm30FW.js → RunRow-Duz6GoZ0.js} +1 -1
  5. package/assets/assets/RunsPage-DpocjSZ-.js +1 -0
  6. package/assets/assets/{SettingsPage-DwpJMAmo.js → SettingsPage-CboDfSRx.js} +1 -1
  7. package/assets/assets/TrafficPage-B5c8opWF.js +1 -0
  8. package/assets/assets/TrafficSourceDetailPage-D9JPwzH-.js +1 -0
  9. package/assets/assets/{arrow-left-uUn3V6mX.js → arrow-left-DMukIffh.js} +1 -1
  10. package/assets/assets/{extract-error-message-DnaGve8f.js → extract-error-message-CVln-Uf_.js} +1 -1
  11. package/assets/assets/{index-Du2NS1zP.js → index-DNoISJxr.js} +53 -53
  12. package/assets/assets/{trash-2-Cn2KSurM.js → trash-2-BbhOWhnf.js} +1 -1
  13. package/assets/index.html +1 -1
  14. package/dist/{chunk-FVELOZTK.js → chunk-B3B3HJPH.js} +3 -3
  15. package/dist/{chunk-D5PEINWZ.js → chunk-XYSEBOHP.js} +221 -183
  16. package/dist/cli.js +3 -3
  17. package/dist/index.js +3 -3
  18. package/dist/{intelligence-service-ZPY7NIKR.js → intelligence-service-RRWOGVVE.js} +1 -1
  19. package/dist/mcp.js +1 -1
  20. package/package.json +7 -7
  21. package/assets/assets/BacklinksPage-D71EWLVy.js +0 -1
  22. package/assets/assets/ProjectPage-zNZMtXRD.js +0 -7
  23. package/assets/assets/RunsPage-BmwjeZUx.js +0 -1
  24. package/assets/assets/TrafficPage-DQERHZoJ.js +0 -1
  25. package/assets/assets/TrafficSourceDetailPage-C-5sFG6L.js +0 -1
  26. /package/dist/{chunk-K2XOEBSH.js → chunk-RMTNF2ES.js} +0 -0
@@ -274,7 +274,7 @@ import {
274
274
  } from "./chunk-DBZLOLYT.js";
275
275
 
276
276
  // src/intelligence-service.ts
277
- import { eq as eq38, desc as desc18, asc as asc6, and as and28, ne as ne5, or as or6, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
277
+ import { eq as eq38, desc as desc18, asc as asc6, and as and29, ne as ne5, or as or6, inArray as inArray14, gte as gte7, lte as lte4 } from "drizzle-orm";
278
278
 
279
279
  // ../db/src/client.ts
280
280
  import { mkdirSync } from "fs";
@@ -6291,7 +6291,7 @@ function aliasArraysEqual(a, b) {
6291
6291
 
6292
6292
  // ../api-routes/src/queries.ts
6293
6293
  import crypto5 from "crypto";
6294
- import { eq as eq4, inArray, sql as sql4 } from "drizzle-orm";
6294
+ import { and, eq as eq4, inArray, sql as sql4 } from "drizzle-orm";
6295
6295
  function preserveSnapshotQueryText(tx, projectId, queryIds) {
6296
6296
  const candidates = queryIds && queryIds.length > 0 ? tx.select({ id: queries.id, text: queries.query }).from(queries).where(inArray(queries.id, queryIds)).all() : tx.select({ id: queries.id, text: queries.query }).from(queries).where(eq4(queries.projectId, projectId)).all();
6297
6297
  for (const q of candidates) {
@@ -6391,6 +6391,26 @@ async function queryRoutes(app, opts) {
6391
6391
  const rows = app.db.select().from(queries).where(eq4(queries.projectId, project.id)).all();
6392
6392
  return reply.send(rows.map((r) => ({ id: r.id, query: r.query, createdAt: r.createdAt })));
6393
6393
  });
6394
+ app.delete("/projects/:name/queries/:id", async (request, reply) => {
6395
+ const project = resolveProject(app.db, request.params.name);
6396
+ const query = app.db.select().from(queries).where(and(eq4(queries.projectId, project.id), eq4(queries.id, request.params.id))).get();
6397
+ if (!query) {
6398
+ throw notFound("Query", request.params.id);
6399
+ }
6400
+ app.db.transaction((tx) => {
6401
+ preserveSnapshotQueryText(tx, project.id, [query.id]);
6402
+ tx.delete(queries).where(eq4(queries.id, query.id)).run();
6403
+ writeAuditLog(tx, auditFromRequest(request, {
6404
+ projectId: project.id,
6405
+ actor: "api",
6406
+ action: "queries.deleted",
6407
+ entityType: "query",
6408
+ entityId: query.id,
6409
+ diff: { deleted: [query.query] }
6410
+ }));
6411
+ });
6412
+ return reply.status(204).send();
6413
+ });
6394
6414
  app.post("/projects/:name/queries", async (request, reply) => {
6395
6415
  const project = resolveProject(app.db, request.params.name);
6396
6416
  const body = request.body;
@@ -6730,12 +6750,12 @@ function parseCompetitorBatch(value) {
6730
6750
 
6731
6751
  // ../api-routes/src/runs.ts
6732
6752
  import crypto8 from "crypto";
6733
- import { and as and2, eq as eq7, asc, desc, or as or2, sql as sql5 } from "drizzle-orm";
6753
+ import { and as and3, eq as eq7, asc, desc, or as or2, sql as sql5 } from "drizzle-orm";
6734
6754
  import { gte } from "drizzle-orm";
6735
6755
 
6736
6756
  // ../api-routes/src/run-queue.ts
6737
6757
  import crypto7 from "crypto";
6738
- import { and, eq as eq6, or } from "drizzle-orm";
6758
+ import { and as and2, eq as eq6, or } from "drizzle-orm";
6739
6759
  function queueRunIfProjectIdle(db, params) {
6740
6760
  const createdAt = params.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
6741
6761
  const kind = params.kind ?? "answer-visibility";
@@ -6743,7 +6763,7 @@ function queueRunIfProjectIdle(db, params) {
6743
6763
  const runId = crypto7.randomUUID();
6744
6764
  return db.transaction((tx) => {
6745
6765
  const activeRun = tx.select().from(runs).where(
6746
- and(
6766
+ and2(
6747
6767
  eq6(runs.projectId, params.projectId),
6748
6768
  or(eq6(runs.status, "queued"), eq6(runs.status, "running"))
6749
6769
  )
@@ -6826,7 +6846,7 @@ async function runRoutes(app, opts) {
6826
6846
  throw validationError("No locations configured for this project");
6827
6847
  }
6828
6848
  const result = app.db.transaction((tx) => {
6829
- const activeRun = tx.select({ id: runs.id }).from(runs).where(and2(
6849
+ const activeRun = tx.select({ id: runs.id }).from(runs).where(and3(
6830
6850
  eq7(runs.projectId, project.id),
6831
6851
  or2(eq7(runs.status, "queued"), eq7(runs.status, "running"))
6832
6852
  )).get();
@@ -6899,15 +6919,15 @@ async function runRoutes(app, opts) {
6899
6919
  const parsedLimit = parseInt(request.query.limit ?? "", 10);
6900
6920
  const limit = Number.isNaN(parsedLimit) || parsedLimit <= 0 ? void 0 : parsedLimit;
6901
6921
  const kind = parseListKind(request.query.kind);
6902
- const where = kind ? and2(eq7(runs.projectId, project.id), eq7(runs.kind, kind)) : eq7(runs.projectId, project.id);
6922
+ const where = kind ? and3(eq7(runs.projectId, project.id), eq7(runs.kind, kind)) : eq7(runs.projectId, project.id);
6903
6923
  const rows = limit == null ? app.db.select().from(runs).where(where).orderBy(asc(runs.createdAt)).all() : app.db.select().from(runs).where(where).orderBy(desc(runs.createdAt)).limit(limit).all().reverse();
6904
6924
  return reply.send(rows.map(formatRun));
6905
6925
  });
6906
6926
  app.get("/projects/:name/runs/latest", async (request, reply) => {
6907
6927
  const project = resolveProject(app.db, request.params.name);
6908
- const countRow = app.db.select({ count: sql5`count(*)` }).from(runs).where(and2(eq7(runs.projectId, project.id), notProbeRun())).get();
6928
+ const countRow = app.db.select({ count: sql5`count(*)` }).from(runs).where(and3(eq7(runs.projectId, project.id), notProbeRun())).get();
6909
6929
  const totalRuns = countRow?.count ?? 0;
6910
- const latestRun = app.db.select().from(runs).where(and2(eq7(runs.projectId, project.id), notProbeRun())).orderBy(desc(runs.createdAt), desc(runs.id)).limit(1).get();
6930
+ const latestRun = app.db.select().from(runs).where(and3(eq7(runs.projectId, project.id), notProbeRun())).orderBy(desc(runs.createdAt), desc(runs.id)).limit(1).get();
6911
6931
  if (!latestRun) {
6912
6932
  return reply.send({ totalRuns: 0, run: null });
6913
6933
  }
@@ -6926,7 +6946,7 @@ async function runRoutes(app, opts) {
6926
6946
  if (kind) filters.push(eq7(runs.kind, kind));
6927
6947
  const scopedProjectId = request.apiKey?.projectId;
6928
6948
  if (scopedProjectId) filters.push(eq7(runs.projectId, scopedProjectId));
6929
- const rows = app.db.select().from(runs).where(and2(...filters)).orderBy(desc(runs.createdAt), desc(runs.id)).limit(limit).all();
6949
+ const rows = app.db.select().from(runs).where(and3(...filters)).orderBy(desc(runs.createdAt), desc(runs.id)).limit(limit).all();
6930
6950
  return reply.send(rows.map(formatRun));
6931
6951
  });
6932
6952
  app.post("/runs", async (request, reply) => {
@@ -7137,7 +7157,7 @@ function loadRunDetail(app, run) {
7137
7157
 
7138
7158
  // ../api-routes/src/apply.ts
7139
7159
  import crypto10 from "crypto";
7140
- import { and as and3, eq as eq8 } from "drizzle-orm";
7160
+ import { and as and4, eq as eq8 } from "drizzle-orm";
7141
7161
 
7142
7162
  // ../api-routes/src/schedule-utils.ts
7143
7163
  import { CronExpressionParser } from "cron-parser";
@@ -7580,7 +7600,7 @@ async function applyRoutes(app, opts) {
7580
7600
  });
7581
7601
  const AV_KIND = SchedulableRunKinds["answer-visibility"];
7582
7602
  if (resolvedSchedule) {
7583
- const existingSched = tx.select().from(schedules).where(and3(eq8(schedules.projectId, projectId), eq8(schedules.kind, AV_KIND))).get();
7603
+ const existingSched = tx.select().from(schedules).where(and4(eq8(schedules.projectId, projectId), eq8(schedules.kind, AV_KIND))).get();
7584
7604
  if (existingSched) {
7585
7605
  tx.update(schedules).set({
7586
7606
  cronExpr: resolvedSchedule.cronExpr,
@@ -7606,9 +7626,9 @@ async function applyRoutes(app, opts) {
7606
7626
  }
7607
7627
  scheduleAction = "upsert";
7608
7628
  } else if (deleteSchedule) {
7609
- const existingSched = tx.select().from(schedules).where(and3(eq8(schedules.projectId, projectId), eq8(schedules.kind, AV_KIND))).get();
7629
+ const existingSched = tx.select().from(schedules).where(and4(eq8(schedules.projectId, projectId), eq8(schedules.kind, AV_KIND))).get();
7610
7630
  if (existingSched) {
7611
- tx.delete(schedules).where(and3(eq8(schedules.projectId, projectId), eq8(schedules.kind, AV_KIND))).run();
7631
+ tx.delete(schedules).where(and4(eq8(schedules.projectId, projectId), eq8(schedules.kind, AV_KIND))).run();
7612
7632
  scheduleAction = "delete";
7613
7633
  }
7614
7634
  }
@@ -7692,7 +7712,7 @@ function normalizeCompetitorList2(domains) {
7692
7712
  }
7693
7713
 
7694
7714
  // ../api-routes/src/history.ts
7695
- import { and as and4, eq as eq9, desc as desc2, inArray as inArray2 } from "drizzle-orm";
7715
+ import { and as and5, eq as eq9, desc as desc2, inArray as inArray2 } from "drizzle-orm";
7696
7716
 
7697
7717
  // ../api-routes/src/notification-redaction.ts
7698
7718
  var REDACTED_URL = {
@@ -7750,7 +7770,7 @@ async function historyRoutes(app) {
7750
7770
  const project = resolveProject(app.db, request.params.name);
7751
7771
  const limit = parseInt(request.query.limit ?? "50", 10);
7752
7772
  const offset = parseInt(request.query.offset ?? "0", 10);
7753
- const projectRuns = app.db.select({ id: runs.id }).from(runs).where(and4(eq9(runs.projectId, project.id), notProbeRun())).all();
7773
+ const projectRuns = app.db.select({ id: runs.id }).from(runs).where(and5(eq9(runs.projectId, project.id), notProbeRun())).all();
7754
7774
  if (projectRuns.length === 0) {
7755
7775
  return reply.send({ snapshots: [], total: 0 });
7756
7776
  }
@@ -7799,7 +7819,7 @@ async function historyRoutes(app) {
7799
7819
  app.get("/projects/:name/timeline", async (request, reply) => {
7800
7820
  const project = resolveProject(app.db, request.params.name);
7801
7821
  const projectQueries = app.db.select().from(queries).where(eq9(queries.projectId, project.id)).all();
7802
- const projectRuns = app.db.select().from(runs).where(and4(eq9(runs.projectId, project.id), notProbeRun())).orderBy(runs.createdAt).all();
7822
+ const projectRuns = app.db.select().from(runs).where(and5(eq9(runs.projectId, project.id), notProbeRun())).orderBy(runs.createdAt).all();
7803
7823
  if (projectRuns.length === 0 || projectQueries.length === 0) {
7804
7824
  return reply.send([]);
7805
7825
  }
@@ -8010,13 +8030,13 @@ function formatAuditEntry(row) {
8010
8030
  }
8011
8031
 
8012
8032
  // ../api-routes/src/analytics.ts
8013
- import { and as and5, eq as eq10, desc as desc3, inArray as inArray3 } from "drizzle-orm";
8033
+ import { and as and6, eq as eq10, desc as desc3, inArray as inArray3 } from "drizzle-orm";
8014
8034
  async function analyticsRoutes(app) {
8015
8035
  app.get("/projects/:name/analytics/metrics", async (request, reply) => {
8016
8036
  const project = resolveProject(app.db, request.params.name);
8017
8037
  const window = parseWindow(request.query.window);
8018
8038
  const cutoff = windowCutoff(window);
8019
- const projectRuns = app.db.select().from(runs).where(and5(eq10(runs.projectId, project.id), notProbeRun())).orderBy(runs.createdAt).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
8039
+ const projectRuns = app.db.select().from(runs).where(and6(eq10(runs.projectId, project.id), notProbeRun())).orderBy(runs.createdAt).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
8020
8040
  if (projectRuns.length === 0) {
8021
8041
  return reply.send({
8022
8042
  window,
@@ -8068,14 +8088,14 @@ async function analyticsRoutes(app) {
8068
8088
  const project = resolveProject(app.db, request.params.name);
8069
8089
  const window = parseWindow(request.query.window);
8070
8090
  const cutoff = windowCutoff(window);
8071
- const completedRuns = app.db.select().from(runs).where(and5(eq10(runs.projectId, project.id), notProbeRun())).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial");
8091
+ const completedRuns = app.db.select().from(runs).where(and6(eq10(runs.projectId, project.id), notProbeRun())).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial");
8072
8092
  const latestGroup = groupRunsByCreatedAt(completedRuns)[0] ?? [];
8073
8093
  const latestGroupRunIds = latestGroup.map((r) => r.id);
8074
8094
  const latestRun = pickGroupRepresentative(latestGroup);
8075
8095
  if (!latestRun) {
8076
8096
  return reply.send({ cited: [], gap: [], uncited: [], mentionedQueries: [], mentionGap: [], notMentioned: [], runId: "", window });
8077
8097
  }
8078
- const windowRuns = app.db.select().from(runs).where(and5(eq10(runs.projectId, project.id), notProbeRun())).orderBy(runs.createdAt).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
8098
+ const windowRuns = app.db.select().from(runs).where(and6(eq10(runs.projectId, project.id), notProbeRun())).orderBy(runs.createdAt).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
8079
8099
  const windowRunIds = windowRuns.map((r) => r.id);
8080
8100
  const runIdToCreatedAt = new Map(windowRuns.map((r) => [r.id, r.createdAt]));
8081
8101
  const consistencyMap = /* @__PURE__ */ new Map();
@@ -8206,7 +8226,7 @@ async function analyticsRoutes(app) {
8206
8226
  const mapped = surfaceClassFromCompetitorType(row.competitorType);
8207
8227
  if (mapped) storedSurfaceClasses.set(normalizeProjectDomain(row.domain), mapped);
8208
8228
  }
8209
- const windowRuns = app.db.select().from(runs).where(and5(eq10(runs.projectId, project.id), notProbeRun())).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
8229
+ const windowRuns = app.db.select().from(runs).where(and6(eq10(runs.projectId, project.id), notProbeRun())).orderBy(desc3(runs.createdAt), desc3(runs.id)).all().filter((r) => r.status === "completed" || r.status === "partial").filter((r) => !cutoff || r.createdAt >= cutoff);
8210
8230
  if (windowRuns.length === 0) {
8211
8231
  return reply.send({
8212
8232
  overall: [],
@@ -8471,7 +8491,7 @@ function buildCategoryCounts(counts2) {
8471
8491
  }
8472
8492
 
8473
8493
  // ../api-routes/src/intelligence.ts
8474
- import { eq as eq11, desc as desc4, and as and6, inArray as inArray4, like } from "drizzle-orm";
8494
+ import { eq as eq11, desc as desc4, and as and7, inArray as inArray4, like } from "drizzle-orm";
8475
8495
  var SEVERITY_RANK = { low: 0, medium: 1, high: 2, critical: 3 };
8476
8496
  function severitiesAtOrAbove(min) {
8477
8497
  const floor = SEVERITY_RANK[min];
@@ -8611,7 +8631,7 @@ async function intelligenceRoutes(app) {
8611
8631
  }
8612
8632
  limit = parsed;
8613
8633
  }
8614
- const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and6(...conditions)).orderBy(desc4(insights.createdAt)).all();
8634
+ const rows = app.db.select().from(insights).where(conditions.length === 1 ? conditions[0] : and7(...conditions)).orderBy(desc4(insights.createdAt)).all();
8615
8635
  const showDismissed = request.query.dismissed === "true";
8616
8636
  let result = rows.filter((r) => showDismissed || !r.dismissed).map(mapInsightRow);
8617
8637
  if (limit !== void 0) result = result.slice(0, limit);
@@ -8636,7 +8656,7 @@ async function intelligenceRoutes(app) {
8636
8656
  });
8637
8657
  app.get("/projects/:name/health/latest", async (request, reply) => {
8638
8658
  const project = resolveProject(app.db, request.params.name);
8639
- const projectVisRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and6(
8659
+ const projectVisRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and7(
8640
8660
  eq11(runs.projectId, project.id),
8641
8661
  eq11(runs.kind, RunKinds["answer-visibility"]),
8642
8662
  inArray4(runs.status, [RunStatuses.completed, RunStatuses.partial]),
@@ -8647,7 +8667,7 @@ async function intelligenceRoutes(app) {
8647
8667
  const latestGroup = groupRunsByCreatedAt(projectVisRuns)[0] ?? [];
8648
8668
  const latestGroupRunIds = latestGroup.map((r) => r.id);
8649
8669
  if (latestGroupRunIds.length > 0) {
8650
- const groupRows = app.db.select().from(healthSnapshots).where(and6(
8670
+ const groupRows = app.db.select().from(healthSnapshots).where(and7(
8651
8671
  eq11(healthSnapshots.projectId, project.id),
8652
8672
  inArray4(healthSnapshots.runId, latestGroupRunIds)
8653
8673
  )).all();
@@ -8671,14 +8691,14 @@ async function intelligenceRoutes(app) {
8671
8691
  }
8672
8692
 
8673
8693
  // ../api-routes/src/report.ts
8674
- import { and as and10, desc as desc7, eq as eq15, gte as gte2, inArray as inArray6, lt, lte, ne as ne2, or as or3, sql as sql7 } from "drizzle-orm";
8694
+ import { and as and11, desc as desc7, eq as eq15, gte as gte2, inArray as inArray6, lt, lte, ne as ne2, or as or3, sql as sql7 } from "drizzle-orm";
8675
8695
 
8676
8696
  // ../api-routes/src/content.ts
8677
8697
  import crypto11 from "crypto";
8678
- import { and as and8, desc as desc6, eq as eq13 } from "drizzle-orm";
8698
+ import { and as and9, desc as desc6, eq as eq13 } from "drizzle-orm";
8679
8699
 
8680
8700
  // ../api-routes/src/content-data.ts
8681
- import { and as and7, eq as eq12, desc as desc5, inArray as inArray5 } from "drizzle-orm";
8701
+ import { and as and8, eq as eq12, desc as desc5, inArray as inArray5 } from "drizzle-orm";
8682
8702
  var RECENT_RUNS_WINDOW = 5;
8683
8703
  function loadOrchestratorInput(db, project, locationFilter = void 0) {
8684
8704
  const projectId = project.id;
@@ -8808,7 +8828,7 @@ function listCompetitorDomains(db, projectId) {
8808
8828
  }
8809
8829
  function listRecentAnswerVisibilityRunIds(db, projectId, limit, locationFilter) {
8810
8830
  const rows = db.select({ id: runs.id, location: runs.location }).from(runs).where(
8811
- and7(
8831
+ and8(
8812
8832
  eq12(runs.projectId, projectId),
8813
8833
  eq12(runs.kind, RunKinds["answer-visibility"]),
8814
8834
  // Queued/running/failed/cancelled runs may have partial or no
@@ -9179,7 +9199,7 @@ async function contentRoutes(app, opts = {}) {
9179
9199
  dismissedAt: now
9180
9200
  }
9181
9201
  }).run();
9182
- const row = app.db.select().from(contentTargetDismissals).where(and8(
9202
+ const row = app.db.select().from(contentTargetDismissals).where(and9(
9183
9203
  eq13(contentTargetDismissals.projectId, project.id),
9184
9204
  eq13(contentTargetDismissals.targetRef, targetRef)
9185
9205
  )).get();
@@ -9189,7 +9209,7 @@ async function contentRoutes(app, opts = {}) {
9189
9209
  app.delete("/projects/:name/content/dismissals/:targetRef", async (request, reply) => {
9190
9210
  const project = resolveProject(app.db, request.params.name);
9191
9211
  const { targetRef } = request.params;
9192
- const result = app.db.delete(contentTargetDismissals).where(and8(
9212
+ const result = app.db.delete(contentTargetDismissals).where(and9(
9193
9213
  eq13(contentTargetDismissals.projectId, project.id),
9194
9214
  eq13(contentTargetDismissals.targetRef, targetRef)
9195
9215
  )).run();
@@ -9200,7 +9220,7 @@ async function contentRoutes(app, opts = {}) {
9200
9220
  });
9201
9221
  app.get("/projects/:name/content/recommendations/:targetRef/analysis", async (request, reply) => {
9202
9222
  const project = resolveProject(app.db, request.params.name);
9203
- const row = app.db.select().from(recommendationExplanations).where(and8(
9223
+ const row = app.db.select().from(recommendationExplanations).where(and9(
9204
9224
  eq13(recommendationExplanations.projectId, project.id),
9205
9225
  eq13(recommendationExplanations.targetRef, request.params.targetRef)
9206
9226
  )).orderBy(desc6(recommendationExplanations.generatedAt)).limit(1).get();
@@ -9228,7 +9248,7 @@ async function contentRoutes(app, opts = {}) {
9228
9248
  throw notFound("contentRecommendation", targetRef);
9229
9249
  }
9230
9250
  if (!body.forceRefresh) {
9231
- const cached = app.db.select().from(recommendationExplanations).where(and8(
9251
+ const cached = app.db.select().from(recommendationExplanations).where(and9(
9232
9252
  eq13(recommendationExplanations.projectId, project.id),
9233
9253
  eq13(recommendationExplanations.targetRef, targetRef)
9234
9254
  )).orderBy(desc6(recommendationExplanations.generatedAt)).limit(1).get();
@@ -9267,7 +9287,7 @@ async function contentRoutes(app, opts = {}) {
9267
9287
  generatedAt: now
9268
9288
  }
9269
9289
  }).run();
9270
- const row = app.db.select().from(recommendationExplanations).where(and8(
9290
+ const row = app.db.select().from(recommendationExplanations).where(and9(
9271
9291
  eq13(recommendationExplanations.projectId, project.id),
9272
9292
  eq13(recommendationExplanations.targetRef, targetRef),
9273
9293
  eq13(recommendationExplanations.promptVersion, result.promptVersion)
@@ -9351,7 +9371,7 @@ async function contentRoutes(app, opts = {}) {
9351
9371
  generatedAt: now
9352
9372
  }
9353
9373
  }).run();
9354
- const row = app.db.select().from(recommendationBriefs).where(and8(
9374
+ const row = app.db.select().from(recommendationBriefs).where(and9(
9355
9375
  eq13(recommendationBriefs.projectId, project.id),
9356
9376
  eq13(recommendationBriefs.targetRef, targetRef),
9357
9377
  eq13(recommendationBriefs.promptVersion, result.promptVersion)
@@ -9381,7 +9401,7 @@ function lookupCachedBrief(db, projectId, targetRef, promptVersion) {
9381
9401
  if (promptVersion !== void 0) {
9382
9402
  conditions.push(eq13(recommendationBriefs.promptVersion, promptVersion));
9383
9403
  }
9384
- return db.select().from(recommendationBriefs).where(and8(...conditions)).orderBy(desc6(recommendationBriefs.generatedAt)).limit(1).get();
9404
+ return db.select().from(recommendationBriefs).where(and9(...conditions)).orderBy(desc6(recommendationBriefs.generatedAt)).limit(1).get();
9385
9405
  }
9386
9406
  function parseLimitParam(raw) {
9387
9407
  if (raw === void 0) return void 0;
@@ -9407,7 +9427,7 @@ function winnabilityClassRank(winnabilityClass) {
9407
9427
  }
9408
9428
 
9409
9429
  // ../api-routes/src/gsc-totals.ts
9410
- import { and as and9, asc as asc2, eq as eq14, sql as sql6 } from "drizzle-orm";
9430
+ import { and as and10, asc as asc2, eq as eq14, sql as sql6 } from "drizzle-orm";
9411
9431
  function readGscDailyTotals(db, projectId, startDate, endDate) {
9412
9432
  const rows = db.select({
9413
9433
  date: gscDailyTotals.date,
@@ -9415,7 +9435,7 @@ function readGscDailyTotals(db, projectId, startDate, endDate) {
9415
9435
  impressions: gscDailyTotals.impressions,
9416
9436
  position: gscDailyTotals.position
9417
9437
  }).from(gscDailyTotals).where(
9418
- and9(
9438
+ and10(
9419
9439
  eq14(gscDailyTotals.projectId, projectId),
9420
9440
  sql6`${gscDailyTotals.date} >= ${startDate}`,
9421
9441
  sql6`${gscDailyTotals.date} <= ${endDate}`
@@ -11846,7 +11866,7 @@ function buildGscSection(db, projectId, projectBrandNames, canonicalDomain, trac
11846
11866
  function buildGaSection(db, projectId, windowDays) {
11847
11867
  const gaWindowKey = GA_WINDOW_SUMMARY_KEYS[windowDays];
11848
11868
  const windowSummary = gaWindowKey ? db.select().from(gaTrafficWindowSummaries).where(
11849
- and10(
11869
+ and11(
11850
11870
  eq15(gaTrafficWindowSummaries.projectId, projectId),
11851
11871
  eq15(gaTrafficWindowSummaries.windowKey, gaWindowKey)
11852
11872
  )
@@ -12024,7 +12044,7 @@ function nonSubresourceReferralPathCondition() {
12024
12044
  }
12025
12045
  function buildServerActivity(db, projectId, windowDays) {
12026
12046
  const sourceRows = db.select({ id: trafficSources.id }).from(trafficSources).where(
12027
- and10(
12047
+ and11(
12028
12048
  eq15(trafficSources.projectId, projectId),
12029
12049
  ne2(trafficSources.status, TrafficSourceStatuses.archived)
12030
12050
  )
@@ -12040,7 +12060,7 @@ function buildServerActivity(db, projectId, windowDays) {
12040
12060
  const trendStart = new Date(trendStartMs).toISOString();
12041
12061
  const sumVerifiedCrawlers = (windowStartIso, windowEndIso, exclusiveEnd = false) => Number(
12042
12062
  db.select({ total: sql7`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
12043
- and10(
12063
+ and11(
12044
12064
  eq15(crawlerEventsHourly.projectId, projectId),
12045
12065
  eq15(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
12046
12066
  gte2(crawlerEventsHourly.tsHour, windowStartIso),
@@ -12050,7 +12070,7 @@ function buildServerActivity(db, projectId, windowDays) {
12050
12070
  );
12051
12071
  const sumUnverifiedCrawlers = (windowStartIso, windowEndIso, exclusiveEnd = false) => Number(
12052
12072
  db.select({ total: sql7`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
12053
- and10(
12073
+ and11(
12054
12074
  eq15(crawlerEventsHourly.projectId, projectId),
12055
12075
  ne2(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
12056
12076
  gte2(crawlerEventsHourly.tsHour, windowStartIso),
@@ -12060,7 +12080,7 @@ function buildServerActivity(db, projectId, windowDays) {
12060
12080
  );
12061
12081
  const sumReferrals = (windowStartIso, windowEndIso, exclusiveEnd = false) => Number(
12062
12082
  db.select({ total: sql7`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
12063
- and10(
12083
+ and11(
12064
12084
  eq15(aiReferralEventsHourly.projectId, projectId),
12065
12085
  nonSubresourceReferralPathCondition(),
12066
12086
  gte2(aiReferralEventsHourly.tsHour, windowStartIso),
@@ -12070,7 +12090,7 @@ function buildServerActivity(db, projectId, windowDays) {
12070
12090
  );
12071
12091
  const sumUserFetches = (windowStartIso, windowEndIso, exclusiveEnd = false) => Number(
12072
12092
  db.select({ total: sql7`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
12073
- and10(
12093
+ and11(
12074
12094
  eq15(aiUserFetchEventsHourly.projectId, projectId),
12075
12095
  gte2(aiUserFetchEventsHourly.tsHour, windowStartIso),
12076
12096
  exclusiveEnd ? lt(aiUserFetchEventsHourly.tsHour, windowEndIso) : lte(aiUserFetchEventsHourly.tsHour, windowEndIso)
@@ -12090,7 +12110,7 @@ function buildServerActivity(db, projectId, windowDays) {
12090
12110
  verificationStatus: crawlerEventsHourly.verificationStatus,
12091
12111
  hits: sql7`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
12092
12112
  }).from(crawlerEventsHourly).where(
12093
- and10(
12113
+ and11(
12094
12114
  eq15(crawlerEventsHourly.projectId, projectId),
12095
12115
  gte2(crawlerEventsHourly.tsHour, headlineStart),
12096
12116
  lte(crawlerEventsHourly.tsHour, headlineEnd)
@@ -12100,7 +12120,7 @@ function buildServerActivity(db, projectId, windowDays) {
12100
12120
  operator: crawlerEventsHourly.operator,
12101
12121
  hits: sql7`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
12102
12122
  }).from(crawlerEventsHourly).where(
12103
- and10(
12123
+ and11(
12104
12124
  eq15(crawlerEventsHourly.projectId, projectId),
12105
12125
  eq15(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
12106
12126
  gte2(crawlerEventsHourly.tsHour, priorStart),
@@ -12111,7 +12131,7 @@ function buildServerActivity(db, projectId, windowDays) {
12111
12131
  operator: aiReferralEventsHourly.operator,
12112
12132
  hits: sql7`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`
12113
12133
  }).from(aiReferralEventsHourly).where(
12114
- and10(
12134
+ and11(
12115
12135
  eq15(aiReferralEventsHourly.projectId, projectId),
12116
12136
  nonSubresourceReferralPathCondition(),
12117
12137
  gte2(aiReferralEventsHourly.tsHour, headlineStart),
@@ -12122,7 +12142,7 @@ function buildServerActivity(db, projectId, windowDays) {
12122
12142
  operator: aiUserFetchEventsHourly.operator,
12123
12143
  hits: sql7`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)`
12124
12144
  }).from(aiUserFetchEventsHourly).where(
12125
- and10(
12145
+ and11(
12126
12146
  eq15(aiUserFetchEventsHourly.projectId, projectId),
12127
12147
  gte2(aiUserFetchEventsHourly.tsHour, headlineStart),
12128
12148
  lte(aiUserFetchEventsHourly.tsHour, headlineEnd)
@@ -12166,7 +12186,7 @@ function buildServerActivity(db, projectId, windowDays) {
12166
12186
  hits: sql7`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`,
12167
12187
  operators: sql7`COUNT(DISTINCT ${crawlerEventsHourly.operator})`
12168
12188
  }).from(crawlerEventsHourly).where(
12169
- and10(
12189
+ and11(
12170
12190
  eq15(crawlerEventsHourly.projectId, projectId),
12171
12191
  eq15(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
12172
12192
  gte2(crawlerEventsHourly.tsHour, headlineStart),
@@ -12183,7 +12203,7 @@ function buildServerActivity(db, projectId, windowDays) {
12183
12203
  arrivals: sql7`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`,
12184
12204
  landingPaths: sql7`COUNT(DISTINCT ${aiReferralEventsHourly.landingPathNormalized})`
12185
12205
  }).from(aiReferralEventsHourly).where(
12186
- and10(
12206
+ and11(
12187
12207
  eq15(aiReferralEventsHourly.projectId, projectId),
12188
12208
  nonSubresourceReferralPathCondition(),
12189
12209
  gte2(aiReferralEventsHourly.tsHour, headlineStart),
@@ -12200,7 +12220,7 @@ function buildServerActivity(db, projectId, windowDays) {
12200
12220
  arrivals: sql7`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`,
12201
12221
  products: sql7`COUNT(DISTINCT ${aiReferralEventsHourly.product})`
12202
12222
  }).from(aiReferralEventsHourly).where(
12203
- and10(
12223
+ and11(
12204
12224
  eq15(aiReferralEventsHourly.projectId, projectId),
12205
12225
  nonSubresourceReferralPathCondition(),
12206
12226
  gte2(aiReferralEventsHourly.tsHour, headlineStart),
@@ -12216,7 +12236,7 @@ function buildServerActivity(db, projectId, windowDays) {
12216
12236
  date: sql7`SUBSTR(${crawlerEventsHourly.tsHour}, 1, 10)`,
12217
12237
  hits: sql7`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
12218
12238
  }).from(crawlerEventsHourly).where(
12219
- and10(
12239
+ and11(
12220
12240
  eq15(crawlerEventsHourly.projectId, projectId),
12221
12241
  eq15(crawlerEventsHourly.verificationStatus, VerificationStatuses.verified),
12222
12242
  gte2(crawlerEventsHourly.tsHour, trendStart),
@@ -12227,7 +12247,7 @@ function buildServerActivity(db, projectId, windowDays) {
12227
12247
  date: sql7`SUBSTR(${aiReferralEventsHourly.tsHour}, 1, 10)`,
12228
12248
  hits: sql7`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)`
12229
12249
  }).from(aiReferralEventsHourly).where(
12230
- and10(
12250
+ and11(
12231
12251
  eq15(aiReferralEventsHourly.projectId, projectId),
12232
12252
  nonSubresourceReferralPathCondition(),
12233
12253
  gte2(aiReferralEventsHourly.tsHour, trendStart),
@@ -12238,7 +12258,7 @@ function buildServerActivity(db, projectId, windowDays) {
12238
12258
  date: sql7`SUBSTR(${aiUserFetchEventsHourly.tsHour}, 1, 10)`,
12239
12259
  hits: sql7`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)`
12240
12260
  }).from(aiUserFetchEventsHourly).where(
12241
- and10(
12261
+ and11(
12242
12262
  eq15(aiUserFetchEventsHourly.projectId, projectId),
12243
12263
  gte2(aiUserFetchEventsHourly.tsHour, trendStart),
12244
12264
  lte(aiUserFetchEventsHourly.tsHour, headlineEnd)
@@ -12323,7 +12343,7 @@ function buildIndexingHealth(db, projectId) {
12323
12343
  return null;
12324
12344
  }
12325
12345
  function buildCitationsTrend(db, projectId, queryLookup, locationFilter) {
12326
- const visibilityRuns = db.select().from(runs).where(and10(eq15(runs.projectId, projectId), eq15(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).all().filter((r) => locationFilter === void 0 || (r.location ?? null) === locationFilter);
12346
+ const visibilityRuns = db.select().from(runs).where(and11(eq15(runs.projectId, projectId), eq15(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).all().filter((r) => locationFilter === void 0 || (r.location ?? null) === locationFilter);
12327
12347
  const totalQueries = queryLookup.byId.size;
12328
12348
  const points = [];
12329
12349
  for (const run of visibilityRuns) {
@@ -12371,7 +12391,7 @@ function buildCitationsTrend(db, projectId, queryLookup, locationFilter) {
12371
12391
  }
12372
12392
  function buildInsightList(db, projectId, locationFilter) {
12373
12393
  const recentRunIds = db.select({ id: runs.id, location: runs.location }).from(runs).where(
12374
- and10(
12394
+ and11(
12375
12395
  eq15(runs.projectId, projectId),
12376
12396
  eq15(runs.kind, RunKinds["answer-visibility"]),
12377
12397
  or3(eq15(runs.status, RunStatuses.completed), eq15(runs.status, RunStatuses.partial)),
@@ -12379,7 +12399,7 @@ function buildInsightList(db, projectId, locationFilter) {
12379
12399
  )
12380
12400
  ).orderBy(desc7(runs.createdAt)).all().filter((r) => locationFilter === void 0 || (r.location ?? null) === locationFilter).slice(0, INSIGHT_LOOKBACK_RUNS).map((r) => r.id);
12381
12401
  if (recentRunIds.length === 0) return [];
12382
- const rows = db.select().from(insights).where(and10(eq15(insights.projectId, projectId), inArray6(insights.runId, recentRunIds))).orderBy(desc7(insights.createdAt)).all();
12402
+ const rows = db.select().from(insights).where(and11(eq15(insights.projectId, projectId), inArray6(insights.runId, recentRunIds))).orderBy(desc7(insights.createdAt)).all();
12383
12403
  const severityRank = { critical: 0, high: 1, medium: 2, low: 3 };
12384
12404
  const flat = rows.filter((r) => !r.dismissed).map((r) => {
12385
12405
  const recommendation = r.recommendation;
@@ -12931,7 +12951,7 @@ function buildProjectReport(db, projectName, periodDays) {
12931
12951
  const project = resolveProject(db, projectName);
12932
12952
  const queryLookup = loadQueryLookup(db, project.id);
12933
12953
  const comparisonWindowDays = reportComparisonWindowDays(periodDays);
12934
- const allRuns = db.select().from(runs).where(and10(eq15(runs.projectId, project.id), notProbeRun())).orderBy(desc7(runs.createdAt), desc7(runs.id)).all();
12954
+ const allRuns = db.select().from(runs).where(and11(eq15(runs.projectId, project.id), notProbeRun())).orderBy(desc7(runs.createdAt), desc7(runs.id)).all();
12935
12955
  const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
12936
12956
  const completedVisRunGroups = groupRunsByCreatedAt(
12937
12957
  visibilityRuns.filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial)
@@ -13167,7 +13187,7 @@ async function reportRoutes(app) {
13167
13187
  }
13168
13188
 
13169
13189
  // ../api-routes/src/citations.ts
13170
- import { and as and11, eq as eq16, inArray as inArray7 } from "drizzle-orm";
13190
+ import { and as and12, eq as eq16, inArray as inArray7 } from "drizzle-orm";
13171
13191
  async function citationRoutes(app) {
13172
13192
  app.get("/projects/:name/citations/visibility", async (request, reply) => {
13173
13193
  const project = resolveProject(app.db, request.params.name);
@@ -13176,7 +13196,7 @@ async function citationRoutes(app) {
13176
13196
  if (projectQueries.length === 0) {
13177
13197
  return reply.send(emptyCitationVisibility("no-queries"));
13178
13198
  }
13179
- const projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and11(eq16(runs.projectId, project.id), notProbeRun())).all();
13199
+ const projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(and12(eq16(runs.projectId, project.id), notProbeRun())).all();
13180
13200
  if (projectRuns.length === 0) {
13181
13201
  return reply.send(emptyCitationVisibility("no-runs-yet"));
13182
13202
  }
@@ -13332,7 +13352,7 @@ function normalizeDomain2(domain) {
13332
13352
  }
13333
13353
 
13334
13354
  // ../api-routes/src/visibility-stats.ts
13335
- import { and as and12, desc as desc8, eq as eq17, inArray as inArray8 } from "drizzle-orm";
13355
+ import { and as and13, desc as desc8, eq as eq17, inArray as inArray8 } from "drizzle-orm";
13336
13356
  function round42(value) {
13337
13357
  return Math.round(value * 1e4) / 1e4;
13338
13358
  }
@@ -13484,7 +13504,7 @@ async function visibilityStatsRoutes(app) {
13484
13504
  lastRuns = n;
13485
13505
  }
13486
13506
  const projectQueries = app.db.select({ id: queries.id, query: queries.query }).from(queries).where(eq17(queries.projectId, project.id)).all();
13487
- let projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt, status: runs.status }).from(runs).where(and12(eq17(runs.projectId, project.id), eq17(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc8(runs.createdAt)).all().filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial);
13507
+ let projectRuns = app.db.select({ id: runs.id, createdAt: runs.createdAt, status: runs.status }).from(runs).where(and13(eq17(runs.projectId, project.id), eq17(runs.kind, RunKinds["answer-visibility"]), notProbeRun())).orderBy(desc8(runs.createdAt)).all().filter((r) => r.status === RunStatuses.completed || r.status === RunStatuses.partial);
13488
13508
  if (sinceMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) >= sinceMs);
13489
13509
  if (untilMs !== null) projectRuns = projectRuns.filter((r) => Date.parse(r.createdAt) <= untilMs);
13490
13510
  if (lastRuns !== null) projectRuns = projectRuns.slice(0, lastRuns);
@@ -13554,7 +13574,7 @@ async function visibilityStatsRoutes(app) {
13554
13574
  }
13555
13575
 
13556
13576
  // ../api-routes/src/composites.ts
13557
- import { eq as eq18, and as and13, desc as desc9, sql as sql8, like as like2, or as or4, inArray as inArray9 } from "drizzle-orm";
13577
+ import { eq as eq18, and as and14, desc as desc9, sql as sql8, like as like2, or as or4, inArray as inArray9 } from "drizzle-orm";
13558
13578
  var TOP_INSIGHT_LIMIT = 5;
13559
13579
  var SEARCH_HIT_HARD_LIMIT = 50;
13560
13580
  var SEARCH_SNIPPET_RADIUS = 80;
@@ -13572,7 +13592,7 @@ async function compositeRoutes(app) {
13572
13592
  const project = resolveProject(app.db, request.params.name);
13573
13593
  const filterLocation = (request.query.location ?? "").trim() || null;
13574
13594
  const sinceIso = parseSinceFilter(request.query.since);
13575
- const allRunsRaw = app.db.select().from(runs).where(and13(eq18(runs.projectId, project.id), notProbeRun())).orderBy(desc9(runs.createdAt), desc9(runs.id)).all();
13595
+ const allRunsRaw = app.db.select().from(runs).where(and14(eq18(runs.projectId, project.id), notProbeRun())).orderBy(desc9(runs.createdAt), desc9(runs.id)).all();
13576
13596
  const allRuns = allRunsRaw.filter((r) => runMatchesFilters(r, filterLocation, sinceIso));
13577
13597
  const totalRuns = allRuns.length;
13578
13598
  const visibilityRuns = allRuns.filter((r) => r.kind === RunKinds["answer-visibility"]);
@@ -13728,7 +13748,7 @@ async function compositeRoutes(app) {
13728
13748
  rawResponse: querySnapshots.rawResponse,
13729
13749
  createdAt: querySnapshots.createdAt
13730
13750
  }).from(querySnapshots).innerJoin(queries, eq18(querySnapshots.queryId, queries.id)).where(
13731
- and13(
13751
+ and14(
13732
13752
  eq18(queries.projectId, project.id),
13733
13753
  or4(
13734
13754
  sql8`${querySnapshots.answerText} LIKE ${pattern} ESCAPE '\\'`,
@@ -13739,7 +13759,7 @@ async function compositeRoutes(app) {
13739
13759
  )
13740
13760
  ).orderBy(desc9(querySnapshots.createdAt)).limit(limit + 1).all());
13741
13761
  const insightMatches = app.db.select().from(insights).where(
13742
- and13(
13762
+ and14(
13743
13763
  eq18(insights.projectId, project.id),
13744
13764
  or4(
13745
13765
  like2(insights.title, pattern),
@@ -13956,7 +13976,7 @@ function buildSuggestedQueriesFromGsc(app, projectId, trackedQueries) {
13956
13976
  // NULLIF guards the degenerate impressions=0 case (SQLite returns NULL,
13957
13977
  // which the JS coerces to 0 — caught by the impression floor anyway).
13958
13978
  avgPosition: sql8`COALESCE(SUM(${gscSearchData.position} * ${gscSearchData.impressions}) * 1.0 / NULLIF(SUM(${gscSearchData.impressions}), 0), 0)`
13959
- }).from(gscSearchData).where(and13(
13979
+ }).from(gscSearchData).where(and14(
13960
13980
  eq18(gscSearchData.projectId, projectId),
13961
13981
  sql8`${gscSearchData.date} >= ${cutoff}`,
13962
13982
  sql8`${gscSearchData.impressions} > 0`
@@ -14464,6 +14484,13 @@ var runIdParameter = {
14464
14484
  description: "Run ID.",
14465
14485
  schema: stringSchema
14466
14486
  };
14487
+ var queryIdParameter = {
14488
+ name: "id",
14489
+ in: "path",
14490
+ required: true,
14491
+ description: "Query ID.",
14492
+ schema: stringSchema
14493
+ };
14467
14494
  var notificationIdParameter = {
14468
14495
  name: "id",
14469
14496
  in: "path",
@@ -14870,6 +14897,17 @@ var routeCatalog = [
14870
14897
  400: errorResponse("Invalid query delete request.")
14871
14898
  }
14872
14899
  },
14900
+ {
14901
+ method: "delete",
14902
+ path: "/api/v1/projects/{name}/queries/{id}",
14903
+ summary: "Delete one query by ID",
14904
+ tags: ["queries"],
14905
+ parameters: [nameParameter, queryIdParameter],
14906
+ responses: {
14907
+ 204: { description: "Query deleted." },
14908
+ 404: errorResponse("Project or query not found.")
14909
+ }
14910
+ },
14873
14911
  {
14874
14912
  method: "post",
14875
14913
  path: "/api/v1/projects/{name}/queries",
@@ -18862,7 +18900,7 @@ async function telemetryRoutes(app, opts) {
18862
18900
 
18863
18901
  // ../api-routes/src/schedules.ts
18864
18902
  import crypto13 from "crypto";
18865
- import { and as and14, eq as eq20 } from "drizzle-orm";
18903
+ import { and as and15, eq as eq20 } from "drizzle-orm";
18866
18904
  function parseKindParam(raw) {
18867
18905
  if (raw === void 0 || raw === null || raw === "") return SchedulableRunKinds["answer-visibility"];
18868
18906
  const parsed = schedulableRunKindSchema.safeParse(raw);
@@ -18934,7 +18972,7 @@ async function scheduleRoutes(app, opts) {
18934
18972
  }
18935
18973
  const now = (/* @__PURE__ */ new Date()).toISOString();
18936
18974
  const enabledBool = enabled !== false;
18937
- const existing = app.db.select().from(schedules).where(and14(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
18975
+ const existing = app.db.select().from(schedules).where(and15(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
18938
18976
  if (existing) {
18939
18977
  app.db.update(schedules).set({
18940
18978
  cronExpr,
@@ -18968,13 +19006,13 @@ async function scheduleRoutes(app, opts) {
18968
19006
  diff: { kind, cronExpr, preset, timezone, providers, sourceId }
18969
19007
  });
18970
19008
  opts.onScheduleUpdated?.("upsert", project.id, kind);
18971
- const schedule = app.db.select().from(schedules).where(and14(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
19009
+ const schedule = app.db.select().from(schedules).where(and15(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
18972
19010
  return reply.status(existing ? 200 : 201).send(formatSchedule(schedule));
18973
19011
  });
18974
19012
  app.get("/projects/:name/schedule", async (request, reply) => {
18975
19013
  const project = resolveProject(app.db, request.params.name);
18976
19014
  const kind = parseKindParam(request.query?.kind);
18977
- const schedule = app.db.select().from(schedules).where(and14(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
19015
+ const schedule = app.db.select().from(schedules).where(and15(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
18978
19016
  if (!schedule) {
18979
19017
  throw notFound("Schedule", `${request.params.name} (kind=${kind})`);
18980
19018
  }
@@ -18983,7 +19021,7 @@ async function scheduleRoutes(app, opts) {
18983
19021
  app.delete("/projects/:name/schedule", async (request, reply) => {
18984
19022
  const project = resolveProject(app.db, request.params.name);
18985
19023
  const kind = parseKindParam(request.query?.kind);
18986
- const schedule = app.db.select().from(schedules).where(and14(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
19024
+ const schedule = app.db.select().from(schedules).where(and15(eq20(schedules.projectId, project.id), eq20(schedules.kind, kind))).get();
18987
19025
  if (!schedule) {
18988
19026
  throw notFound("Schedule", `${request.params.name} (kind=${kind})`);
18989
19027
  }
@@ -19140,7 +19178,7 @@ function formatNotification(row) {
19140
19178
 
19141
19179
  // ../api-routes/src/google.ts
19142
19180
  import crypto18 from "crypto";
19143
- import { eq as eq22, and as and15, desc as desc11, sql as sql9, inArray as inArray10 } from "drizzle-orm";
19181
+ import { eq as eq22, and as and16, desc as desc11, sql as sql9, inArray as inArray10 } from "drizzle-orm";
19144
19182
 
19145
19183
  // ../api-routes/src/gbp-summary.ts
19146
19184
  function computeMetricTotals(rows) {
@@ -21120,7 +21158,7 @@ async function googleRoutes(app, opts) {
21120
21158
  if (page) conditions.push(sql9`${gscSearchData.page} LIKE ${"%" + escapeLikePattern(page) + "%"} ESCAPE '\\'`);
21121
21159
  const limitVal = Math.max(parseInt(limit ?? "500", 10) || 0, 1);
21122
21160
  const offsetVal = Math.max(parseInt(offset ?? "0", 10) || 0, 0);
21123
- const rows = app.db.select().from(gscSearchData).where(and15(...conditions)).orderBy(desc11(gscSearchData.date)).limit(limitVal).offset(offsetVal).all();
21161
+ const rows = app.db.select().from(gscSearchData).where(and16(...conditions)).orderBy(desc11(gscSearchData.date)).limit(limitVal).offset(offsetVal).all();
21124
21162
  return rows.map((r) => ({
21125
21163
  date: r.date,
21126
21164
  query: r.query,
@@ -21148,7 +21186,7 @@ async function googleRoutes(app, opts) {
21148
21186
  date: gscSearchData.date,
21149
21187
  clicks: sql9`COALESCE(SUM(${gscSearchData.clicks}), 0)`,
21150
21188
  impressions: sql9`COALESCE(SUM(${gscSearchData.impressions}), 0)`
21151
- }).from(gscSearchData).where(and15(...conditions)).groupBy(gscSearchData.date).orderBy(gscSearchData.date).all();
21189
+ }).from(gscSearchData).where(and16(...conditions)).groupBy(gscSearchData.date).orderBy(gscSearchData.date).all();
21152
21190
  const daily = mergeGscDailyTotalsWithFallback(
21153
21191
  dailyTotals,
21154
21192
  dimensionedRows.map((r) => ({
@@ -21241,7 +21279,7 @@ async function googleRoutes(app, opts) {
21241
21279
  const { url, limit } = request.query;
21242
21280
  const conditions = [eq22(gscUrlInspections.projectId, project.id)];
21243
21281
  if (url) conditions.push(eq22(gscUrlInspections.url, url));
21244
- const rows = app.db.select().from(gscUrlInspections).where(and15(...conditions)).orderBy(desc11(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
21282
+ const rows = app.db.select().from(gscUrlInspections).where(and16(...conditions)).orderBy(desc11(gscUrlInspections.inspectedAt)).limit(parseInt(limit ?? "100", 10)).all();
21245
21283
  return rows.map((r) => ({
21246
21284
  id: r.id,
21247
21285
  url: r.url,
@@ -21736,7 +21774,7 @@ async function googleRoutes(app, opts) {
21736
21774
  app.db.transaction((tx) => {
21737
21775
  if (switching) clearGbpProjectData(tx, project.id);
21738
21776
  for (const remote of remoteLocations) {
21739
- const existing = tx.select().from(gbpLocations).where(and15(eq22(gbpLocations.projectId, project.id), eq22(gbpLocations.locationName, remote.name))).get();
21777
+ const existing = tx.select().from(gbpLocations).where(and16(eq22(gbpLocations.projectId, project.id), eq22(gbpLocations.locationName, remote.name))).get();
21740
21778
  const profile = buildLocationProfileFields(remote);
21741
21779
  if (existing) {
21742
21780
  tx.update(gbpLocations).set({
@@ -21833,7 +21871,7 @@ async function googleRoutes(app, opts) {
21833
21871
  throw validationError(parsed.error.issues[0]?.message ?? "Invalid selection request");
21834
21872
  }
21835
21873
  const { selected } = parsed.data;
21836
- const existing = app.db.select().from(gbpLocations).where(and15(eq22(gbpLocations.projectId, project.id), eq22(gbpLocations.locationName, locationName))).get();
21874
+ const existing = app.db.select().from(gbpLocations).where(and16(eq22(gbpLocations.projectId, project.id), eq22(gbpLocations.locationName, locationName))).get();
21837
21875
  if (!existing) throw notFound("GBP location", locationName);
21838
21876
  const now = (/* @__PURE__ */ new Date()).toISOString();
21839
21877
  app.db.transaction((tx) => {
@@ -21893,7 +21931,7 @@ async function googleRoutes(app, opts) {
21893
21931
  const conditions = [eq22(gbpDailyMetrics.projectId, project.id)];
21894
21932
  if (request.query.locationName) conditions.push(eq22(gbpDailyMetrics.locationName, request.query.locationName));
21895
21933
  if (request.query.metric) conditions.push(eq22(gbpDailyMetrics.metric, request.query.metric));
21896
- const rows = app.db.select().from(gbpDailyMetrics).where(and15(...conditions)).orderBy(desc11(gbpDailyMetrics.date)).all();
21934
+ const rows = app.db.select().from(gbpDailyMetrics).where(and16(...conditions)).orderBy(desc11(gbpDailyMetrics.date)).all();
21897
21935
  return {
21898
21936
  metrics: rows.map((r) => ({ locationName: r.locationName, date: r.date, metric: r.metric, value: r.value })),
21899
21937
  total: rows.length
@@ -21903,7 +21941,7 @@ async function googleRoutes(app, opts) {
21903
21941
  const project = resolveProject(app.db, request.params.name);
21904
21942
  const conditions = [eq22(gbpKeywordImpressions.projectId, project.id)];
21905
21943
  if (request.query.locationName) conditions.push(eq22(gbpKeywordImpressions.locationName, request.query.locationName));
21906
- const rows = app.db.select().from(gbpKeywordImpressions).where(and15(...conditions)).all();
21944
+ const rows = app.db.select().from(gbpKeywordImpressions).where(and16(...conditions)).all();
21907
21945
  rows.sort((a, b) => (b.valueCount ?? -1) - (a.valueCount ?? -1));
21908
21946
  const thresholded = rows.filter((r) => r.valueThreshold !== null).length;
21909
21947
  return {
@@ -21923,7 +21961,7 @@ async function googleRoutes(app, opts) {
21923
21961
  const project = resolveProject(app.db, request.params.name);
21924
21962
  const conditions = [eq22(gbpPlaceActions.projectId, project.id)];
21925
21963
  if (request.query.locationName) conditions.push(eq22(gbpPlaceActions.locationName, request.query.locationName));
21926
- const rows = app.db.select().from(gbpPlaceActions).where(and15(...conditions)).all();
21964
+ const rows = app.db.select().from(gbpPlaceActions).where(and16(...conditions)).all();
21927
21965
  return {
21928
21966
  placeActions: rows.map((r) => ({
21929
21967
  locationName: r.locationName,
@@ -21940,7 +21978,7 @@ async function googleRoutes(app, opts) {
21940
21978
  const project = resolveProject(app.db, request.params.name);
21941
21979
  const conditions = [eq22(gbpLodgingSnapshots.projectId, project.id)];
21942
21980
  if (request.query.locationName) conditions.push(eq22(gbpLodgingSnapshots.locationName, request.query.locationName));
21943
- const rows = app.db.select().from(gbpLodgingSnapshots).where(and15(...conditions)).orderBy(desc11(gbpLodgingSnapshots.syncedAt)).all();
21981
+ const rows = app.db.select().from(gbpLodgingSnapshots).where(and16(...conditions)).orderBy(desc11(gbpLodgingSnapshots.syncedAt)).all();
21944
21982
  const latestByLocation = /* @__PURE__ */ new Map();
21945
21983
  for (const row of rows) {
21946
21984
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -21957,7 +21995,7 @@ async function googleRoutes(app, opts) {
21957
21995
  const project = resolveProject(app.db, request.params.name);
21958
21996
  const conditions = [eq22(gbpAttributesSnapshots.projectId, project.id)];
21959
21997
  if (request.query.locationName) conditions.push(eq22(gbpAttributesSnapshots.locationName, request.query.locationName));
21960
- const rows = app.db.select().from(gbpAttributesSnapshots).where(and15(...conditions)).orderBy(desc11(gbpAttributesSnapshots.syncedAt)).all();
21998
+ const rows = app.db.select().from(gbpAttributesSnapshots).where(and16(...conditions)).orderBy(desc11(gbpAttributesSnapshots.syncedAt)).all();
21961
21999
  const latestByLocation = /* @__PURE__ */ new Map();
21962
22000
  for (const row of rows) {
21963
22001
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -21977,7 +22015,7 @@ async function googleRoutes(app, opts) {
21977
22015
  const project = resolveProject(app.db, request.params.name);
21978
22016
  const conditions = [eq22(gbpPlaceDetails.projectId, project.id)];
21979
22017
  if (request.query.locationName) conditions.push(eq22(gbpPlaceDetails.locationName, request.query.locationName));
21980
- const rows = app.db.select().from(gbpPlaceDetails).where(and15(...conditions)).orderBy(desc11(gbpPlaceDetails.syncedAt)).all();
22018
+ const rows = app.db.select().from(gbpPlaceDetails).where(and16(...conditions)).orderBy(desc11(gbpPlaceDetails.syncedAt)).all();
21981
22019
  const latestByLocation = /* @__PURE__ */ new Map();
21982
22020
  for (const row of rows) {
21983
22021
  if (!latestByLocation.has(row.locationName)) latestByLocation.set(row.locationName, row);
@@ -21996,7 +22034,7 @@ async function googleRoutes(app, opts) {
21996
22034
  app.get("/projects/:name/gbp/summary", async (request) => {
21997
22035
  const project = resolveProject(app.db, request.params.name);
21998
22036
  const locationName = request.query.locationName ?? null;
21999
- const locationNames = locationName ? [locationName] : app.db.select({ n: gbpLocations.locationName }).from(gbpLocations).where(and15(eq22(gbpLocations.projectId, project.id), eq22(gbpLocations.selected, true))).all().map((r) => r.n);
22037
+ const locationNames = locationName ? [locationName] : app.db.select({ n: gbpLocations.locationName }).from(gbpLocations).where(and16(eq22(gbpLocations.projectId, project.id), eq22(gbpLocations.selected, true))).all().map((r) => r.n);
22000
22038
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
22001
22039
  if (locationNames.length === 0) {
22002
22040
  return buildGbpSummary({
@@ -22010,10 +22048,10 @@ async function googleRoutes(app, opts) {
22010
22048
  locationProfiles: []
22011
22049
  });
22012
22050
  }
22013
- const metricRows = app.db.select().from(gbpDailyMetrics).where(and15(eq22(gbpDailyMetrics.projectId, project.id), inArray10(gbpDailyMetrics.locationName, locationNames))).all();
22014
- const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and15(eq22(gbpKeywordImpressions.projectId, project.id), inArray10(gbpKeywordImpressions.locationName, locationNames))).all();
22015
- const placeActionRows = app.db.select().from(gbpPlaceActions).where(and15(eq22(gbpPlaceActions.projectId, project.id), inArray10(gbpPlaceActions.locationName, locationNames))).all();
22016
- const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and15(eq22(gbpLodgingSnapshots.projectId, project.id), inArray10(gbpLodgingSnapshots.locationName, locationNames))).orderBy(desc11(gbpLodgingSnapshots.syncedAt)).all();
22051
+ const metricRows = app.db.select().from(gbpDailyMetrics).where(and16(eq22(gbpDailyMetrics.projectId, project.id), inArray10(gbpDailyMetrics.locationName, locationNames))).all();
22052
+ const keywordRows = app.db.select().from(gbpKeywordImpressions).where(and16(eq22(gbpKeywordImpressions.projectId, project.id), inArray10(gbpKeywordImpressions.locationName, locationNames))).all();
22053
+ const placeActionRows = app.db.select().from(gbpPlaceActions).where(and16(eq22(gbpPlaceActions.projectId, project.id), inArray10(gbpPlaceActions.locationName, locationNames))).all();
22054
+ const lodgingRows = app.db.select().from(gbpLodgingSnapshots).where(and16(eq22(gbpLodgingSnapshots.projectId, project.id), inArray10(gbpLodgingSnapshots.locationName, locationNames))).orderBy(desc11(gbpLodgingSnapshots.syncedAt)).all();
22017
22055
  const latestLodgingByLocation = /* @__PURE__ */ new Map();
22018
22056
  for (const row of lodgingRows) {
22019
22057
  if (!latestLodgingByLocation.has(row.locationName)) {
@@ -22027,7 +22065,7 @@ async function googleRoutes(app, opts) {
22027
22065
  regularHours: gbpLocations.regularHours,
22028
22066
  primaryPhone: gbpLocations.primaryPhone,
22029
22067
  openStatus: gbpLocations.openStatus
22030
- }).from(gbpLocations).where(and15(eq22(gbpLocations.projectId, project.id), inArray10(gbpLocations.locationName, locationNames))).all();
22068
+ }).from(gbpLocations).where(and16(eq22(gbpLocations.projectId, project.id), inArray10(gbpLocations.locationName, locationNames))).all();
22031
22069
  return buildGbpSummary({
22032
22070
  locationName,
22033
22071
  locationCount: locationNames.length,
@@ -22043,7 +22081,7 @@ async function googleRoutes(app, opts) {
22043
22081
 
22044
22082
  // ../api-routes/src/ads.ts
22045
22083
  import crypto19 from "crypto";
22046
- import { eq as eq23, and as and16, asc as asc3, gte as gte3, lte as lte2, inArray as inArray11 } from "drizzle-orm";
22084
+ import { eq as eq23, and as and17, asc as asc3, gte as gte3, lte as lte2, inArray as inArray11 } from "drizzle-orm";
22047
22085
  function statusDto(row) {
22048
22086
  if (!row) return { connected: false };
22049
22087
  return {
@@ -22159,7 +22197,7 @@ async function adsRoutes(app, opts) {
22159
22197
  if (!row) {
22160
22198
  throw validationError('No ads connection for this project. Run "canonry ads connect" first.');
22161
22199
  }
22162
- const inFlight = app.db.select({ id: runs.id, status: runs.status }).from(runs).where(and16(
22200
+ const inFlight = app.db.select({ id: runs.id, status: runs.status }).from(runs).where(and17(
22163
22201
  eq23(runs.projectId, project.id),
22164
22202
  eq23(runs.kind, RunKinds["ads-sync"]),
22165
22203
  inArray11(runs.status, [RunStatuses.queued, RunStatuses.running])
@@ -22244,7 +22282,7 @@ async function adsRoutes(app, opts) {
22244
22282
  if (entityId) conditions.push(eq23(adsInsightsDaily.entityId, entityId));
22245
22283
  if (from) conditions.push(gte3(adsInsightsDaily.date, from));
22246
22284
  if (to) conditions.push(lte2(adsInsightsDaily.date, to));
22247
- const rows = app.db.select().from(adsInsightsDaily).where(and16(...conditions)).orderBy(asc3(adsInsightsDaily.date)).all();
22285
+ const rows = app.db.select().from(adsInsightsDaily).where(and17(...conditions)).orderBy(asc3(adsInsightsDaily.date)).all();
22248
22286
  const dtoRows = rows.map((row) => ({
22249
22287
  level: row.level,
22250
22288
  entityId: row.entityId,
@@ -22266,7 +22304,7 @@ async function adsRoutes(app, opts) {
22266
22304
  const campaignCount = app.db.select().from(adsCampaigns).where(eq23(adsCampaigns.projectId, project.id)).all().length;
22267
22305
  const adGroupCount = app.db.select().from(adsAdGroups).where(eq23(adsAdGroups.projectId, project.id)).all().length;
22268
22306
  const adCount = app.db.select().from(adsAds).where(eq23(adsAds.projectId, project.id)).all().length;
22269
- const campaignInsights = app.db.select().from(adsInsightsDaily).where(and16(
22307
+ const campaignInsights = app.db.select().from(adsInsightsDaily).where(and17(
22270
22308
  eq23(adsInsightsDaily.projectId, project.id),
22271
22309
  eq23(adsInsightsDaily.level, "campaign")
22272
22310
  )).all();
@@ -22308,7 +22346,7 @@ async function adsRoutes(app, opts) {
22308
22346
 
22309
22347
  // ../api-routes/src/bing.ts
22310
22348
  import crypto20 from "crypto";
22311
- import { eq as eq24, and as and17, desc as desc12 } from "drizzle-orm";
22349
+ import { eq as eq24, and as and18, desc as desc12 } from "drizzle-orm";
22312
22350
 
22313
22351
  // ../integration-bing/src/constants.ts
22314
22352
  var BING_WMT_API_BASE = "https://ssl.bing.com/webmaster/api.svc/json";
@@ -22783,7 +22821,7 @@ async function bingRoutes(app, opts) {
22783
22821
  requireConnectionStore();
22784
22822
  const project = resolveProject(app.db, request.params.name);
22785
22823
  const { url, limit } = request.query;
22786
- const whereClause = url ? and17(eq24(bingUrlInspections.projectId, project.id), eq24(bingUrlInspections.url, url)) : eq24(bingUrlInspections.projectId, project.id);
22824
+ const whereClause = url ? and18(eq24(bingUrlInspections.projectId, project.id), eq24(bingUrlInspections.url, url)) : eq24(bingUrlInspections.projectId, project.id);
22787
22825
  const filtered = app.db.select().from(bingUrlInspections).where(whereClause).orderBy(desc12(bingUrlInspections.inspectedAt)).limit(Math.max(1, Math.min(parseInt(limit ?? "100", 10) || 100, 1e3))).all();
22788
22826
  return filtered.map((r) => ({
22789
22827
  id: r.id,
@@ -23015,7 +23053,7 @@ async function bingRoutes(app, opts) {
23015
23053
  import fs from "fs";
23016
23054
  import path from "path";
23017
23055
  import os from "os";
23018
- import { eq as eq25, and as and18 } from "drizzle-orm";
23056
+ import { eq as eq25, and as and19 } from "drizzle-orm";
23019
23057
  function getScreenshotDir() {
23020
23058
  return path.join(os.homedir(), ".canonry", "screenshots");
23021
23059
  }
@@ -23090,7 +23128,7 @@ async function cdpRoutes(app, opts) {
23090
23128
  async (request, reply) => {
23091
23129
  const project = resolveProject(app.db, request.params.name);
23092
23130
  const { runId } = request.params;
23093
- const run = app.db.select().from(runs).where(and18(eq25(runs.id, runId), eq25(runs.projectId, project.id))).get();
23131
+ const run = app.db.select().from(runs).where(and19(eq25(runs.id, runId), eq25(runs.projectId, project.id))).get();
23094
23132
  if (!run) {
23095
23133
  const err = notFound("Run", runId);
23096
23134
  return reply.code(err.statusCode).send(err.toJSON());
@@ -23187,7 +23225,7 @@ async function cdpRoutes(app, opts) {
23187
23225
 
23188
23226
  // ../api-routes/src/ga.ts
23189
23227
  import crypto21 from "crypto";
23190
- import { eq as eq26, desc as desc13, and as and19, sql as sql10 } from "drizzle-orm";
23228
+ import { eq as eq26, desc as desc13, and as and20, sql as sql10 } from "drizzle-orm";
23191
23229
  function gaLog(level, action, ctx) {
23192
23230
  const entry = { ts: (/* @__PURE__ */ new Date()).toISOString(), level, module: "GA4Routes", action, ...ctx };
23193
23231
  const stream = level === "error" ? process.stderr : process.stdout;
@@ -23482,7 +23520,7 @@ async function ga4Routes(app, opts) {
23482
23520
  app.db.transaction((tx) => {
23483
23521
  if (syncTraffic) {
23484
23522
  tx.delete(gaTrafficSnapshots).where(
23485
- and19(
23523
+ and20(
23486
23524
  eq26(gaTrafficSnapshots.projectId, project.id),
23487
23525
  sql10`${gaTrafficSnapshots.date} >= ${summary.periodStart}`,
23488
23526
  sql10`${gaTrafficSnapshots.date} <= ${summary.periodEnd}`
@@ -23506,7 +23544,7 @@ async function ga4Routes(app, opts) {
23506
23544
  }
23507
23545
  if (syncAi) {
23508
23546
  tx.delete(gaAiReferrals).where(
23509
- and19(
23547
+ and20(
23510
23548
  eq26(gaAiReferrals.projectId, project.id),
23511
23549
  sql10`${gaAiReferrals.date} >= ${summary.periodStart}`,
23512
23550
  sql10`${gaAiReferrals.date} <= ${summary.periodEnd}`
@@ -23532,7 +23570,7 @@ async function ga4Routes(app, opts) {
23532
23570
  }
23533
23571
  if (syncSocial) {
23534
23572
  tx.delete(gaSocialReferrals).where(
23535
- and19(
23573
+ and20(
23536
23574
  eq26(gaSocialReferrals.projectId, project.id),
23537
23575
  sql10`${gaSocialReferrals.date} >= ${summary.periodStart}`,
23538
23576
  sql10`${gaSocialReferrals.date} <= ${summary.periodEnd}`
@@ -23636,7 +23674,7 @@ async function ga4Routes(app, opts) {
23636
23674
  totalDirectSessions: gaTrafficWindowSummaries.totalDirectSessions,
23637
23675
  totalUsers: gaTrafficWindowSummaries.totalUsers
23638
23676
  }).from(gaTrafficWindowSummaries).where(
23639
- and19(
23677
+ and20(
23640
23678
  eq26(gaTrafficWindowSummaries.projectId, project.id),
23641
23679
  eq26(gaTrafficWindowSummaries.windowKey, window)
23642
23680
  )
@@ -23645,7 +23683,7 @@ async function ga4Routes(app, opts) {
23645
23683
  totalSessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)`,
23646
23684
  totalOrganicSessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)`,
23647
23685
  totalUsers: sql10`COALESCE(SUM(${gaTrafficSnapshots.users}), 0)`
23648
- }).from(gaTrafficSnapshots).where(and19(...snapshotConditions)).get() : null;
23686
+ }).from(gaTrafficSnapshots).where(and20(...snapshotConditions)).get() : null;
23649
23687
  const summaryRow = cutoffDate ? windowSummaryRow ?? snapshotTotalsRow : app.db.select({
23650
23688
  totalSessions: gaTrafficSummaries.totalSessions,
23651
23689
  totalOrganicSessions: gaTrafficSummaries.totalOrganicSessions,
@@ -23653,7 +23691,7 @@ async function ga4Routes(app, opts) {
23653
23691
  }).from(gaTrafficSummaries).where(eq26(gaTrafficSummaries.projectId, project.id)).get();
23654
23692
  const directTotalRow = windowSummaryRow ? { totalDirectSessions: windowSummaryRow.totalDirectSessions } : app.db.select({
23655
23693
  totalDirectSessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)`
23656
- }).from(gaTrafficSnapshots).where(and19(...snapshotConditions)).get();
23694
+ }).from(gaTrafficSnapshots).where(and20(...snapshotConditions)).get();
23657
23695
  const summaryMeta = app.db.select({
23658
23696
  periodStart: gaTrafficSummaries.periodStart,
23659
23697
  periodEnd: gaTrafficSummaries.periodEnd
@@ -23664,14 +23702,14 @@ async function ga4Routes(app, opts) {
23664
23702
  organicSessions: sql10`SUM(${gaTrafficSnapshots.organicSessions})`,
23665
23703
  directSessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)`,
23666
23704
  users: sql10`SUM(${gaTrafficSnapshots.users})`
23667
- }).from(gaTrafficSnapshots).where(and19(...snapshotConditions)).groupBy(sql10`COALESCE(${gaTrafficSnapshots.landingPageNormalized}, ${gaTrafficSnapshots.landingPage})`).orderBy(sql10`SUM(${gaTrafficSnapshots.sessions}) DESC`).limit(limit).all();
23705
+ }).from(gaTrafficSnapshots).where(and20(...snapshotConditions)).groupBy(sql10`COALESCE(${gaTrafficSnapshots.landingPageNormalized}, ${gaTrafficSnapshots.landingPage})`).orderBy(sql10`SUM(${gaTrafficSnapshots.sessions}) DESC`).limit(limit).all();
23668
23706
  const aiReferralRows = app.db.select({
23669
23707
  source: gaAiReferrals.source,
23670
23708
  medium: gaAiReferrals.medium,
23671
23709
  sourceDimension: gaAiReferrals.sourceDimension,
23672
23710
  sessions: sql10`SUM(${gaAiReferrals.sessions})`,
23673
23711
  users: sql10`SUM(${gaAiReferrals.users})`
23674
- }).from(gaAiReferrals).where(and19(...aiConditions)).groupBy(gaAiReferrals.source, gaAiReferrals.medium, gaAiReferrals.sourceDimension).all();
23712
+ }).from(gaAiReferrals).where(and20(...aiConditions)).groupBy(gaAiReferrals.source, gaAiReferrals.medium, gaAiReferrals.sourceDimension).all();
23675
23713
  const aiReferralLandingPageRows = app.db.select({
23676
23714
  source: gaAiReferrals.source,
23677
23715
  medium: gaAiReferrals.medium,
@@ -23679,7 +23717,7 @@ async function ga4Routes(app, opts) {
23679
23717
  landingPage: sql10`COALESCE(${gaAiReferrals.landingPageNormalized}, ${gaAiReferrals.landingPage})`,
23680
23718
  sessions: sql10`SUM(${gaAiReferrals.sessions})`,
23681
23719
  users: sql10`SUM(${gaAiReferrals.users})`
23682
- }).from(gaAiReferrals).where(and19(...aiConditions)).groupBy(
23720
+ }).from(gaAiReferrals).where(and20(...aiConditions)).groupBy(
23683
23721
  gaAiReferrals.source,
23684
23722
  gaAiReferrals.medium,
23685
23723
  gaAiReferrals.sourceDimension,
@@ -23716,7 +23754,7 @@ async function ga4Routes(app, opts) {
23716
23754
  channelGroup: gaAiReferrals.channelGroup,
23717
23755
  sessions: sql10`COALESCE(SUM(${gaAiReferrals.sessions}), 0)`,
23718
23756
  users: sql10`COALESCE(SUM(${gaAiReferrals.users}), 0)`
23719
- }).from(gaAiReferrals).where(and19(...aiConditions, eq26(gaAiReferrals.sourceDimension, "session"))).groupBy(gaAiReferrals.channelGroup).all();
23757
+ }).from(gaAiReferrals).where(and20(...aiConditions, eq26(gaAiReferrals.sourceDimension, "session"))).groupBy(gaAiReferrals.channelGroup).all();
23720
23758
  const aiSessionsByChannelGroup = /* @__PURE__ */ new Map();
23721
23759
  let aiBySessionUsers = 0;
23722
23760
  for (const row of aiBySessionRows) {
@@ -23730,11 +23768,11 @@ async function ga4Routes(app, opts) {
23730
23768
  channelGroup: gaSocialReferrals.channelGroup,
23731
23769
  sessions: sql10`SUM(${gaSocialReferrals.sessions})`,
23732
23770
  users: sql10`SUM(${gaSocialReferrals.users})`
23733
- }).from(gaSocialReferrals).where(and19(...socialConditions)).groupBy(gaSocialReferrals.source, gaSocialReferrals.medium, gaSocialReferrals.channelGroup).orderBy(sql10`SUM(${gaSocialReferrals.sessions}) DESC`).all();
23771
+ }).from(gaSocialReferrals).where(and20(...socialConditions)).groupBy(gaSocialReferrals.source, gaSocialReferrals.medium, gaSocialReferrals.channelGroup).orderBy(sql10`SUM(${gaSocialReferrals.sessions}) DESC`).all();
23734
23772
  const socialTotals = app.db.select({
23735
23773
  sessions: sql10`SUM(${gaSocialReferrals.sessions})`,
23736
23774
  users: sql10`SUM(${gaSocialReferrals.users})`
23737
- }).from(gaSocialReferrals).where(and19(...socialConditions)).get();
23775
+ }).from(gaSocialReferrals).where(and20(...socialConditions)).get();
23738
23776
  const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq26(gaTrafficSummaries.projectId, project.id)).orderBy(desc13(gaTrafficSummaries.syncedAt)).limit(1).get();
23739
23777
  const total = summaryRow?.totalSessions ?? 0;
23740
23778
  const totalDirectSessions = directTotalRow?.totalDirectSessions ?? 0;
@@ -23825,7 +23863,7 @@ async function ga4Routes(app, opts) {
23825
23863
  sourceDimension: gaAiReferrals.sourceDimension,
23826
23864
  sessions: sql10`SUM(${gaAiReferrals.sessions})`,
23827
23865
  users: sql10`SUM(${gaAiReferrals.users})`
23828
- }).from(gaAiReferrals).where(and19(...conditions)).groupBy(
23866
+ }).from(gaAiReferrals).where(and20(...conditions)).groupBy(
23829
23867
  gaAiReferrals.date,
23830
23868
  gaAiReferrals.source,
23831
23869
  gaAiReferrals.medium,
@@ -23847,7 +23885,7 @@ async function ga4Routes(app, opts) {
23847
23885
  channelGroup: gaSocialReferrals.channelGroup,
23848
23886
  sessions: gaSocialReferrals.sessions,
23849
23887
  users: gaSocialReferrals.users
23850
- }).from(gaSocialReferrals).where(and19(...conditions)).orderBy(gaSocialReferrals.date).all();
23888
+ }).from(gaSocialReferrals).where(and20(...conditions)).orderBy(gaSocialReferrals.date).all();
23851
23889
  return rows;
23852
23890
  });
23853
23891
  app.get("/projects/:name/ga/social-referral-trend", async (request, _reply) => {
@@ -23860,7 +23898,7 @@ async function ga4Routes(app, opts) {
23860
23898
  d.setDate(d.getDate() - n);
23861
23899
  return fmt(d);
23862
23900
  };
23863
- const sumSocial = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(and19(
23901
+ const sumSocial = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(and20(
23864
23902
  eq26(gaSocialReferrals.projectId, project.id),
23865
23903
  sql10`${gaSocialReferrals.date} >= ${from}`,
23866
23904
  sql10`${gaSocialReferrals.date} < ${to}`
@@ -23873,7 +23911,7 @@ async function ga4Routes(app, opts) {
23873
23911
  const sourceCurrent = app.db.select({
23874
23912
  source: gaSocialReferrals.source,
23875
23913
  sessions: sql10`SUM(${gaSocialReferrals.sessions})`
23876
- }).from(gaSocialReferrals).where(and19(
23914
+ }).from(gaSocialReferrals).where(and20(
23877
23915
  eq26(gaSocialReferrals.projectId, project.id),
23878
23916
  sql10`${gaSocialReferrals.date} >= ${daysAgo(7)}`,
23879
23917
  sql10`${gaSocialReferrals.date} < ${fmt(today)}`
@@ -23881,7 +23919,7 @@ async function ga4Routes(app, opts) {
23881
23919
  const sourcePrev = app.db.select({
23882
23920
  source: gaSocialReferrals.source,
23883
23921
  sessions: sql10`SUM(${gaSocialReferrals.sessions})`
23884
- }).from(gaSocialReferrals).where(and19(
23922
+ }).from(gaSocialReferrals).where(and20(
23885
23923
  eq26(gaSocialReferrals.projectId, project.id),
23886
23924
  sql10`${gaSocialReferrals.date} >= ${daysAgo(14)}`,
23887
23925
  sql10`${gaSocialReferrals.date} < ${daysAgo(7)}`
@@ -23923,16 +23961,16 @@ async function ga4Routes(app, opts) {
23923
23961
  return fmt(d);
23924
23962
  };
23925
23963
  const pct = (cur, prev) => prev === 0 ? null : Math.round((cur - prev) / prev * 100);
23926
- const sumTotal = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)` }).from(gaTrafficSnapshots).where(and19(eq26(gaTrafficSnapshots.projectId, project.id), sql10`${gaTrafficSnapshots.date} >= ${from}`, sql10`${gaTrafficSnapshots.date} < ${to}`)).get();
23927
- const sumOrganic = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)` }).from(gaTrafficSnapshots).where(and19(eq26(gaTrafficSnapshots.projectId, project.id), sql10`${gaTrafficSnapshots.date} >= ${from}`, sql10`${gaTrafficSnapshots.date} < ${to}`)).get();
23928
- const sumDirect = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)` }).from(gaTrafficSnapshots).where(and19(eq26(gaTrafficSnapshots.projectId, project.id), sql10`${gaTrafficSnapshots.date} >= ${from}`, sql10`${gaTrafficSnapshots.date} < ${to}`)).get();
23929
- const sumAi = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and19(
23964
+ const sumTotal = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)` }).from(gaTrafficSnapshots).where(and20(eq26(gaTrafficSnapshots.projectId, project.id), sql10`${gaTrafficSnapshots.date} >= ${from}`, sql10`${gaTrafficSnapshots.date} < ${to}`)).get();
23965
+ const sumOrganic = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)` }).from(gaTrafficSnapshots).where(and20(eq26(gaTrafficSnapshots.projectId, project.id), sql10`${gaTrafficSnapshots.date} >= ${from}`, sql10`${gaTrafficSnapshots.date} < ${to}`)).get();
23966
+ const sumDirect = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaTrafficSnapshots.directSessions}), 0)` }).from(gaTrafficSnapshots).where(and20(eq26(gaTrafficSnapshots.projectId, project.id), sql10`${gaTrafficSnapshots.date} >= ${from}`, sql10`${gaTrafficSnapshots.date} < ${to}`)).get();
23967
+ const sumAi = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and20(
23930
23968
  eq26(gaAiReferrals.projectId, project.id),
23931
23969
  sql10`${gaAiReferrals.date} >= ${from}`,
23932
23970
  sql10`${gaAiReferrals.date} < ${to}`,
23933
23971
  eq26(gaAiReferrals.sourceDimension, "session")
23934
23972
  )).get();
23935
- const sumSocial = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(and19(eq26(gaSocialReferrals.projectId, project.id), sql10`${gaSocialReferrals.date} >= ${from}`, sql10`${gaSocialReferrals.date} < ${to}`)).get();
23973
+ const sumSocial = (from, to) => app.db.select({ sessions: sql10`COALESCE(SUM(${gaSocialReferrals.sessions}), 0)` }).from(gaSocialReferrals).where(and20(eq26(gaSocialReferrals.projectId, project.id), sql10`${gaSocialReferrals.date} >= ${from}`, sql10`${gaSocialReferrals.date} < ${to}`)).get();
23936
23974
  const todayStr = fmt(today);
23937
23975
  const buildTrend = (sum) => {
23938
23976
  const c7 = sum(daysAgo(7), todayStr)?.sessions ?? 0;
@@ -23941,13 +23979,13 @@ async function ga4Routes(app, opts) {
23941
23979
  const p30 = sum(daysAgo(60), daysAgo(30))?.sessions ?? 0;
23942
23980
  return { sessions7d: c7, sessionsPrev7d: p7, trend7dPct: pct(c7, p7), sessions30d: c30, sessionsPrev30d: p30, trend30dPct: pct(c30, p30) };
23943
23981
  };
23944
- const aiSourceCurrent = app.db.select({ source: gaAiReferrals.source, sessions: sql10`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and19(
23982
+ const aiSourceCurrent = app.db.select({ source: gaAiReferrals.source, sessions: sql10`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and20(
23945
23983
  eq26(gaAiReferrals.projectId, project.id),
23946
23984
  sql10`${gaAiReferrals.date} >= ${daysAgo(7)}`,
23947
23985
  sql10`${gaAiReferrals.date} < ${todayStr}`,
23948
23986
  eq26(gaAiReferrals.sourceDimension, "session")
23949
23987
  )).groupBy(gaAiReferrals.source).all();
23950
- const aiSourcePrev = app.db.select({ source: gaAiReferrals.source, sessions: sql10`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and19(
23988
+ const aiSourcePrev = app.db.select({ source: gaAiReferrals.source, sessions: sql10`COALESCE(SUM(${gaAiReferrals.sessions}), 0)` }).from(gaAiReferrals).where(and20(
23951
23989
  eq26(gaAiReferrals.projectId, project.id),
23952
23990
  sql10`${gaAiReferrals.date} >= ${daysAgo(14)}`,
23953
23991
  sql10`${gaAiReferrals.date} < ${daysAgo(7)}`,
@@ -23967,8 +24005,8 @@ async function ga4Routes(app, opts) {
23967
24005
  }
23968
24006
  return mover;
23969
24007
  };
23970
- const socialSourceCurrent = app.db.select({ source: gaSocialReferrals.source, sessions: sql10`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(and19(eq26(gaSocialReferrals.projectId, project.id), sql10`${gaSocialReferrals.date} >= ${daysAgo(7)}`, sql10`${gaSocialReferrals.date} < ${todayStr}`)).groupBy(gaSocialReferrals.source).all();
23971
- const socialSourcePrev = app.db.select({ source: gaSocialReferrals.source, sessions: sql10`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(and19(eq26(gaSocialReferrals.projectId, project.id), sql10`${gaSocialReferrals.date} >= ${daysAgo(14)}`, sql10`${gaSocialReferrals.date} < ${daysAgo(7)}`)).groupBy(gaSocialReferrals.source).all();
24008
+ const socialSourceCurrent = app.db.select({ source: gaSocialReferrals.source, sessions: sql10`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(and20(eq26(gaSocialReferrals.projectId, project.id), sql10`${gaSocialReferrals.date} >= ${daysAgo(7)}`, sql10`${gaSocialReferrals.date} < ${todayStr}`)).groupBy(gaSocialReferrals.source).all();
24009
+ const socialSourcePrev = app.db.select({ source: gaSocialReferrals.source, sessions: sql10`SUM(${gaSocialReferrals.sessions})` }).from(gaSocialReferrals).where(and20(eq26(gaSocialReferrals.projectId, project.id), sql10`${gaSocialReferrals.date} >= ${daysAgo(14)}`, sql10`${gaSocialReferrals.date} < ${daysAgo(7)}`)).groupBy(gaSocialReferrals.source).all();
23972
24010
  return {
23973
24011
  total: buildTrend(sumTotal),
23974
24012
  organic: buildTrend(sumOrganic),
@@ -23990,7 +24028,7 @@ async function ga4Routes(app, opts) {
23990
24028
  sessions: sql10`SUM(${gaTrafficSnapshots.sessions})`,
23991
24029
  organicSessions: sql10`SUM(${gaTrafficSnapshots.organicSessions})`,
23992
24030
  users: sql10`SUM(${gaTrafficSnapshots.users})`
23993
- }).from(gaTrafficSnapshots).where(and19(...conditions)).groupBy(gaTrafficSnapshots.date).orderBy(gaTrafficSnapshots.date).all();
24031
+ }).from(gaTrafficSnapshots).where(and20(...conditions)).groupBy(gaTrafficSnapshots.date).orderBy(gaTrafficSnapshots.date).all();
23994
24032
  return rows.map((r) => ({
23995
24033
  date: r.date,
23996
24034
  sessions: r.sessions ?? 0,
@@ -25654,7 +25692,7 @@ async function wordpressRoutes(app, opts) {
25654
25692
 
25655
25693
  // ../api-routes/src/backlinks.ts
25656
25694
  import crypto23 from "crypto";
25657
- import { and as and21, asc as asc4, desc as desc14, eq as eq27, sql as sql11 } from "drizzle-orm";
25695
+ import { and as and22, asc as asc4, desc as desc14, eq as eq27, sql as sql11 } from "drizzle-orm";
25658
25696
 
25659
25697
  // ../integration-commoncrawl/src/constants.ts
25660
25698
  import os2 from "os";
@@ -26057,7 +26095,7 @@ function pruneCachedRelease(release, opts = {}) {
26057
26095
  }
26058
26096
 
26059
26097
  // ../api-routes/src/backlinks-filter.ts
26060
- import { and as and20, ne as ne3, notLike } from "drizzle-orm";
26098
+ import { and as and21, ne as ne3, notLike } from "drizzle-orm";
26061
26099
  var BACKLINK_FILTER_PATTERNS = [
26062
26100
  "*.google.com",
26063
26101
  "*.googleusercontent.com",
@@ -26080,7 +26118,7 @@ function backlinkCrawlerExclusionClause() {
26080
26118
  conditions.push(ne3(backlinkDomains.linkingDomain, pattern));
26081
26119
  }
26082
26120
  }
26083
- const combined = and20(...conditions);
26121
+ const combined = and21(...conditions);
26084
26122
  if (!combined) throw new Error("BACKLINK_FILTER_PATTERNS is unexpectedly empty");
26085
26123
  return combined;
26086
26124
  }
@@ -26155,7 +26193,7 @@ function latestSummaryForProject(db, projectId, source, release) {
26155
26193
  eq27(backlinkSummaries.source, source)
26156
26194
  ];
26157
26195
  if (release) conditions.push(eq27(backlinkSummaries.release, release));
26158
- return db.select().from(backlinkSummaries).where(and21(...conditions)).orderBy(desc14(backlinkSummaries.queriedAt)).limit(1).get();
26196
+ return db.select().from(backlinkSummaries).where(and22(...conditions)).orderBy(desc14(backlinkSummaries.queriedAt)).limit(1).get();
26159
26197
  }
26160
26198
  function parseExcludeCrawlers(value) {
26161
26199
  if (!value) return false;
@@ -26163,12 +26201,12 @@ function parseExcludeCrawlers(value) {
26163
26201
  return lower === "1" || lower === "true" || lower === "yes";
26164
26202
  }
26165
26203
  function computeFilteredSummary(db, base) {
26166
- const baseDomainCondition = and21(
26204
+ const baseDomainCondition = and22(
26167
26205
  eq27(backlinkDomains.projectId, base.projectId),
26168
26206
  eq27(backlinkDomains.source, base.source),
26169
26207
  eq27(backlinkDomains.release, base.release)
26170
26208
  );
26171
- const filteredCondition = and21(baseDomainCondition, backlinkCrawlerExclusionClause());
26209
+ const filteredCondition = and22(baseDomainCondition, backlinkCrawlerExclusionClause());
26172
26210
  const unfilteredAgg = db.select({
26173
26211
  count: sql11`count(*)`,
26174
26212
  total: sql11`coalesce(sum(${backlinkDomains.numHosts}), 0)`
@@ -26198,10 +26236,10 @@ function computeFilteredSummary(db, base) {
26198
26236
  };
26199
26237
  }
26200
26238
  function buildSourceAvailability(db, projectId, source, connected, excludeCrawlers) {
26201
- const summary = db.select().from(backlinkSummaries).where(and21(eq27(backlinkSummaries.projectId, projectId), eq27(backlinkSummaries.source, source))).orderBy(desc14(backlinkSummaries.queriedAt)).limit(1).get();
26239
+ const summary = db.select().from(backlinkSummaries).where(and22(eq27(backlinkSummaries.projectId, projectId), eq27(backlinkSummaries.source, source))).orderBy(desc14(backlinkSummaries.queriedAt)).limit(1).get();
26202
26240
  let totalLinkingDomains = summary?.totalLinkingDomains ?? 0;
26203
26241
  if (summary && excludeCrawlers) {
26204
- const filtered = db.select({ count: sql11`count(*)` }).from(backlinkDomains).where(and21(
26242
+ const filtered = db.select({ count: sql11`count(*)` }).from(backlinkDomains).where(and22(
26205
26243
  eq27(backlinkDomains.projectId, projectId),
26206
26244
  eq27(backlinkDomains.source, source),
26207
26245
  eq27(backlinkDomains.release, summary.release),
@@ -26384,12 +26422,12 @@ async function backlinksRoutes(app, opts) {
26384
26422
  const limit = Math.min(Math.max(parseInt(request.query.limit ?? "50", 10) || 50, 1), 500);
26385
26423
  const offset = Math.max(parseInt(request.query.offset ?? "0", 10) || 0, 0);
26386
26424
  const excludeCrawlers = parseExcludeCrawlers(request.query.excludeCrawlers);
26387
- const baseDomainCondition = and21(
26425
+ const baseDomainCondition = and22(
26388
26426
  eq27(backlinkDomains.projectId, project.id),
26389
26427
  eq27(backlinkDomains.source, source),
26390
26428
  eq27(backlinkDomains.release, targetRelease)
26391
26429
  );
26392
- const domainCondition = excludeCrawlers ? and21(baseDomainCondition, backlinkCrawlerExclusionClause()) : baseDomainCondition;
26430
+ const domainCondition = excludeCrawlers ? and22(baseDomainCondition, backlinkCrawlerExclusionClause()) : baseDomainCondition;
26393
26431
  const totalRow = app.db.select({ count: sql11`count(*)` }).from(backlinkDomains).where(domainCondition).get();
26394
26432
  const rows = app.db.select({
26395
26433
  linkingDomain: backlinkDomains.linkingDomain,
@@ -26413,7 +26451,7 @@ async function backlinksRoutes(app, opts) {
26413
26451
  async (request, reply) => {
26414
26452
  const project = resolveProject(app.db, request.params.name);
26415
26453
  const source = parseSourceParam(request.query.source);
26416
- const rows = app.db.select().from(backlinkSummaries).where(and21(eq27(backlinkSummaries.projectId, project.id), eq27(backlinkSummaries.source, source))).orderBy(asc4(backlinkSummaries.queriedAt)).all();
26454
+ const rows = app.db.select().from(backlinkSummaries).where(and22(eq27(backlinkSummaries.projectId, project.id), eq27(backlinkSummaries.source, source))).orderBy(asc4(backlinkSummaries.queriedAt)).all();
26417
26455
  const response = rows.map((r) => ({
26418
26456
  release: r.release,
26419
26457
  totalLinkingDomains: r.totalLinkingDomains,
@@ -26469,7 +26507,7 @@ async function backlinksRoutes(app, opts) {
26469
26507
  // ../api-routes/src/traffic.ts
26470
26508
  import crypto25 from "crypto";
26471
26509
  import { Agent as UndiciAgent } from "undici";
26472
- import { and as and22, desc as desc15, eq as eq28, gte as gte4, lte as lte3, sql as sql12 } from "drizzle-orm";
26510
+ import { and as and23, desc as desc15, eq as eq28, gte as gte4, lte as lte3, sql as sql12 } from "drizzle-orm";
26473
26511
 
26474
26512
  // ../integration-cloud-run/src/auth.ts
26475
26513
  import crypto24 from "crypto";
@@ -30328,28 +30366,28 @@ async function runBackfillTask(options) {
30328
30366
  try {
30329
30367
  app.db.transaction((tx) => {
30330
30368
  tx.delete(crawlerEventsHourly).where(
30331
- and22(
30369
+ and23(
30332
30370
  eq28(crawlerEventsHourly.sourceId, sourceRow.id),
30333
30371
  gte4(crawlerEventsHourly.tsHour, windowStartIso),
30334
30372
  lte3(crawlerEventsHourly.tsHour, windowEndIso)
30335
30373
  )
30336
30374
  ).run();
30337
30375
  tx.delete(aiUserFetchEventsHourly).where(
30338
- and22(
30376
+ and23(
30339
30377
  eq28(aiUserFetchEventsHourly.sourceId, sourceRow.id),
30340
30378
  gte4(aiUserFetchEventsHourly.tsHour, windowStartIso),
30341
30379
  lte3(aiUserFetchEventsHourly.tsHour, windowEndIso)
30342
30380
  )
30343
30381
  ).run();
30344
30382
  tx.delete(aiReferralEventsHourly).where(
30345
- and22(
30383
+ and23(
30346
30384
  eq28(aiReferralEventsHourly.sourceId, sourceRow.id),
30347
30385
  gte4(aiReferralEventsHourly.tsHour, windowStartIso),
30348
30386
  lte3(aiReferralEventsHourly.tsHour, windowEndIso)
30349
30387
  )
30350
30388
  ).run();
30351
30389
  tx.delete(rawEventSamples).where(
30352
- and22(
30390
+ and23(
30353
30391
  eq28(rawEventSamples.sourceId, sourceRow.id),
30354
30392
  gte4(rawEventSamples.ts, windowStartIso),
30355
30393
  lte3(rawEventSamples.ts, windowEndIso)
@@ -30732,7 +30770,7 @@ async function trafficRoutes(app, opts) {
30732
30770
  row = tx.select().from(trafficSources).where(eq28(trafficSources.id, newId)).get();
30733
30771
  }
30734
30772
  const existingSchedule = tx.select().from(schedules).where(
30735
- and22(
30773
+ and23(
30736
30774
  eq28(schedules.projectId, project.id),
30737
30775
  eq28(schedules.kind, SchedulableRunKinds["traffic-sync"])
30738
30776
  )
@@ -31454,7 +31492,7 @@ async function trafficRoutes(app, opts) {
31454
31492
  pathNormalized: crawlerEventsHourly.pathNormalized,
31455
31493
  hits: sql12`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
31456
31494
  }).from(crawlerEventsHourly).where(
31457
- and22(
31495
+ and23(
31458
31496
  eq28(crawlerEventsHourly.sourceId, row.id),
31459
31497
  gte4(crawlerEventsHourly.tsHour, since)
31460
31498
  )
@@ -31464,25 +31502,25 @@ async function trafficRoutes(app, opts) {
31464
31502
  );
31465
31503
  const crawlerTotal = crawlerSegments.content + crawlerSegments.sitemap + crawlerSegments.robots + crawlerSegments.asset + crawlerSegments.other;
31466
31504
  const aiUserFetchTotals = app.db.select({ total: sql12`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(
31467
- and22(
31505
+ and23(
31468
31506
  eq28(aiUserFetchEventsHourly.sourceId, row.id),
31469
31507
  gte4(aiUserFetchEventsHourly.tsHour, since)
31470
31508
  )
31471
31509
  ).get();
31472
31510
  const aiTotals = app.db.select({ total: sql12`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
31473
- and22(
31511
+ and23(
31474
31512
  eq28(aiReferralEventsHourly.sourceId, row.id),
31475
31513
  gte4(aiReferralEventsHourly.tsHour, since)
31476
31514
  )
31477
31515
  ).get();
31478
31516
  const sampleTotals = app.db.select({ total: sql12`COUNT(*)` }).from(rawEventSamples).where(
31479
- and22(
31517
+ and23(
31480
31518
  eq28(rawEventSamples.sourceId, row.id),
31481
31519
  gte4(rawEventSamples.ts, since)
31482
31520
  )
31483
31521
  ).get();
31484
31522
  const latestRun = app.db.select().from(runs).where(
31485
- and22(
31523
+ and23(
31486
31524
  eq28(runs.projectId, projectId),
31487
31525
  eq28(runs.kind, RunKinds["traffic-sync"]),
31488
31526
  eq28(runs.sourceId, row.id)
@@ -31516,7 +31554,7 @@ async function trafficRoutes(app, opts) {
31516
31554
  "`advanceToNow` must be `true`. There is no implicit reset."
31517
31555
  );
31518
31556
  }
31519
- const sourceRow = app.db.select().from(trafficSources).where(and22(eq28(trafficSources.projectId, project.id), eq28(trafficSources.id, request.params.id))).get();
31557
+ const sourceRow = app.db.select().from(trafficSources).where(and23(eq28(trafficSources.projectId, project.id), eq28(trafficSources.id, request.params.id))).get();
31520
31558
  if (!sourceRow) {
31521
31559
  throw notFound("traffic source", request.params.id);
31522
31560
  }
@@ -31621,7 +31659,7 @@ async function trafficRoutes(app, opts) {
31621
31659
  lte3(crawlerEventsHourly.tsHour, untilIso)
31622
31660
  ];
31623
31661
  if (sourceIdParam) crawlerFilters.push(eq28(crawlerEventsHourly.sourceId, sourceIdParam));
31624
- const crawlerWhere = and22(...crawlerFilters);
31662
+ const crawlerWhere = and23(...crawlerFilters);
31625
31663
  const pathTotals = app.db.select({
31626
31664
  pathNormalized: crawlerEventsHourly.pathNormalized,
31627
31665
  hits: sql12`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)`
@@ -31653,7 +31691,7 @@ async function trafficRoutes(app, opts) {
31653
31691
  lte3(aiUserFetchEventsHourly.tsHour, untilIso)
31654
31692
  ];
31655
31693
  if (sourceIdParam) userFetchFilters.push(eq28(aiUserFetchEventsHourly.sourceId, sourceIdParam));
31656
- const userFetchWhere = and22(...userFetchFilters);
31694
+ const userFetchWhere = and23(...userFetchFilters);
31657
31695
  const total = app.db.select({ total: sql12`COALESCE(SUM(${aiUserFetchEventsHourly.hits}), 0)` }).from(aiUserFetchEventsHourly).where(userFetchWhere).get();
31658
31696
  aiUserFetchTotal = Number(total?.total ?? 0);
31659
31697
  const rows = app.db.select().from(aiUserFetchEventsHourly).where(userFetchWhere).orderBy(desc15(aiUserFetchEventsHourly.tsHour)).limit(limit).all();
@@ -31678,7 +31716,7 @@ async function trafficRoutes(app, opts) {
31678
31716
  lte3(aiReferralEventsHourly.tsHour, untilIso)
31679
31717
  ];
31680
31718
  if (sourceIdParam) aiFilters.push(eq28(aiReferralEventsHourly.sourceId, sourceIdParam));
31681
- const aiWhere = and22(...aiFilters);
31719
+ const aiWhere = and23(...aiFilters);
31682
31720
  const total = app.db.select({ total: sql12`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(aiWhere).get();
31683
31721
  aiReferralTotal = Number(total?.total ?? 0);
31684
31722
  const rows = app.db.select().from(aiReferralEventsHourly).where(aiWhere).orderBy(desc15(aiReferralEventsHourly.tsHour)).limit(limit).all();
@@ -31885,7 +31923,7 @@ function readInstalledManifest(skillDir) {
31885
31923
  var AGENT_CHECKS = [skillsInstalledCheck, skillsCurrentCheck];
31886
31924
 
31887
31925
  // ../api-routes/src/doctor/checks/backlinks.ts
31888
- import { and as and23, eq as eq29 } from "drizzle-orm";
31926
+ import { and as and24, eq as eq29 } from "drizzle-orm";
31889
31927
  function skippedNoProject() {
31890
31928
  return {
31891
31929
  status: CheckStatuses.skipped,
@@ -31917,7 +31955,7 @@ var BACKLINKS_CHECKS = [
31917
31955
  details: { commoncrawl: ccConnected, bingWebmaster: bingConnected }
31918
31956
  };
31919
31957
  }
31920
- const ccHasData = ccConnected ? !!ctx.db.select({ id: backlinkSummaries.id }).from(backlinkSummaries).where(and23(
31958
+ const ccHasData = ccConnected ? !!ctx.db.select({ id: backlinkSummaries.id }).from(backlinkSummaries).where(and24(
31921
31959
  eq29(backlinkSummaries.projectId, ctx.project.id),
31922
31960
  eq29(backlinkSummaries.source, BacklinkSources.commoncrawl)
31923
31961
  )).limit(1).get() : false;
@@ -32442,7 +32480,7 @@ var ga4ConnectionCheck = {
32442
32480
  var GA_AUTH_CHECKS = [ga4ConnectionCheck];
32443
32481
 
32444
32482
  // ../api-routes/src/doctor/checks/gbp-auth.ts
32445
- import { and as and24, eq as eq32 } from "drizzle-orm";
32483
+ import { and as and25, eq as eq32 } from "drizzle-orm";
32446
32484
  var RECENT_SYNC_WARN_DAYS2 = 7;
32447
32485
  var RECENT_SYNC_FAIL_DAYS2 = 30;
32448
32486
  function skippedNoProject3() {
@@ -32675,7 +32713,7 @@ var recentSyncCheck = {
32675
32713
  title: "GBP recent sync",
32676
32714
  run: (ctx) => {
32677
32715
  if (!ctx.project) return skippedNoProject3();
32678
- const selected = ctx.db.select({ locationName: gbpLocations.locationName, syncedAt: gbpLocations.syncedAt }).from(gbpLocations).where(and24(eq32(gbpLocations.projectId, ctx.project.id), eq32(gbpLocations.selected, true))).all();
32716
+ const selected = ctx.db.select({ locationName: gbpLocations.locationName, syncedAt: gbpLocations.syncedAt }).from(gbpLocations).where(and25(eq32(gbpLocations.projectId, ctx.project.id), eq32(gbpLocations.selected, true))).all();
32679
32717
  if (selected.length === 0) {
32680
32718
  return {
32681
32719
  status: CheckStatuses.skipped,
@@ -33277,7 +33315,7 @@ var RUNTIME_STATE_CHECKS = [
33277
33315
  ];
33278
33316
 
33279
33317
  // ../api-routes/src/doctor/checks/traffic-source.ts
33280
- import { and as and25, eq as eq34, gte as gte5, ne as ne4, sql as sql13 } from "drizzle-orm";
33318
+ import { and as and26, eq as eq34, gte as gte5, ne as ne4, sql as sql13 } from "drizzle-orm";
33281
33319
  var RECENT_DATA_WARN_DAYS = 7;
33282
33320
  var RECENT_DATA_FAIL_DAYS = 30;
33283
33321
  function skippedNoProject5() {
@@ -33291,7 +33329,7 @@ function skippedNoProject5() {
33291
33329
  function loadProbes(ctx) {
33292
33330
  if (!ctx.project) return [];
33293
33331
  const rows = ctx.db.select().from(trafficSources).where(
33294
- and25(
33332
+ and26(
33295
33333
  eq34(trafficSources.projectId, ctx.project.id),
33296
33334
  ne4(trafficSources.status, TrafficSourceStatuses.archived)
33297
33335
  )
@@ -33372,7 +33410,7 @@ var recentDataCheck = {
33372
33410
  const failCutoff = new Date(now.getTime() - RECENT_DATA_FAIL_DAYS * 24 * 60 * 6e4).toISOString();
33373
33411
  const recentCrawlers = Number(
33374
33412
  ctx.db.select({ total: sql13`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
33375
- and25(
33413
+ and26(
33376
33414
  eq34(crawlerEventsHourly.projectId, ctx.project.id),
33377
33415
  gte5(crawlerEventsHourly.tsHour, warnCutoff)
33378
33416
  )
@@ -33380,7 +33418,7 @@ var recentDataCheck = {
33380
33418
  );
33381
33419
  const recentReferrals = Number(
33382
33420
  ctx.db.select({ total: sql13`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
33383
- and25(
33421
+ and26(
33384
33422
  eq34(aiReferralEventsHourly.projectId, ctx.project.id),
33385
33423
  gte5(aiReferralEventsHourly.tsHour, warnCutoff)
33386
33424
  )
@@ -33396,7 +33434,7 @@ var recentDataCheck = {
33396
33434
  }
33397
33435
  const olderCrawlers = Number(
33398
33436
  ctx.db.select({ total: sql13`COALESCE(SUM(${crawlerEventsHourly.hits}), 0)` }).from(crawlerEventsHourly).where(
33399
- and25(
33437
+ and26(
33400
33438
  eq34(crawlerEventsHourly.projectId, ctx.project.id),
33401
33439
  gte5(crawlerEventsHourly.tsHour, failCutoff)
33402
33440
  )
@@ -33404,7 +33442,7 @@ var recentDataCheck = {
33404
33442
  );
33405
33443
  const olderReferrals = Number(
33406
33444
  ctx.db.select({ total: sql13`COALESCE(SUM(${aiReferralEventsHourly.sessionsOrHits}), 0)` }).from(aiReferralEventsHourly).where(
33407
- and25(
33445
+ and26(
33408
33446
  eq34(aiReferralEventsHourly.projectId, ctx.project.id),
33409
33447
  gte5(aiReferralEventsHourly.tsHour, failCutoff)
33410
33448
  )
@@ -33821,7 +33859,7 @@ async function doctorRoutes(app, opts) {
33821
33859
 
33822
33860
  // ../api-routes/src/discovery/routes.ts
33823
33861
  import crypto27 from "crypto";
33824
- import { and as and26, desc as desc16, eq as eq35, gte as gte6, inArray as inArray12, isNull, or as or5 } from "drizzle-orm";
33862
+ import { and as and27, desc as desc16, eq as eq35, gte as gte6, inArray as inArray12, isNull, or as or5 } from "drizzle-orm";
33825
33863
  var MAX_INFLIGHT_DISCOVERY_AGE_MS = 2 * 60 * 60 * 1e3;
33826
33864
  async function discoveryRoutes(app, opts) {
33827
33865
  app.post("/projects/:name/discover/run", async (request, reply) => {
@@ -33855,7 +33893,7 @@ async function discoveryRoutes(app, opts) {
33855
33893
  const now = (/* @__PURE__ */ new Date()).toISOString();
33856
33894
  const ageFloorIso = new Date(Date.now() - MAX_INFLIGHT_DISCOVERY_AGE_MS).toISOString();
33857
33895
  const decision = app.db.transaction((tx) => {
33858
- const existing = tx.select({ id: discoverySessions.id, runId: discoverySessions.runId }).from(discoverySessions).where(and26(
33896
+ const existing = tx.select({ id: discoverySessions.id, runId: discoverySessions.runId }).from(discoverySessions).where(and27(
33859
33897
  eq35(discoverySessions.projectId, project.id),
33860
33898
  eq35(discoverySessions.icpDescription, icpDescription),
33861
33899
  // Buyer is part of session identity: it changes the seed prompt's
@@ -34501,7 +34539,7 @@ function dedupeStrings(input) {
34501
34539
 
34502
34540
  // ../api-routes/src/technical-aeo.ts
34503
34541
  import crypto29 from "crypto";
34504
- import { and as and27, asc as asc5, count, desc as desc17, eq as eq37, inArray as inArray13 } from "drizzle-orm";
34542
+ import { and as and28, asc as asc5, count, desc as desc17, eq as eq37, inArray as inArray13 } from "drizzle-orm";
34505
34543
  var SURFACEABLE_STATUSES = [RunStatuses.completed, RunStatuses.partial];
34506
34544
  function emptyScore(projectName) {
34507
34545
  return {
@@ -34533,7 +34571,7 @@ function parsePositiveInt(value, fallback, max) {
34533
34571
  async function technicalAeoRoutes(app, opts) {
34534
34572
  app.get("/projects/:name/technical-aeo", async (request) => {
34535
34573
  const project = resolveProject(app.db, request.params.name);
34536
- const rows = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq37(siteAuditSnapshots.runId, runs.id)).where(and27(
34574
+ const rows = app.db.select({ snap: siteAuditSnapshots, runStatus: runs.status }).from(siteAuditSnapshots).innerJoin(runs, eq37(siteAuditSnapshots.runId, runs.id)).where(and28(
34537
34575
  eq37(siteAuditSnapshots.projectId, project.id),
34538
34576
  eq37(runs.kind, RunKinds["site-audit"]),
34539
34577
  inArray13(runs.status, SURFACEABLE_STATUSES),
@@ -34568,7 +34606,7 @@ async function technicalAeoRoutes(app, opts) {
34568
34606
  });
34569
34607
  app.get("/projects/:name/technical-aeo/pages", async (request) => {
34570
34608
  const project = resolveProject(app.db, request.params.name);
34571
- const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq37(siteAuditSnapshots.runId, runs.id)).where(and27(
34609
+ const latest = app.db.select({ runId: siteAuditSnapshots.runId, auditedAt: siteAuditSnapshots.auditedAt }).from(siteAuditSnapshots).innerJoin(runs, eq37(siteAuditSnapshots.runId, runs.id)).where(and28(
34572
34610
  eq37(siteAuditSnapshots.projectId, project.id),
34573
34611
  eq37(runs.kind, RunKinds["site-audit"]),
34574
34612
  inArray13(runs.status, SURFACEABLE_STATUSES),
@@ -34580,7 +34618,7 @@ async function technicalAeoRoutes(app, opts) {
34580
34618
  const statusFilter = request.query.status === "success" || request.query.status === "error" ? request.query.status : null;
34581
34619
  const conds = [eq37(siteAuditPages.runId, latest.runId)];
34582
34620
  if (statusFilter) conds.push(eq37(siteAuditPages.status, statusFilter));
34583
- const where = and27(...conds);
34621
+ const where = and28(...conds);
34584
34622
  const totalRow = app.db.select({ value: count() }).from(siteAuditPages).where(where).get();
34585
34623
  const total = totalRow?.value ?? 0;
34586
34624
  const limit = parsePositiveInt(request.query.limit, 100, 500);
@@ -34604,7 +34642,7 @@ async function technicalAeoRoutes(app, opts) {
34604
34642
  auditedAt: siteAuditSnapshots.auditedAt,
34605
34643
  aggregateScore: siteAuditSnapshots.aggregateScore,
34606
34644
  pagesAudited: siteAuditSnapshots.pagesAudited
34607
- }).from(siteAuditSnapshots).innerJoin(runs, eq37(siteAuditSnapshots.runId, runs.id)).where(and27(
34645
+ }).from(siteAuditSnapshots).innerJoin(runs, eq37(siteAuditSnapshots.runId, runs.id)).where(and28(
34608
34646
  eq37(siteAuditSnapshots.projectId, project.id),
34609
34647
  eq37(runs.kind, RunKinds["site-audit"]),
34610
34648
  inArray13(runs.status, SURFACEABLE_STATUSES),
@@ -34618,7 +34656,7 @@ async function technicalAeoRoutes(app, opts) {
34618
34656
  if (!parsed.success) {
34619
34657
  throw validationError(parsed.error.issues[0]?.message ?? "Invalid site-audit request");
34620
34658
  }
34621
- const existing = app.db.select({ id: runs.id, status: runs.status }).from(runs).where(and27(
34659
+ const existing = app.db.select({ id: runs.id, status: runs.status }).from(runs).where(and28(
34622
34660
  eq37(runs.projectId, project.id),
34623
34661
  eq37(runs.kind, RunKinds["site-audit"]),
34624
34662
  inArray13(runs.status, [RunStatuses.queued, RunStatuses.running])
@@ -35211,7 +35249,7 @@ var IntelligenceService = class {
35211
35249
  */
35212
35250
  analyzeAndPersist(runId, projectId) {
35213
35251
  const recentRuns = this.db.select().from(runs).where(
35214
- and28(
35252
+ and29(
35215
35253
  eq38(runs.projectId, projectId),
35216
35254
  or6(eq38(runs.status, "completed"), eq38(runs.status, "partial")),
35217
35255
  // Defensive: RunCoordinator already skips probes before this is
@@ -35303,7 +35341,7 @@ var IntelligenceService = class {
35303
35341
  }
35304
35342
  const windowStart = runRow.startedAt ?? runRow.createdAt;
35305
35343
  const windowEnd = runRow.finishedAt ?? (/* @__PURE__ */ new Date()).toISOString();
35306
- const selected = this.db.select().from(gbpLocations).where(and28(
35344
+ const selected = this.db.select().from(gbpLocations).where(and29(
35307
35345
  eq38(gbpLocations.projectId, projectId),
35308
35346
  eq38(gbpLocations.selected, true),
35309
35347
  gte7(gbpLocations.syncedAt, windowStart),
@@ -35340,12 +35378,12 @@ var IntelligenceService = class {
35340
35378
  }
35341
35379
  /** Build the per-location signal bundle the GBP analyzer consumes. */
35342
35380
  buildGbpLocationSignals(projectId, locationName, displayName, fallbackDate) {
35343
- const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and28(eq38(gbpDailyMetrics.projectId, projectId), eq38(gbpDailyMetrics.locationName, locationName))).all();
35344
- const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and28(eq38(gbpPlaceActions.projectId, projectId), eq38(gbpPlaceActions.locationName, locationName))).all();
35345
- const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and28(eq38(gbpLodgingSnapshots.projectId, projectId), eq38(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc18(gbpLodgingSnapshots.syncedAt)).limit(1).get();
35346
- const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and28(eq38(gbpLocations.projectId, projectId), eq38(gbpLocations.locationName, locationName))).get();
35381
+ const metricRows = this.db.select({ metric: gbpDailyMetrics.metric, date: gbpDailyMetrics.date, value: gbpDailyMetrics.value }).from(gbpDailyMetrics).where(and29(eq38(gbpDailyMetrics.projectId, projectId), eq38(gbpDailyMetrics.locationName, locationName))).all();
35382
+ const placeActionRows = this.db.select({ placeActionType: gbpPlaceActions.placeActionType, providerType: gbpPlaceActions.providerType }).from(gbpPlaceActions).where(and29(eq38(gbpPlaceActions.projectId, projectId), eq38(gbpPlaceActions.locationName, locationName))).all();
35383
+ const lodgingRow = this.db.select({ populatedGroupCount: gbpLodgingSnapshots.populatedGroupCount }).from(gbpLodgingSnapshots).where(and29(eq38(gbpLodgingSnapshots.projectId, projectId), eq38(gbpLodgingSnapshots.locationName, locationName))).orderBy(desc18(gbpLodgingSnapshots.syncedAt)).limit(1).get();
35384
+ const ownerRow = this.db.select({ description: gbpLocations.description }).from(gbpLocations).where(and29(eq38(gbpLocations.projectId, projectId), eq38(gbpLocations.locationName, locationName))).get();
35347
35385
  const descriptionMissing = !(ownerRow?.description ?? "").trim();
35348
- const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and28(eq38(gbpPlaceDetails.projectId, projectId), eq38(gbpPlaceDetails.locationName, locationName))).orderBy(desc18(gbpPlaceDetails.syncedAt)).limit(1).get();
35386
+ const placeRow = this.db.select({ attributes: gbpPlaceDetails.attributes }).from(gbpPlaceDetails).where(and29(eq38(gbpPlaceDetails.projectId, projectId), eq38(gbpPlaceDetails.locationName, locationName))).orderBy(desc18(gbpPlaceDetails.syncedAt)).limit(1).get();
35349
35387
  const placesAmenities = placeRow ? extractPlaceAmenities(placeRow.attributes) : [];
35350
35388
  const summary = buildGbpSummary({
35351
35389
  locationName,
@@ -35381,7 +35419,7 @@ var IntelligenceService = class {
35381
35419
  /** Build the month-over-month keyword series for a location from the
35382
35420
  * accumulating gbp_keyword_monthly table (latest complete month vs prior). */
35383
35421
  buildGbpKeywordTrend(projectId, locationName) {
35384
- const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(and28(eq38(gbpKeywordMonthly.projectId, projectId), eq38(gbpKeywordMonthly.locationName, locationName))).all();
35422
+ const rows = this.db.select({ month: gbpKeywordMonthly.month, keyword: gbpKeywordMonthly.keyword, valueCount: gbpKeywordMonthly.valueCount }).from(gbpKeywordMonthly).where(and29(eq38(gbpKeywordMonthly.projectId, projectId), eq38(gbpKeywordMonthly.locationName, locationName))).all();
35385
35423
  if (rows.length === 0) return { recentMonth: null, priorMonth: null, points: [] };
35386
35424
  const months = [...new Set(rows.map((r) => r.month))].sort().reverse();
35387
35425
  const recentMonth = months[0] ?? null;
@@ -35412,7 +35450,7 @@ var IntelligenceService = class {
35412
35450
  */
35413
35451
  persistGbpInsights(runId, projectId, gbpInsights, coveredLocationNames) {
35414
35452
  const covered = new Set(coveredLocationNames);
35415
- const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and28(eq38(insights.projectId, projectId), eq38(insights.provider, GBP_INSIGHT_PROVIDER))).all();
35453
+ const existing = this.db.select({ id: insights.id, dismissed: insights.dismissed }).from(insights).where(and29(eq38(insights.projectId, projectId), eq38(insights.provider, GBP_INSIGHT_PROVIDER))).all();
35416
35454
  const staleIds = [];
35417
35455
  const dismissedSlots = /* @__PURE__ */ new Set();
35418
35456
  for (const row of existing) {
@@ -35514,7 +35552,7 @@ var IntelligenceService = class {
35514
35552
  sinceTimestamp = parsed;
35515
35553
  }
35516
35554
  const allRuns = this.db.select().from(runs).where(
35517
- and28(
35555
+ and29(
35518
35556
  eq38(runs.projectId, project.id),
35519
35557
  or6(eq38(runs.status, "completed"), eq38(runs.status, "partial")),
35520
35558
  // Backfill must not replay probe runs as if they were real sweeps.
@@ -35691,7 +35729,7 @@ var IntelligenceService = class {
35691
35729
  );
35692
35730
  const ROWS_PER_GROUP_BUDGET = Math.max(2, locationCount);
35693
35731
  const recentRunRows = this.db.select({ id: runs.id, createdAt: runs.createdAt }).from(runs).where(
35694
- and28(
35732
+ and29(
35695
35733
  eq38(runs.projectId, projectId),
35696
35734
  eq38(runs.kind, RunKinds["answer-visibility"]),
35697
35735
  or6(eq38(runs.status, "completed"), eq38(runs.status, "partial")),
@@ -35714,7 +35752,7 @@ var IntelligenceService = class {
35714
35752
  const haveHistory = recentRunIds.length > 0;
35715
35753
  const priorRegressionsByPair = /* @__PURE__ */ new Map();
35716
35754
  if (haveHistory) {
35717
- const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and28(eq38(insights.type, "regression"), inArray14(insights.runId, recentRunIds))).all();
35755
+ const priorRows = this.db.select({ query: insights.query, provider: insights.provider, runId: insights.runId }).from(insights).where(and29(eq38(insights.type, "regression"), inArray14(insights.runId, recentRunIds))).all();
35718
35756
  const regressionGroups = /* @__PURE__ */ new Map();
35719
35757
  for (const row of priorRows) {
35720
35758
  if (!row.runId) continue;